Merge "MediaSyncTest: increase ramp up time due to initial latency in AudioTrack." into nyc-dev
diff --git a/OldCtsTestCaseList.mk b/OldCtsTestCaseList.mk
index 8cdbc9f..6b30aee 100644
--- a/OldCtsTestCaseList.mk
+++ b/OldCtsTestCaseList.mk
@@ -87,6 +87,7 @@
     CtsAtraceTestApp \
     CtsCertInstallerApp \
     CtsContactDirectoryProvider \
+    CtsCustomizationApp \
     CtsCppToolsApp \
     CtsDeviceAdminApp23 \
     CtsDeviceAdminApp24 \
@@ -118,7 +119,6 @@
     CtsSomeAccessibilityServices \
     CtsSystemUiDeviceApp \
     CtsThemeDeviceApp \
-    CtsUiAutomatorTestApp \
     CtsUsbSerialTestApp \
     CtsVoiceInteractionService \
     CtsVoiceInteractionApp \
@@ -161,6 +161,7 @@
     CtsCarTestCases \
     CtsContentTestCases \
     CtsDatabaseTestCases \
+    CtsDeviceAdminUninstallerTestCases \
     CtsDisplayTestCases \
     CtsDpiTestCases \
     CtsDpiTestCases2 \
@@ -281,9 +282,6 @@
 cts_native_tests += CtsSimpleperfTestCases
 endif
 
-cts_ui_tests := \
-    CtsUiAutomatorTestCases
-
 cts_device_jars := \
     CtsJdwpApp
 
@@ -300,7 +298,6 @@
 # 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-ui-lib-paths,$(cts_ui_tests)) \
     $(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)) \
@@ -316,7 +313,6 @@
     $(call cts-get-test-xmls,$(cts_test_packages)) \
     $(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
diff --git a/apps/CameraITS/pymodules/its/caps.py b/apps/CameraITS/pymodules/its/caps.py
index dd35ca2..94b12f5 100644
--- a/apps/CameraITS/pymodules/its/caps.py
+++ b/apps/CameraITS/pymodules/its/caps.py
@@ -36,6 +36,19 @@
         print "Test skipped"
         sys.exit(SKIP_RET_CODE)
 
+def full_or_better(props):
+    """Returns whether a device is a FULL or better camera2 device.
+
+    Args:
+        props: Camera properties object.
+
+    Returns:
+        Boolean.
+    """
+    return props.has_key("android.info.supportedHardwareLevel") and \
+            props["android.info.supportedHardwareLevel"] != 2 and \
+            props["android.info.supportedHardwareLevel"] > 1
+
 def level3(props):
     """Returns whether a device is a LEVEL3 capability camera2 device.
 
@@ -107,8 +120,7 @@
         Boolean.
     """
     return    props.has_key("android.request.availableCapabilities") and \
-              1 in props["android.request.availableCapabilities"] \
-           or full(props)
+              1 in props["android.request.availableCapabilities"]
 
 def manual_post_proc(props):
     """Returns whether a device supports MANUAL_POST_PROCESSING capabilities.
@@ -120,8 +132,7 @@
         Boolean.
     """
     return    props.has_key("android.request.availableCapabilities") and \
-              2 in props["android.request.availableCapabilities"] \
-           or full(props)
+              2 in props["android.request.availableCapabilities"]
 
 def raw(props):
     """Returns whether a device supports RAW capabilities.
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index c669540..8dfcc27 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -179,6 +179,11 @@
                 time.sleep(duration)
                 print "Reboot complete"
 
+        # Flush logcat so following code won't be misled by previous
+        # 'ItsService ready' log.
+        _run('%s logcat -c' % (self.adb))
+        time.sleep(1)
+
         # TODO: Figure out why "--user 0" is needed, and fix the problem.
         _run('%s shell am force-stop --user 0 %s' % (self.adb, self.PACKAGE))
         _run(('%s shell am startservice --user 0 -t text/plain '
diff --git a/apps/CameraITS/tests/scene0/test_metadata.py b/apps/CameraITS/tests/scene0/test_metadata.py
index 44663bb..2914493 100644
--- a/apps/CameraITS/tests/scene0/test_metadata.py
+++ b/apps/CameraITS/tests/scene0/test_metadata.py
@@ -36,7 +36,7 @@
     print "Hardware level"
     print "  Legacy:", its.caps.legacy(props)
     print "  Limited:", its.caps.limited(props)
-    print "  Full:", its.caps.full(props)
+    print "  Full or better:", its.caps.full_or_better(props)
     print "Capabilities"
     print "  Manual sensor:", its.caps.manual_sensor(props)
     print "  Manual post-proc:", its.caps.manual_post_proc(props)
@@ -46,7 +46,7 @@
     # Test: hardware level should be a valid value.
     check('props.has_key("android.info.supportedHardwareLevel")')
     check('props["android.info.supportedHardwareLevel"] is not None')
-    check('props["android.info.supportedHardwareLevel"] in [0,1,2]')
+    check('props["android.info.supportedHardwareLevel"] in [0,1,2,3]')
     full = getval('props["android.info.supportedHardwareLevel"]') == 1
     manual_sensor = its.caps.manual_sensor(props)
 
diff --git a/apps/CameraITS/tests/scene1/test_latching.py b/apps/CameraITS/tests/scene1/test_latching.py
index 176f01b..a7da421 100644
--- a/apps/CameraITS/tests/scene1/test_latching.py
+++ b/apps/CameraITS/tests/scene1/test_latching.py
@@ -33,8 +33,7 @@
 
     with its.device.ItsSession() as cam:
         props = cam.get_camera_properties()
-        its.caps.skip_unless(its.caps.full(props) and
-                             its.caps.per_frame_control(props))
+        its.caps.skip_unless(its.caps.full_or_better(props))
 
         _,fmt = its.objects.get_fastest_manual_capture_settings(props)
         e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 7af3974..26b0621 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1752,8 +1752,9 @@
         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
+        - Device administrators outside of the work profile (if any) appear in the list, and the managed profile administrators are badged correctly.\n
         - \"CTS Verifier\" exists under the Work category, and is activated.\n
+        - Attempting to uncheck badged \"CTS Verifier\" shows an alert dialog informing you that this admin can be deactivated only if you remove the managed profile.\n
         \n
         Use the Back button to return to this page.
     </string>
@@ -2069,6 +2070,16 @@
             Also, check that if you can download files from your phone to the desktop computer. The test is successful if the files from your phone are not and cannot be downloaded through USB.\n
             Please mark the test accordingly.
     </string>
+    <string name="device_owner_set_user_icon">Setting the user icon</string>
+    <string name="device_owner_set_user_icon_instruction">
+        This test verifies that the user icon can be set.\n
+        1. Press the set user icon button.\n
+        2. Press the go button to go to Settings.\n
+        3a. If there is a \"users\" section in Settings, check that the icon of the user \"owner\" is the CtsVerifier one and mark this test accordingly.\n
+        3b. If there is no \"users\" section, mark this test as passed.\n
+    </string>
+    <string name="device_owner_set_user_icon_button">Set user icon</string>
+
     <string name="profile_owner_permission_lockdown_test_info">
         <b>
         Before proceeding, check if com.android.cts.permissionapp (aka CtsPermissionApp) is installed in work profile by going to Settings &gt; Apps. If not, please install the app before proceeding.\n\n
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
index 4f26b9c..4e39720 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
@@ -21,6 +21,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.BitmapFactory;
 import android.os.Bundle;
 import android.os.UserManager;
 import android.util.Log;
@@ -55,6 +56,7 @@
     public static final String COMMAND_PROFILE_OWNER_CLEAR_POLICIES = "po-clear-policies";
     public static final String COMMAND_REMOVE_DEVICE_OWNER = "remove-device-owner";
     public static final String COMMAND_REQUEST_BUGREPORT = "request-bugreport";
+    public static final String COMMAND_SET_USER_ICON = "set-user-icon";
 
     public static final String EXTRA_USER_RESTRICTION =
             "com.android.cts.verifier.managedprovisioning.extra.USER_RESTRICTION";
@@ -161,6 +163,13 @@
                     }
                     clearProfileOwnerRelatedPolicies();
                 } break;
+                case COMMAND_SET_USER_ICON: {
+                    if (!mDpm.isDeviceOwnerApp(getPackageName())) {
+                        return;
+                    }
+                    mDpm.setUserIcon(mAdmin, BitmapFactory.decodeResource(getResources(),
+                            com.android.cts.verifier.R.drawable.icon));
+                } break;
             }
         } catch (Exception e) {
             Log.e(TAG, "Failed to execute command: " + intent, e);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
index cbb050c..163f2fe 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/DeviceOwnerPositiveTestActivity.java
@@ -66,8 +66,7 @@
     private static final String DISALLOW_CONFIG_WIFI_ID = "DISALLOW_CONFIG_WIFI";
     private static final String DISALLOW_CONFIG_VPN_ID = "DISALLOW_CONFIG_VPN";
     private static final String DISALLOW_USB_FILE_TRANSFER_ID = "DISALLOW_USB_FILE_TRANSFER";
-    //TODO(rgl): This symbol should be available in android.provider.settings
-    private static final String ACTION_VPN_SETTINGS = "android.net.vpn.SETTINGS";
+    private static final String SET_USER_ICON_TEST_ID = "SET_USER_ICON";
     private static final String DISALLOW_DATA_ROAMING_ID = "DISALLOW_DATA_ROAMING";
     private static final String POLICY_TRANSPARENCY_TEST_ID = "POLICY_TRANSPARENCY";
     private static final String REMOVE_DEVICE_OWNER_TEST_ID = "REMOVE_DEVICE_OWNER";
@@ -182,7 +181,7 @@
                                         UserManager.DISALLOW_CONFIG_VPN)),
                         new ButtonInfo(
                                 R.string.device_owner_settings_go,
-                                new Intent(ACTION_VPN_SETTINGS)),
+                                new Intent(Settings.ACTION_VPN_SETTINGS)),
                         new ButtonInfo(
                                 R.string.device_owner_vpn_test,
                                 new Intent(this, VpnTestActivity.class))}));
@@ -258,6 +257,17 @@
                                         CommandReceiverActivity.COMMAND_SET_KEYGUARD_DISABLED,
                                                 false))}));
 
+        adapter.add(createInteractiveTestItem(this, SET_USER_ICON_TEST_ID,
+                R.string.device_owner_set_user_icon,
+                R.string.device_owner_set_user_icon_instruction,
+                new ButtonInfo[] {
+                        new ButtonInfo(
+                                R.string.device_owner_set_user_icon_button,
+                                createSetUserIconIntent()),
+                        new ButtonInfo(
+                                R.string.device_owner_settings_go,
+                                new Intent(Settings.ACTION_SETTINGS))}));
+
         // setPermissionGrantState
         adapter.add(createTestItem(this, CHECK_PERMISSION_LOCKDOWN_TEST_ID,
                 R.string.device_profile_owner_permission_lockdown_test,
@@ -309,4 +319,10 @@
                 .putExtra(CommandReceiverActivity.EXTRA_USER_RESTRICTION, restriction)
                 .putExtra(CommandReceiverActivity.EXTRA_ENFORCED, true);
     }
-}
\ No newline at end of file
+
+    private Intent createSetUserIconIntent() {
+        return new Intent(this, CommandReceiverActivity.class)
+                .putExtra(CommandReceiverActivity.EXTRA_COMMAND,
+                        CommandReceiverActivity.COMMAND_SET_USER_ICON);
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
index 0cf58f7..af71ebe 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
@@ -77,6 +77,7 @@
                 new Intent(Settings.ACTION_WIRELESS_SETTINGS),
                 new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD),
                 new Intent("android.net.vpn.SETTINGS"),
+                new Intent(Settings.ACTION_VPN_SETTINGS),
                 new Intent("android.settings.ACCOUNT_SYNC_SETTINGS"),
                 new Intent(Settings.ACTION_BATTERY_SAVER_SETTINGS),
                 new Intent("android.settings.LICENSE"),
diff --git a/build/config.mk b/build/config.mk
index 6a70618..306c5fd 100644
--- a/build/config.mk
+++ b/build/config.mk
@@ -46,7 +46,6 @@
 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
 BUILD_CTS_SUPPORT_PACKAGE := cts/build/support_package.mk
 BUILD_CTS_MODULE_TEST_CONFIG := cts/build/module_test_config.mk
diff --git a/build/test_uiautomator.mk b/build/test_uiautomator.mk
deleted file mode 100644
index a191d72..0000000
--- a/build/test_uiautomator.mk
+++ /dev/null
@@ -1,60 +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.
-
-#
-# Builds a uiautomator library and defines a rule to generate the associated test
-# package XML needed by CTS.
-#
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_JAVA_LIBRARY)
-include $(BUILD_CTS_MODULE_TEST_CONFIG)
-
-cts_library_jar := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).jar
-$(cts_library_jar): $(LOCAL_BUILT_MODULE)
-	$(call copy-file-to-target)
-
-cts_src_dirs := $(LOCAL_PATH)/src
-cts_src_dirs += $(sort $(dir $(LOCAL_GENERATED_SOURCES)))
-cts_src_dirs := $(addprefix -s , $(cts_src_dirs))
-
-cts_library_xml := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).xml
-$(cts_library_xml): PRIVATE_SRC_DIRS := $(cts_src_dirs)
-$(cts_library_xml): PRIVATE_TEST_APP_PACKAGE := $(LOCAL_CTS_TEST_APP_PACKAGE)
-$(cts_library_xml): PRIVATE_TEST_PACKAGE := $(LOCAL_CTS_TEST_PACKAGE)
-$(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): $(cts_library_jar)
-$(cts_library_xml): $(cts_module_test_config)
-$(cts_library_xml): $(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) $(PRIVATE_SRC_DIRS) \
-						-d $(CTS_JAVA_TEST_SCANNER_DOCLET) | \
-			$(CTS_XML_GENERATOR) -t uiAutomator \
-						-i $(PRIVATE_TEST_APK) \
-						-j $(PRIVATE_JAR_PATH) \
-						-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 $@
-
-# Have the module name depend on the cts files; so the cts files get generated when you run mm/mmm/mma/mmma.
-$(my_register_name) : $(cts_library_jar) $(cts_library_xml) $(cts_module_test_config)
diff --git a/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ScreenLockHelper.java b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ScreenLockHelper.java
index d2380af..385f22f 100644
--- a/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ScreenLockHelper.java
+++ b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/ScreenLockHelper.java
@@ -18,6 +18,7 @@
 
 import android.app.KeyguardManager;
 import android.content.Context;
+import android.os.Build;
 
 /**
  * ScreenLockHelper is used to check whether the device is protected by a locked screen.
@@ -29,6 +30,9 @@
      * is no way to programmatically distinguish between the two.
      */
     public static boolean isDeviceSecure(Context context) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+            return true; // KeyguardManager.isDeviceSecure() added in M, skip this check
+        }
         KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
         return km.isDeviceSecure();
     }
diff --git a/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/WifiHelper.java b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/WifiHelper.java
index 70a4b03..ef63544 100644
--- a/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/WifiHelper.java
+++ b/common/device-side/preconditions/src/com/android/compatibility/common/preconditions/WifiHelper.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
+import android.os.Build;
 
 /**
  * WifiHelper is used to check whether the device is connected to WiFi.
@@ -27,6 +28,9 @@
 public class WifiHelper {
 
     public static boolean isWifiConnected(Context context) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+            return true; // ConnectivityManager.getNetworkInfo() added in LOLLIPOP, skip this check
+        }
         ConnectivityManager cm = (ConnectivityManager)
                 context.getSystemService(Context.CONNECTIVITY_SERVICE);
         NetworkInfo wifiNetworkInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java
index a7a1e4a..ee6d7db 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildProvider.java
@@ -26,12 +26,16 @@
 import com.android.tradefed.config.OptionClass;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
+
+import java.util.regex.Pattern;
 /**
  * A simple {@link IBuildProvider} that uses a pre-existing Compatibility install.
  */
 @OptionClass(alias="compatibility-build-provider")
 public class CompatibilityBuildProvider implements IDeviceBuildProvider {
 
+    private static final Pattern RELEASE_BUILD = Pattern.compile("^[A-Z]{3}\\d{2}[A-Z]{0,1}$");
+
     @Option(name="branch", description="build branch name to supply.")
     private String mBranch = null;
 
@@ -84,7 +88,10 @@
             }
             info.setBuildBranch(mBranch);
             info.setBuildFlavor(buildFlavor);
-            info.addBuildAttribute("build_alias", device.getBuildAlias());
+            String buildAlias = device.getBuildAlias();
+            if (RELEASE_BUILD.matcher(buildAlias).matches()) {
+                info.addBuildAttribute("build_alias", buildAlias);
+            }
             return info;
         }
     }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
index 069b61e..3a222a2 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
@@ -57,7 +57,7 @@
 
     /**
      * Hard coded list of modules to be excluded from manual module sharding
-     * @see {@link #splitModules(int)}
+     * @see #splitModules(int)
      */
     private final static Set<String> MODULE_SPLIT_EXCLUSIONS = new HashSet<>();
     static {
@@ -84,7 +84,7 @@
         trie.put(new Runnable() {
             @Override
             public void run() {
-                // TODO(stuartscott)" listPlans(buildHelper);
+                listPlans();
             }
         }, LIST_PATTERN, "p(?:lans)?");
         trie.put(new Runnable() {
@@ -209,6 +209,11 @@
         }
     }
 
+    private void listPlans() {
+        printLine("Available plans include:");
+        ConfigurationFactory.getInstance().printHelp(System.out);
+    }
+
     private void splitModules(int shards) {
         File[] files = null;
         try {
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
index 2d76cdb..14f3812 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
@@ -69,7 +69,8 @@
        ITestSummaryListener {
 
     private static final String RESULT_KEY = "COMPATIBILITY_TEST_RESULT";
-    private static final String BUILD_INFO = "build_";
+    private static final String CTS_PREFIX = "cts:";
+    private static final String BUILD_INFO = CTS_PREFIX + "build_";
     private static final String[] RESULT_RESOURCES = {
         "compatibility_result.css",
         "compatibility_result.xsd",
@@ -273,7 +274,7 @@
         for (Entry<String, String> entry : mBuild.getBuildAttributes().entrySet()) {
             String key = entry.getKey();
             if (key.startsWith(BUILD_INFO)) {
-                mResult.addBuildInfo(key, entry.getValue());
+                mResult.addBuildInfo(key.substring(CTS_PREFIX.length()), entry.getValue());
             }
         }
         mCurrentModuleResult.addRuntime(elapsedTime);
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
index a0b8faf..651dc7b 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
@@ -40,26 +40,26 @@
 
     private static final Map<String, String> BUILD_KEYS = new HashMap<>();
     static {
-        BUILD_KEYS.put("build_id", "ro.build.id");
-        BUILD_KEYS.put("build_product", "ro.product.name");
-        BUILD_KEYS.put("build_device", "ro.product.device");
-        BUILD_KEYS.put("build_board", "ro.product.board");
-        BUILD_KEYS.put("build_manufacturer", "ro.product.manufacturer");
-        BUILD_KEYS.put("build_brand", "ro.product.brand");
-        BUILD_KEYS.put("build_model", "ro.product.model");
-        BUILD_KEYS.put("build_type", "ro.build.type");
-        BUILD_KEYS.put("build_tags", "ro.build.tags");
-        BUILD_KEYS.put("build_fingerprint", "ro.build.fingerprint");
-        BUILD_KEYS.put("build_abi", "ro.product.cpu.abi");
-        BUILD_KEYS.put("build_abi2", "ro.product.cpu.abi2");
-        BUILD_KEYS.put("build_abis", "ro.product.cpu.abilist");
-        BUILD_KEYS.put("build_abis_32", "ro.product.cpu.abilist32");
-        BUILD_KEYS.put("build_abis_64", "ro.product.cpu.abilist64");
-        BUILD_KEYS.put("build_serial", "ro.serialno");
-        BUILD_KEYS.put("build_version_release", "ro.build.version.release");
-        BUILD_KEYS.put("build_version_sdk", "ro.build.version.sdk");
-        BUILD_KEYS.put("build_version_base_os", "ro.build.version.base_os");
-        BUILD_KEYS.put("build_version_security_patch", "ro.build.version.security_patch");
+        BUILD_KEYS.put("cts:build_id", "ro.build.id");
+        BUILD_KEYS.put("cts:build_product", "ro.product.name");
+        BUILD_KEYS.put("cts:build_device", "ro.product.device");
+        BUILD_KEYS.put("cts:build_board", "ro.product.board");
+        BUILD_KEYS.put("cts:build_manufacturer", "ro.product.manufacturer");
+        BUILD_KEYS.put("cts:build_brand", "ro.product.brand");
+        BUILD_KEYS.put("cts:build_model", "ro.product.model");
+        BUILD_KEYS.put("cts:build_type", "ro.build.type");
+        BUILD_KEYS.put("cts:build_tags", "ro.build.tags");
+        BUILD_KEYS.put("cts:build_fingerprint", "ro.build.fingerprint");
+        BUILD_KEYS.put("cts:build_abi", "ro.product.cpu.abi");
+        BUILD_KEYS.put("cts:build_abi2", "ro.product.cpu.abi2");
+        BUILD_KEYS.put("cts:build_abis", "ro.product.cpu.abilist");
+        BUILD_KEYS.put("cts:build_abis_32", "ro.product.cpu.abilist32");
+        BUILD_KEYS.put("cts:build_abis_64", "ro.product.cpu.abilist64");
+        BUILD_KEYS.put("cts:build_serial", "ro.serialno");
+        BUILD_KEYS.put("cts:build_version_release", "ro.build.version.release");
+        BUILD_KEYS.put("cts:build_version_sdk", "ro.build.version.sdk");
+        BUILD_KEYS.put("cts:build_version_base_os", "ro.build.version.base_os");
+        BUILD_KEYS.put("cts:build_version_security_patch", "ro.build.version.security_patch");
     }
 
     @Option(name = CompatibilityTest.SKIP_DEVICE_INFO_OPTION,
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java
index 0336211..a4d35fb 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/ScopedDirectoryAccessClientTest.java
@@ -85,23 +85,31 @@
             openExternalDirectoryInvalidPath(volume, "/../");
             openExternalDirectoryInvalidPath(volume, "/HiddenStuff");
         }
+        openExternalDirectoryInvalidPath(getPrimaryVolume(), DIRECTORY_ROOT);
     }
 
     public void testUserRejects() throws Exception {
         if (!supportedHardware()) return;
 
-        final StorageVolume primaryVolume = getPrimaryVolume();
-
-        // Tests user clicking DENY button, for all valid directories.
-        for (String dir : STANDARD_DIRECTORIES) {
-            final UiAlertDialog dialog = openExternalDirectoryValidPath(primaryVolume, dir);
-            dialog.noButton.click();
+        for (StorageVolume volume : getVolumes()) {
+            // Tests user clicking DENY button, for all valid directories.
+            for (String dir : STANDARD_DIRECTORIES) {
+                userRejectsTest(volume, dir);
+            }
+            if (!volume.isPrimary()) {
+                // Also test root
+                userRejectsTest(volume, DIRECTORY_ROOT);
+            }
+            // Also test user clicking back button - one directory is enough.
+            openExternalDirectoryValidPath(volume, DIRECTORY_PICTURES);
+            mDevice.pressBack();
             assertActivityFailed();
         }
+    }
 
-        // Also test user clicking back button - one directory is enough.
-        openExternalDirectoryValidPath(primaryVolume, DIRECTORY_ROOT);
-        mDevice.pressBack();
+    private void userRejectsTest(StorageVolume volume, String dir) throws Exception {
+        final UiAlertDialog dialog = openExternalDirectoryValidPath(volume, dir);
+        dialog.noButton.click();
         assertActivityFailed();
     }
 
@@ -110,7 +118,9 @@
 
         for (StorageVolume volume : getVolumes()) {
             userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_PICTURES);
-            userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_ROOT);
+            if (!volume.isPrimary()) {
+                userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_ROOT);
+            }
         }
     }
 
@@ -149,7 +159,8 @@
     public void testNotAskedAgainOnRoot() throws Exception {
         if (!supportedHardware()) return;
 
-         for (StorageVolume volume : getVolumes()) {
+        for (StorageVolume volume : getVolumes()) {
+            if (volume.isPrimary()) continue;
             final String volumeDesc = volume.getDescription(getInstrumentation().getContext());
             final Uri grantedRootUri = userAcceptsOpenExternalDirectoryTest(volume, DIRECTORY_ROOT);
 
@@ -176,9 +187,10 @@
     public void testDeniesOnceButAllowsAskingAgain() throws Exception {
         if (!supportedHardware())return;
 
-        final String[] dirs = {DIRECTORY_DCIM, DIRECTORY_ROOT};
+        final String[] dirs = { DIRECTORY_DCIM, DIRECTORY_ROOT };
         for (StorageVolume volume : getVolumes()) {
             for (String dir : dirs) {
+                if (volume.isPrimary() && dir == DIRECTORY_ROOT) continue;
                 // Rejects the first attempt...
                 UiAlertDialog dialog = openExternalDirectoryValidPath(volume, dir);
                 dialog.assertDoNotAskAgainVisibility(false);
@@ -203,6 +215,7 @@
         final String[] dirs = {DIRECTORY_PICTURES, DIRECTORY_ROOT};
         for (StorageVolume volume : getVolumes()) {
             for (String dir : dirs) {
+                if (volume.isPrimary() && dir == DIRECTORY_ROOT) continue;
                 // Rejects the first attempt...
                 UiAlertDialog dialog = openExternalDirectoryValidPath(volume, dir);
                 dialog.assertDoNotAskAgainVisibility(false);
@@ -234,10 +247,16 @@
         final UiAlertDialog dialog = openExternalDirectoryValidPath(volume, directoryName);
         final String message = dialog.messageText.getText();
         Log.v(TAG, "request permission message: " + message);
-        final Context context = getInstrumentation().getTargetContext();
+        final Context context = getInstrumentation().getContext();
         final String appLabel = context.getPackageManager().getApplicationLabel(
                 context.getApplicationInfo()).toString();
         assertContainsRegex("missing app label", appLabel, message);
+        final String volumeLabel = volume.getDescription(context);
+        if (volume.isPrimary()) {
+            assertNotContainsRegex("should not have volume label on primary", volumeLabel, message);
+        } else {
+            assertContainsRegex("missing volume label", volumeLabel, message);
+        }
         if (directoryName != null) {
             assertContainsRegex("missing folder", directoryName, message);
         } else {
@@ -248,13 +267,13 @@
         dialog.yesButton.click();
 
         // ...and get its response.
-        final String volumeDesc = volume.getDescription(getInstrumentation().getContext());
+        final String volumeDesc = volume.getDescription(context);
         final Intent data = assertActivitySucceeded("should have already granted "
                 + "permission to " + volumeDesc + " and " + directoryName);
         final Uri grantedUri = data.getData();
 
         // Test granted permission directly by persisting it...
-        final ContentResolver resolver = getInstrumentation().getContext().getContentResolver();
+        final ContentResolver resolver = context.getContentResolver();
         final int modeFlags = data.getFlags()
                 & (Intent.FLAG_GRANT_READ_URI_PERMISSION
                 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
@@ -283,9 +302,10 @@
         return grantedUri;
     }
 
-    private void openExternalDirectoryInvalidPath(StorageVolume volume, String path) {
-        sendOpenExternalDirectoryIntent(volume, path);
-        assertActivityFailed();
+    private void openExternalDirectoryInvalidPath(StorageVolume volume, String directoryName) {
+        final Intent intent = volume.createAccessIntent(directoryName);
+        assertNull("should not get intent for volume '" + volume + "' and directory '"
+                + directoryName + "'", intent);
     }
 
     private UiAlertDialog openExternalDirectoryValidPath(StorageVolume volume, String path)
@@ -296,6 +316,7 @@
 
     private void sendOpenExternalDirectoryIntent(StorageVolume volume, String directoryName) {
         final Intent intent = volume.createAccessIntent(directoryName);
+        assertNotNull("no intent for '" + volume + "' and directory " + directoryName, intent);
         mActivity.startActivityForResult(intent, REQUEST_CODE);
         mDevice.waitForIdle();
     }
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 abe8bf0..d968863 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
@@ -142,6 +142,15 @@
         return paths;
     }
 
+    public static List<File> getAllPackageSpecificPathsExceptMedia(Context context) {
+        final List<File> paths = new ArrayList<File>();
+        Collections.addAll(paths, context.getExternalCacheDirs());
+        Collections.addAll(paths, context.getExternalFilesDirs(null));
+        Collections.addAll(paths, context.getExternalFilesDirs(Environment.DIRECTORY_PICTURES));
+        Collections.addAll(paths, context.getObbDirs());
+        return paths;
+    }
+
     public static List<File> getAllPackageSpecificPathsExceptObb(Context context) {
         final List<File> paths = new ArrayList<File>();
         Collections.addAll(paths, context.getExternalCacheDirs());
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
index ea6c0ea..0436252 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
@@ -17,6 +17,7 @@
 package com.android.cts.writeexternalstorageapp;
 
 import static android.test.MoreAsserts.assertNotEqual;
+
 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.PACKAGE_NONE;
 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.TAG;
 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirNoWriteAccess;
@@ -24,7 +25,7 @@
 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.assertDirReadWriteAccess;
 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.buildProbeFile;
 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.deleteContents;
-import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificPaths;
+import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getAllPackageSpecificPathsExceptMedia;
 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getMountPaths;
 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getPrimaryPackageSpecificPaths;
 import static com.android.cts.externalstorageapp.CommonExternalStorageTest.getSecondaryPackageSpecificPaths;
@@ -240,10 +241,10 @@
      * Verify that .nomedia is created correctly.
      */
     public void testVerifyNoMediaCreated() throws Exception {
-        for (File file : getAllPackageSpecificPaths(getContext())) {
+        for (File file : getAllPackageSpecificPathsExceptMedia(getContext())) {
             deleteContents(file);
         }
-        final List<File> paths = getAllPackageSpecificPaths(getContext());
+        final List<File> paths = getAllPackageSpecificPathsExceptMedia(getContext());
 
         // Require that .nomedia was created somewhere above each dir
         for (File path : paths) {
diff --git a/hostsidetests/devicepolicy/app/ContactDirectoryProvider/src/com/android/cts/contactdirectoryprovider/DirectoryProvider.java b/hostsidetests/devicepolicy/app/ContactDirectoryProvider/src/com/android/cts/contactdirectoryprovider/DirectoryProvider.java
index f7ed4a8..b57a91a 100644
--- a/hostsidetests/devicepolicy/app/ContactDirectoryProvider/src/com/android/cts/contactdirectoryprovider/DirectoryProvider.java
+++ b/hostsidetests/devicepolicy/app/ContactDirectoryProvider/src/com/android/cts/contactdirectoryprovider/DirectoryProvider.java
@@ -16,6 +16,8 @@
 
 package com.android.cts.contactdirectoryprovider;
 
+import android.accounts.Account;
+import android.accounts.AccountManager;
 import android.content.ContentProvider;
 import android.content.ContentValues;
 import android.content.Context;
@@ -43,8 +45,8 @@
     private static final String CONFIG_NAME = "config";
     private static final String SET_CUSTOM_PREFIX = "set_prefix";
     private static final String AUTHORITY = "com.android.cts.contact.directory.provider";
-    private static final String TEST_ACCOUNT_NAME = "cts@android.com";
-    private static final String TEST_ACCOUNT_TYPE = "com.android.cts";
+    // Same as com.android.cts.managedprofile.AccountAuthenticator.ACCOUNT_TYPE
+    private static final String TEST_ACCOUNT_TYPE = "com.android.cts.test";
     private static final String DEFAULT_DISPLAY_NAME = "Directory";
     private static final String DEFAULT_CONTACT_NAME = "DirectoryContact";
 
@@ -109,24 +111,30 @@
         switch (match) {
             case GAL_DIRECTORIES: {
                 final MatrixCursor cursor = new MatrixCursor(projection);
-                final Object[] row = new Object[projection.length];
-                for (int i = 0; i < projection.length; i++) {
-                    final String column = projection[i];
-                    if (column.equals(Directory.ACCOUNT_NAME)) {
-                        row[i] = TEST_ACCOUNT_NAME;
-                    } else if (column.equals(Directory.ACCOUNT_TYPE)) {
-                        row[i] = TEST_ACCOUNT_TYPE;
-                    } else if (column.equals(Directory.TYPE_RESOURCE_ID)) {
-                        row[i] = R.string.directory_resource_id;
-                    } else if (column.equals(Directory.DISPLAY_NAME)) {
-                        row[i] = prefix + DEFAULT_DISPLAY_NAME;
-                    } else if (column.equals(Directory.EXPORT_SUPPORT)) {
-                        row[i] = Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY;
-                    } else if (column.equals(Directory.SHORTCUT_SUPPORT)) {
-                        row[i] = Directory.SHORTCUT_SUPPORT_NONE;
+                final AccountManager am = getContext().getSystemService(AccountManager.class);
+                Account[] accounts = am.getAccountsByType(TEST_ACCOUNT_TYPE);
+                if (accounts != null) {
+                    for (Account account : accounts) {
+                        final Object[] row = new Object[projection.length];
+                        for (int i = 0; i < projection.length; i++) {
+                            final String column = projection[i];
+                            if (column.equals(Directory.ACCOUNT_NAME)) {
+                                row[i] = account.name;
+                            } else if (column.equals(Directory.ACCOUNT_TYPE)) {
+                                row[i] = TEST_ACCOUNT_TYPE;
+                            } else if (column.equals(Directory.TYPE_RESOURCE_ID)) {
+                                row[i] = R.string.directory_resource_id;
+                            } else if (column.equals(Directory.DISPLAY_NAME)) {
+                                row[i] = prefix + DEFAULT_DISPLAY_NAME;
+                            } else if (column.equals(Directory.EXPORT_SUPPORT)) {
+                                row[i] = Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY;
+                            } else if (column.equals(Directory.SHORTCUT_SUPPORT)) {
+                                row[i] = Directory.SHORTCUT_SUPPORT_NONE;
+                            }
+                        }
+                        cursor.addRow(row);
                     }
                 }
-                cursor.addRow(row);
                 return cursor;
             }
             case GAL_FILTER:
diff --git a/tests/uiautomator/app/Android.mk b/hostsidetests/devicepolicy/app/CustomizationApp/Android.mk
similarity index 73%
copy from tests/uiautomator/app/Android.mk
copy to hostsidetests/devicepolicy/app/CustomizationApp/Android.mk
index 4fe2688..7b29bd4 100644
--- a/tests/uiautomator/app/Android.mk
+++ b/hostsidetests/devicepolicy/app/CustomizationApp/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2012 The Android Open Source Project
+# Copyright (C) 2016 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -16,21 +16,18 @@
 
 include $(CLEAR_VARS)
 
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsCustomizationApp
+
 LOCAL_MODULE_TAGS := optional
+
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ctsdeviceutil
+
 LOCAL_SDK_VERSION := current
 
-LOCAL_PACKAGE_NAME := CtsUiAutomatorTestApp
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
+include $(BUILD_CTS_PACKAGE)
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/CustomizationApp/AndroidManifest.xml b/hostsidetests/devicepolicy/app/CustomizationApp/AndroidManifest.xml
new file mode 100644
index 0000000..f638adf
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CustomizationApp/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.customizationapp">
+
+    <uses-sdk android:minSdkVersion="24"/>
+
+    <uses-permission android:name="android.permission.SET_WALLPAPER" />
+
+    <application>
+    </application>
+
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.cts.customizationapp"
+        android:label="Customization CTS Tests" />
+
+</manifest>
diff --git a/hostsidetests/devicepolicy/app/CustomizationApp/res/raw/wallpaper.png b/hostsidetests/devicepolicy/app/CustomizationApp/res/raw/wallpaper.png
new file mode 100644
index 0000000..6a2f3ba
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CustomizationApp/res/raw/wallpaper.png
Binary files differ
diff --git a/hostsidetests/devicepolicy/app/CustomizationApp/src/com/android/cts/customizationapp/CustomizationTest.java b/hostsidetests/devicepolicy/app/CustomizationApp/src/com/android/cts/customizationapp/CustomizationTest.java
new file mode 100644
index 0000000..11d8c78
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/CustomizationApp/src/com/android/cts/customizationapp/CustomizationTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.customizationapp;
+
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.os.UserManager;
+import android.test.AndroidTestCase;
+
+import android.cts.util.BitmapUtils;
+import com.android.cts.customizationapp.R;
+
+/**
+ * Test class to check different restrictions, that are connected to the device customization.
+ * The test verifies that non-admin app can't circumvent restriction. The tested restriction is
+ * {@link UserManager#DISALLOW_SET_WALLPAPER}. There is no non-admin API for setting the user icon,
+ * that would allow to test {@link UserManager#DISALLOW_SET_USER_ICON} restriction in this test.
+ */
+public class CustomizationTest extends AndroidTestCase {
+    private static final int WAITING_TIME_MS = 3 * 1000;
+
+    public void testSetWallpaper_disallowed() throws Exception {
+        final WallpaperManager wallpaperManager = WallpaperManager.getInstance(mContext);
+        final Bitmap originalWallpaper = BitmapUtils.getWallpaperBitmap(mContext);
+        final Bitmap referenceWallpaper = BitmapUtils.generateRandomBitmap(97, 73);
+        final UserManager userManager =
+                (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        assertTrue(userManager.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER));
+
+        // Checking setBitmap() method.
+        wallpaperManager.setBitmap(referenceWallpaper);
+        Thread.sleep(WAITING_TIME_MS);
+        Bitmap newWallpaper = BitmapUtils.getWallpaperBitmap(mContext);
+        assertTrue(BitmapUtils.compareBitmaps(newWallpaper, originalWallpaper));
+
+        // Checking setStream() method.
+        wallpaperManager.setStream(BitmapUtils.bitmapToInputStream(referenceWallpaper));
+        Thread.sleep(WAITING_TIME_MS);
+        newWallpaper = BitmapUtils.getWallpaperBitmap(mContext);
+        assertTrue(BitmapUtils.compareBitmaps(newWallpaper, originalWallpaper));
+
+        // Checking setResource() method.
+        wallpaperManager.setResource(R.raw.wallpaper);
+        Thread.sleep(WAITING_TIME_MS);
+        newWallpaper = BitmapUtils.getWallpaperBitmap(mContext);
+        assertTrue(BitmapUtils.compareBitmaps(newWallpaper, originalWallpaper));
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk
index c104697..b1c35aa 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/api23/Android.mk
@@ -24,7 +24,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
 
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner ub-uiautomator
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctsdeviceutil ctstestrunner ub-uiautomator
 
 LOCAL_SDK_VERSION := current
 
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk
index 1cacc99..7d08bc3 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/Android.mk
@@ -24,7 +24,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, ../src)
 
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctstestrunner ub-uiautomator
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 ctsdeviceutil ctstestrunner ub-uiautomator
 
 LOCAL_SDK_VERSION := current
 
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
index c62af4c..5bd902c 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/latest/AndroidManifest.xml
@@ -22,6 +22,7 @@
     <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
+    <uses-permission android:name="android.permission.SET_WALLPAPER" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/raw/wallpaper.png b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/raw/wallpaper.png
new file mode 100644
index 0000000..6a2f3ba
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/res/raw/wallpaper.png
Binary files differ
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java
index 8f561a6..edeefd3 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java
@@ -68,6 +68,9 @@
     }
 
     public void testAlwaysOnVpn() throws Exception {
+        // test always-on is null by default
+        assertNull(mDevicePolicyManager.getAlwaysOnVpnPackage(ADMIN_RECEIVER_COMPONENT));
+
         final CountDownLatch vpnLatch = new CountDownLatch(1);
 
         final ConnectivityManager cm =
@@ -89,6 +92,8 @@
         cm.registerNetworkCallback(request, callback);
         try {
             mDevicePolicyManager.setAlwaysOnVpnPackage(ADMIN_RECEIVER_COMPONENT, VPN_PACKAGE);
+            assertEquals(VPN_PACKAGE, mDevicePolicyManager.getAlwaysOnVpnPackage(
+                    ADMIN_RECEIVER_COMPONENT));
             assertTrue("Took too long waiting to establish a VPN-backed connection",
                     vpnLatch.await(NETWORK_TIMEOUT_MS, TimeUnit.MILLISECONDS));
 
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CustomizationRestrictionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CustomizationRestrictionsTest.java
new file mode 100644
index 0000000..ebc833b
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/CustomizationRestrictionsTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.deviceandprofileowner;
+
+import android.app.WallpaperManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.cts.util.BitmapUtils;
+import com.android.cts.deviceandprofileowner.R;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * These tests verify that the device / profile owner can use appropriate API for customization
+ * (DevicePolicyManager.setUserIcon(), WallpaperManager.setBitmap(), etc.) even in case,
+ * when appropriate restrictions are set. The tested restrictions are
+ * {@link UserManager#DISALLOW_SET_WALLPAPER} and {@link UserManager#DISALLOW_SET_USER_ICON}.
+ */
+public class CustomizationRestrictionsTest extends BaseDeviceAdminTest {
+
+    private static final int BROADCAST_TIMEOUT_SEC = 3;
+
+    // Class sets/resets restriction in try-with-resources statement.
+    private class RestrictionApplicator implements Closeable {
+        private final String mRestriction;
+        RestrictionApplicator(String restriction) {
+            mRestriction = restriction;
+            mDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT, mRestriction);
+        }
+
+        @Override
+        public void close() throws IOException {
+            mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT, mRestriction);
+        }
+    }
+
+    // Class subscribes/unsubscribe for broadcast notification in try-with-resources statement.
+    private class BroadcastReceiverRegistrator implements Closeable {
+        private final BlockingBroadcastReceiver mReceiver;
+        public BroadcastReceiverRegistrator(String action) {
+            final IntentFilter filter = new IntentFilter();
+            filter.addAction(action);
+            mReceiver = new BlockingBroadcastReceiver();
+            mContext.registerReceiver(mReceiver, filter);
+        }
+
+        @Override
+        public void close() throws IOException {
+            mContext.unregisterReceiver(mReceiver);
+        }
+
+        public void waitForBroadcast() throws Exception {
+            mReceiver.waitForBroadcast();
+        }
+    }
+
+    private class BlockingBroadcastReceiver extends BroadcastReceiver {
+        private BlockingQueue<Integer> mQueue = new ArrayBlockingQueue<Integer> (1);
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            assertTrue(mQueue.add(0));
+        }
+
+        public void waitForBroadcast() throws Exception {
+            Integer result = mQueue.poll(BROADCAST_TIMEOUT_SEC, TimeUnit.SECONDS);
+            assertNotNull(result);
+        }
+    }
+
+    private static int getUserId() throws Exception {
+        UserHandle userHandle = Process.myUserHandle();
+        Class<?>[] noParam = {};
+        Class<?> userHandleClass = userHandle.getClass();
+        Method methodGetIdentifier = userHandleClass.getDeclaredMethod("getIdentifier", noParam);
+        return (Integer) methodGetIdentifier.invoke(userHandle, null);
+    }
+
+    private Bitmap getUserIcon() throws Exception {
+        Class<?>[] paramInt = new Class[1];
+        paramInt[0] = Integer.TYPE;
+        Class<?> umClass = mUserManager.getClass();
+        Method methodGetUserIcon = umClass.getDeclaredMethod("getUserIcon", paramInt);
+        return (Bitmap) methodGetUserIcon.invoke(mUserManager, getUserId());
+    }
+
+    public void testDisallowSetWallpaper_allowed() throws Exception {
+        final WallpaperManager wallpaperManager = WallpaperManager.getInstance(mContext);
+        final Bitmap originalWallpaper = BitmapUtils.getWallpaperBitmap(mContext);
+
+        try (
+            // Set restriction and subscribe for the broadcast.
+            final RestrictionApplicator restr =
+                    new RestrictionApplicator(UserManager.DISALLOW_SET_WALLPAPER);
+            final BroadcastReceiverRegistrator bcast =
+                    new BroadcastReceiverRegistrator(Intent.ACTION_WALLPAPER_CHANGED);
+        ) {
+            assertTrue(mUserManager.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER));
+
+            // Checking setBitmap() method.
+            Bitmap referenceWallpaper = BitmapUtils.generateRandomBitmap(97, 73);
+            wallpaperManager.setBitmap(referenceWallpaper);
+            bcast.waitForBroadcast();
+            Bitmap newWallpaper = BitmapUtils.getWallpaperBitmap(mContext);
+            // Violation of encapsulation if refs are equal.
+            assertNotSame(newWallpaper, referenceWallpaper);
+            assertTrue(BitmapUtils.compareBitmaps(newWallpaper, referenceWallpaper));
+
+            // Checking setStream() method.
+            referenceWallpaper = BitmapUtils.generateRandomBitmap(83, 69);
+            wallpaperManager.setStream(BitmapUtils.bitmapToInputStream(referenceWallpaper));
+            bcast.waitForBroadcast();
+            newWallpaper = BitmapUtils.getWallpaperBitmap(mContext);
+            assertTrue(BitmapUtils.compareBitmaps(newWallpaper, referenceWallpaper));
+
+            // Checking setResource() method.
+            final InputStream is = mContext.getResources().openRawResource(R.raw.wallpaper);
+            referenceWallpaper = BitmapFactory.decodeStream(is);
+            wallpaperManager.setResource(R.raw.wallpaper);
+            bcast.waitForBroadcast();
+            newWallpaper = BitmapUtils.getWallpaperBitmap(mContext);
+            assertTrue(BitmapUtils.compareBitmaps(newWallpaper, referenceWallpaper));
+        } finally {
+            wallpaperManager.setBitmap(originalWallpaper);
+        }
+        assertFalse(mUserManager.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER));
+    }
+
+    public void testDisallowSetUserIcon_allowed() throws Exception {
+        final Bitmap originalIcon = getUserIcon();
+
+        try (
+            // Apply restriction.
+            final RestrictionApplicator restr =
+                    new RestrictionApplicator(UserManager.DISALLOW_SET_USER_ICON);
+        ) {
+            assertTrue(mUserManager.hasUserRestriction(UserManager.DISALLOW_SET_USER_ICON));
+            final Bitmap randomBmp = BitmapUtils.generateRandomBitmap(17, 31);
+            mDevicePolicyManager.setUserIcon(ADMIN_RECEIVER_COMPONENT, randomBmp);
+            final Bitmap currentIcon = getUserIcon();
+            assertNotSame(randomBmp, currentIcon);
+            assertTrue(BitmapUtils.compareBitmaps(randomBmp, currentIcon));
+        } finally {
+            if (originalIcon == null) {
+                // There is no way to restore absence of an icon. Thus set white
+                // icon for esthetic reasons.
+                mDevicePolicyManager.setUserIcon(ADMIN_RECEIVER_COMPONENT,
+                        BitmapUtils.generateWhiteBitmap(20, 20));
+            } else {
+                mDevicePolicyManager.setUserIcon(ADMIN_RECEIVER_COMPONENT, originalIcon);
+            }
+        }
+        assertFalse(mUserManager.hasUserRestriction(UserManager.DISALLOW_SET_USER_ICON));
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SuspendPackageTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SuspendPackageTest.java
index 12461e1..dca2085 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SuspendPackageTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SuspendPackageTest.java
@@ -18,6 +18,7 @@
 
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 
 import java.util.Arrays;
@@ -26,29 +27,29 @@
 public class SuspendPackageTest extends BaseDeviceAdminTest {
     private static final String INTENT_RECEIVER_PKG = "com.android.cts.intent.receiver";
 
-    public void testSetPackagesSuspended() {
+    public void testSetPackagesSuspended() throws NameNotFoundException {
         String[] notHandledPackages =
                 mDevicePolicyManager.setPackagesSuspended(ADMIN_RECEIVER_COMPONENT, new String[]
                         {INTENT_RECEIVER_PKG}, true);
         // all packages should be handled.
         assertEquals(0, notHandledPackages.length);
-        // test getPackageSuspended
+        // test isPackageSuspended
         boolean isSuspended =
-                mDevicePolicyManager.getPackageSuspended(
+                mDevicePolicyManager.isPackageSuspended(
                         ADMIN_RECEIVER_COMPONENT, INTENT_RECEIVER_PKG);
         assertTrue(isSuspended);
     }
 
-    public void testSetPackagesNotSuspended() {
+    public void testSetPackagesNotSuspended() throws NameNotFoundException {
         String[] notHandledPackages = mDevicePolicyManager.setPackagesSuspended(
                 ADMIN_RECEIVER_COMPONENT,
                 new String[] {INTENT_RECEIVER_PKG},
                 false);
         // all packages should be handled.
         assertEquals(0, notHandledPackages.length);
-        // test getPackageSuspended
+        // test isPackageSuspended
         boolean isSuspended =
-                mDevicePolicyManager.getPackageSuspended(
+                mDevicePolicyManager.isPackageSuspended(
                         ADMIN_RECEIVER_COMPONENT, INTENT_RECEIVER_PKG);
         assertFalse(isSuspended);
     }
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/HardwarePropertiesManagerTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/HardwarePropertiesManagerTest.java
index f61c796..40e5220 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/HardwarePropertiesManagerTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/HardwarePropertiesManagerTest.java
@@ -44,7 +44,7 @@
                 || temp == HardwarePropertiesManager.UNDEFINED_TEMPERATURE);
 
         // Compare current temperature and shutdown threshold.
-        assertTrue(temp < shutdownTemp
+        assertTrue(temp < shutdownTemp || temp == HardwarePropertiesManager.UNDEFINED_TEMPERATURE
                 || shutdownTemp == HardwarePropertiesManager.UNDEFINED_TEMPERATURE);
         // Compare throttling and shutdown thresholds.
         assertTrue(throttlingTemp < shutdownTemp
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
index 87fe410..5d6d7fb 100755
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/KeyManagementTest.java
@@ -105,8 +105,10 @@
         final Certificate cert = getCertificate(FAKE_RSA_1.caCertificate);
 
         // Install keypairs.
-        assertTrue(mDevicePolicyManager.installKeyPair(getWho(), privKey, cert, grant, true));
-        assertTrue(mDevicePolicyManager.installKeyPair(getWho(), privKey, cert, withhold, false));
+        assertTrue(mDevicePolicyManager.installKeyPair(getWho(), privKey, new Certificate[] {cert},
+                grant, true));
+        assertTrue(mDevicePolicyManager.installKeyPair(getWho(), privKey, new Certificate[] {cert},
+                withhold, false));
         try {
             // Verify only the requested key was actually granted.
             assertGranted(grant, true);
@@ -130,7 +132,8 @@
         final Certificate cert = getCertificate(FAKE_RSA_1.caCertificate);
 
         // Install keypair.
-        assertTrue(mDevicePolicyManager.installKeyPair(getWho(), privKey, cert, alias, true));
+        assertTrue(mDevicePolicyManager.installKeyPair(getWho(), privKey, new Certificate[] {cert},
+                alias, true));
         try {
             assertGranted(alias, true);
         } finally {
@@ -140,7 +143,8 @@
         assertGranted(alias, false);
 
         // Install again.
-        assertTrue(mDevicePolicyManager.installKeyPair(getWho(), privKey, cert, alias, false));
+        assertTrue(mDevicePolicyManager.installKeyPair(getWho(), privKey, new Certificate[] {cert},
+                alias, false));
         try {
             assertGranted(alias, false);
         } finally {
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockScreenInfoTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockScreenInfoTest.java
index 7d7b57c..4863192 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockScreenInfoTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/LockScreenInfoTest.java
@@ -38,7 +38,7 @@
 
     public void testEmptyStringClearsLockInfo() {
         final String message = "";
-        assertTrue(mDevicePolicyManager.setDeviceOwnerLockScreenInfo(getWho(), message));
+        mDevicePolicyManager.setDeviceOwnerLockScreenInfo(getWho(), message);
         assertNull(mDevicePolicyManager.getDeviceOwnerLockScreenInfo());
     }
 
@@ -78,7 +78,7 @@
      * @throws AssertionError if the setting did not take effect.
      */
     private void setLockInfo(String message) {
-        assertTrue(mDevicePolicyManager.setDeviceOwnerLockScreenInfo(getWho(), message));
+        mDevicePolicyManager.setDeviceOwnerLockScreenInfo(getWho(), message);
         assertEquals(message, mDevicePolicyManager.getDeviceOwnerLockScreenInfo());
     }
 }
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
index 0c1f421..8e42279 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/SecurityLoggingTest.java
@@ -62,6 +62,16 @@
     }
 
     /**
+     * Test: Test enabling and disabling of security logging.
+     */
+    public void testEnablingAndDisablingSecurityLogging() {
+        mDevicePolicyManager.setSecurityLoggingEnabled(getWho(), true);
+        assertTrue(mDevicePolicyManager.isSecurityLoggingEnabled(getWho()));
+        mDevicePolicyManager.setSecurityLoggingEnabled(getWho(), false);
+        assertFalse(mDevicePolicyManager.isSecurityLoggingEnabled(getWho()));
+    }
+
+    /**
      * Test: retrieving security logs should be rate limited - subsequent attempts should return
      * null.
      */
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
index 1f6bc7c..6d233b7 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/AndroidManifest.xml
@@ -19,6 +19,7 @@
 
     <uses-sdk android:minSdkVersion="20"/>
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.READ_CONTACTS" />
@@ -99,6 +100,13 @@
                 <data android:mimeType="vnd.android.cursor.item/person" />
             </intent-filter>
         </activity>
+        <service android:name=".AccountService" 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>
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/res/xml/authenticator.xml b/hostsidetests/devicepolicy/app/ManagedProfile/res/xml/authenticator.xml
new file mode 100644
index 0000000..46cbb7e
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/res/xml/authenticator.xml
@@ -0,0 +1,22 @@
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- The attributes in this XML file provide configuration information -->
+<!-- for the Account Manager. -->
+
+<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:accountType="com.android.cts.test"
+    android:label="@string/label"
+/>
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AccountAuthenticator.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AccountAuthenticator.java
new file mode 100644
index 0000000..e8cc616
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AccountAuthenticator.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.managedprofile;
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.AccountManager;
+import android.accounts.NetworkErrorException;
+import android.content.Context;
+import android.os.Bundle;
+
+/* package */ class AccountAuthenticator extends AbstractAccountAuthenticator {
+    private static AccountAuthenticator sAuthenticator = null;
+    public static final String ACCOUNT_NAME = "CTS";
+    public static final String ACCOUNT_TYPE = "com.android.cts.test";
+    private static final String AUTH_TOKEN = "authToken";
+    private static final String AUTH_TOKEN_LABEL = "authTokenLabel";
+
+    private AccountAuthenticator(Context context) {
+        super(context);
+    }
+
+    private Bundle createResultBundle() {
+        Bundle result = new Bundle();
+        result.putString(AccountManager.KEY_ACCOUNT_NAME, ACCOUNT_NAME);
+        result.putString(AccountManager.KEY_ACCOUNT_TYPE, ACCOUNT_TYPE);
+        result.putString(AccountManager.KEY_AUTHTOKEN, AUTH_TOKEN);
+
+        return result;
+    }
+
+    @Override
+    public Bundle addAccount(AccountAuthenticatorResponse response, String accountType,
+            String authTokenType, String[] requiredFeatures, Bundle options)
+            throws NetworkErrorException {
+        return createResultBundle();
+    }
+
+    @Override
+    public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
+        return createResultBundle();
+    }
+
+    @Override
+    public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account,
+            String authTokenType, Bundle options) throws NetworkErrorException {
+        return createResultBundle();
+    }
+
+    @Override
+    public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account,
+            Bundle options) throws NetworkErrorException {
+
+        Bundle result = new Bundle();
+        result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+        return result;
+    }
+
+    @Override
+    public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account,
+            String authTokenType, Bundle options) throws NetworkErrorException {
+        return createResultBundle();
+    }
+
+    @Override
+    public String getAuthTokenLabel(String authTokenType) {
+        return AUTH_TOKEN_LABEL;
+    }
+
+    @Override
+    public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account,
+            String[] features) throws NetworkErrorException {
+
+        Bundle result = new Bundle();
+        result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+        return result;
+    }
+
+    public static synchronized AccountAuthenticator getAuthenticator(Context context) {
+        if (sAuthenticator == null) {
+            sAuthenticator = new AccountAuthenticator(context.getApplicationContext());
+        }
+        return sAuthenticator;
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AccountService.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AccountService.java
new file mode 100644
index 0000000..5c34a79
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/AccountService.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.managedprofile;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class AccountService extends Service {
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return AccountAuthenticator.getAuthenticator(this).getIBinder();
+    }
+}
diff --git a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java
index 0c4e74c..5a2b3fa 100644
--- a/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java
+++ b/hostsidetests/devicepolicy/app/ManagedProfile/src/com/android/cts/managedprofile/ContactsTest.java
@@ -16,6 +16,8 @@
 
 package com.android.cts.managedprofile;
 
+import android.accounts.Account;
+import android.accounts.AccountManager;
 import android.annotation.TargetApi;
 import android.app.admin.DevicePolicyManager;
 import android.content.ContentProviderOperation;
@@ -50,8 +52,8 @@
 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
 public class ContactsTest extends AndroidTestCase {
 
-    private static final String TEST_ACCOUNT_NAME = "CTS";
-    private static final String TEST_ACCOUNT_TYPE = "com.android.cts.test";
+    private static final String TEST_ACCOUNT_NAME = AccountAuthenticator.ACCOUNT_NAME;
+    private static final String TEST_ACCOUNT_TYPE = AccountAuthenticator.ACCOUNT_TYPE;
     // details of a sample primary contact
     private static final String PRIMARY_CONTACT_DISPLAY_NAME = "Primary";
     private static final String PRIMARY_CONTACT_PHONE = "00000001";
@@ -140,6 +142,11 @@
                 .getSystemService(Context.DEVICE_POLICY_SERVICE);
     }
 
+    public void testAddTestAccount() {
+        Account account = new Account(TEST_ACCOUNT_NAME, TEST_ACCOUNT_TYPE);
+        AccountManager.get(getContext()).addAccountExplicitly(account, null, null);
+    }
+
     public void testPrimaryProfilePhoneAndEmailLookup_insertedAndfound() throws RemoteException,
             OperationApplicationException, NotFoundException, IOException {
         assertFalse(isManagedProfile());
@@ -1232,6 +1239,9 @@
             // Catch all exceptions to let tearDown() run smoothly
             e.printStackTrace();
         }
+
+        Account account = new Account(TEST_ACCOUNT_NAME, TEST_ACCOUNT_TYPE);
+        AccountManager.get(getContext()).removeAccountExplicitly(account);
     }
 
     private InputStream getInputStreamFromUriForTest(String uriString) {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index d9e7790..ef9e741 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -26,8 +26,8 @@
 
 /**
  * Set of tests for use cases that apply to profile and device owner.
- * This class is the base class of MixedProfileOwnerTest and MixedDeviceOwnerTest and is abstract
- * to avoid running spurious tests.
+ * This class is the base class of MixedProfileOwnerTest, MixedDeviceOwnerTest and
+ * MixedManagedProfileOwnerTest and is abstract to avoid running spurious tests.
  *
  * NOTE: Not all tests are executed in the subclasses.  Sometimes, if a test is not applicable to
  * a subclass, they override it with an empty method.
@@ -85,6 +85,9 @@
     private static final String ACCOUNT_TYPE
             = "com.android.cts.devicepolicy.accountmanagement.account.type";
 
+    private static final String CUSTOMIZATION_APP_PKG = "com.android.cts.customizationapp";
+    private static final String CUSTOMIZATION_APP_APK = "CtsCustomizationApp.apk";
+
     // ID of the user all tests are run as. For device owner this will be the primary user, for
     // profile owner it is the user id of the created profile.
     protected int mUserId;
@@ -102,6 +105,7 @@
             getDevice().uninstallPackage(VPN_APP_PKG);
             getDevice().uninstallPackage(INTENT_RECEIVER_PKG);
             getDevice().uninstallPackage(INTENT_SENDER_PKG);
+            getDevice().uninstallPackage(CUSTOMIZATION_APP_PKG);
         }
         super.tearDown();
     }
@@ -384,6 +388,45 @@
         }
     }
 
+    // Sets restrictions and launches non-admin app, that tries to set wallpaper.
+    // Non-admin apps must not violate any user restriction.
+    public void testSetWallpaper_disallowed() throws Exception {
+        // UserManager.DISALLOW_SET_WALLPAPER
+        final String DISALLOW_SET_WALLPAPER = "no_set_wallpaper";
+        if (!mHasFeature) {
+            return;
+        }
+
+        installAppAsUser(CUSTOMIZATION_APP_APK, mUserId);
+        try {
+            changeUserRestrictionForUser(DISALLOW_SET_WALLPAPER, COMMAND_ADD_USER_RESTRICTION,
+                    mUserId);
+            assertTrue(runDeviceTestsAsUser(CUSTOMIZATION_APP_PKG, ".CustomizationTest",
+                "testSetWallpaper_disallowed", mUserId));
+        } finally {
+            changeUserRestrictionForUser(DISALLOW_SET_WALLPAPER, COMMAND_CLEAR_USER_RESTRICTION,
+                    mUserId);
+        }
+    }
+
+    // Runs test with admin privileges. The test methods set all the tested restrictions
+    // inside. But these restrictions must have no effect on the device/profile owner behavior.
+    public void testDisallowSetWallpaper_allowed() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        executeDeviceTestMethod(".CustomizationRestrictionsTest",
+                "testDisallowSetWallpaper_allowed");
+    }
+
+    public void testDisallowSetUserIcon_allowed() throws Exception {
+        if (!mHasFeature) {
+            return;
+        }
+        executeDeviceTestMethod(".CustomizationRestrictionsTest",
+                "testDisallowSetUserIcon_allowed");
+    }
+
     public void testPackageInstallUserRestrictions() throws Exception {
         // UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES
         final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 18ed0a6..2471cca 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -312,6 +312,7 @@
     public void testSecurityLoggingWithSingleUser() throws Exception {
         executeDeviceTestMethod(".SecurityLoggingTest",
                 "testRetrievingSecurityLogsNotPossibleImmediatelyAfterPreviousSuccessfulRetrieval");
+        executeDeviceTestMethod(".SecurityLoggingTest", "testEnablingAndDisablingSecurityLogging");
     }
 
     public void testLockTask() throws Exception {
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
index 8eaa606..975cf4b 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/ManagedProfileTest.java
@@ -751,6 +751,12 @@
         }
 
         try {
+            // Add test account
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testAddTestAccount", mParentUserId));
+            assertTrue(runDeviceTestsAsUser(MANAGED_PROFILE_PKG, ".ContactsTest",
+                    "testAddTestAccount", mProfileUserId));
+
             // Install directory provider to both primary and managed profile
             installAppAsUser(DIRECTORY_PROVIDER_APK, mProfileUserId);
             installAppAsUser(DIRECTORY_PROVIDER_APK, mParentUserId);
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
index 6f93480..32110de 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
@@ -86,4 +86,9 @@
                             mPrimaryUserId));
         }
     }
+
+    @Override
+    public void testDisallowSetWallpaper_allowed() throws Exception {
+        // Managed profile doesn't have wallpaper.
+    }
 }
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index adaaf84..41fd638 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -25,6 +25,7 @@
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 
+import android.app.ActivityManager;
 import android.app.Instrumentation;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -64,6 +65,8 @@
     private static final String STATUS_NETWORK_AVAILABLE_PREFIX = "NetworkAvailable:";
     private static final int SECOND_IN_MS = 1000;
     private static final int NETWORK_TIMEOUT_MS = 15 * SECOND_IN_MS;
+    private static final int PROCESS_STATE_FOREGROUND_SERVICE = 4;
+
 
     // Must be higher than NETWORK_TIMEOUT_MS
     private static final int ORDERED_BROADCAST_TIMEOUT_MS = NETWORK_TIMEOUT_MS * 4;
@@ -82,11 +85,12 @@
         mContext = mInstrumentation.getContext();
         mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
         mWfm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
-        mUid = mContext.getPackageManager().getPackageInfo(TEST_APP2_PKG, 0).applicationInfo.uid;
-        final int myUid = mContext.getPackageManager()
-                .getPackageInfo(mContext.getPackageName(), 0).applicationInfo.uid;
+        mUid = getUid(TEST_APP2_PKG);
+        final int myUid = getUid(mContext.getPackageName());
 
-        Log.d(TAG, "UIDS: test app=" + myUid + ", app2=" + mUid);
+        Log.i(TAG, "Apps status on " + getName() + ":\n"
+                + "\ttest app: uid=" + myUid + ", state=" + getProcessStateByUid(myUid) + "\n"
+                + "\tapp2: uid=" + mUid + ", state=" + getProcessStateByUid(mUid));
    }
 
     @Override
@@ -98,6 +102,10 @@
         }
     }
 
+    protected int getUid(String packageName) throws Exception {
+        return mContext.getPackageManager().getPackageUid(packageName, 0);
+    }
+
     protected void assertRestrictBackgroundChangedReceived(int expectedCount) throws Exception {
         assertRestrictBackgroundChangedReceived(DYNAMIC_RECEIVER, expectedCount);
         assertRestrictBackgroundChangedReceived(MANIFEST_RECEIVER, 0);
@@ -158,6 +166,7 @@
     }
 
     protected void assertRestrictBackgroundStatus(int expectedApiStatus) throws Exception {
+        assertBackgroundState(); // Sanity check.
         final Intent intent = new Intent(ACTION_CHECK_NETWORK);
         final String resultData = sendOrderedBroadcast(intent);
         final String[] resultItems = resultData.split(RESULT_SEPARATOR);
@@ -171,6 +180,7 @@
     }
 
     protected void assertBackgroundNetworkAccess(boolean expectAllowed) throws Exception {
+        assertBackgroundState(); // Sanity check.
         final Intent intent = new Intent(ACTION_CHECK_NETWORK);
         final String resultData = sendOrderedBroadcast(intent);
         final String[] resultItems = resultData.split(RESULT_SEPARATOR);
@@ -178,6 +188,27 @@
         assertNetworkStatus(expectAllowed, networkStatus);
     }
 
+    protected final void assertBackgroundState() throws Exception {
+        final ProcessState state = getProcessStateByUid(mUid);
+        Log.v(TAG, "assertBackgroundState(): status for app2 (" + mUid + "): " + state);
+        final boolean isBackground = isBackground(state.state);
+        assertTrue("App2 is not on background state: " + state, isBackground);
+    }
+
+    protected final void assertForegroundServiceState() throws Exception {
+        final ProcessState state = getProcessStateByUid(mUid);
+        Log.v(TAG, "assertForegroundServiceState(): status for app2 (" + mUid + "): " + state);
+        assertEquals("App2 is not on foreground service state: " + state,
+                PROCESS_STATE_FOREGROUND_SERVICE, state.state);
+    }
+
+    /**
+     * Returns whether an app state should be considered "background" for restriction purposes.
+     */
+    protected boolean isBackground(int state) {
+        return state >= PROCESS_STATE_FOREGROUND_SERVICE;
+    }
+
     private String getNetworkStatus(String[] resultItems) {
         return resultItems.length < 2 ? null : resultItems[1];
     }
@@ -216,8 +247,9 @@
     protected void assertDelayedShellCommand(String command, String expectedResult)
             throws Exception {
         final int maxTries = 5;
+        String result = "";
         for (int i = 1; i <= maxTries; i++) {
-            final String result = executeShellCommand(command).trim();
+            result = executeShellCommand(command).trim();
             if (result.equals(expectedResult))
                 return;
             Log.v(TAG, "Command '" + command + "' returned '" + result + " instead of '"
@@ -225,7 +257,7 @@
             Thread.sleep(SECOND_IN_MS);
         }
         fail("Command '" + command + "' did not return '" + expectedResult + "' after " + maxTries
-                + " attempts");
+                + " attempts. Last result: '" + result + "'");
     }
 
     protected void setMeteredNetwork() throws Exception {
@@ -234,6 +266,8 @@
         if (metered) {
             Log.d(TAG, "Active network already metered: " + info);
             return;
+        } else {
+            Log.w(TAG, "Active network not metered: " + info);
         }
         final String netId = setWifiMeteredStatus(true);
         assertTrue("Could not set wifi '" + netId + "' as metered ("
@@ -243,7 +277,10 @@
     }
 
     protected String setWifiMeteredStatus(boolean metered) throws Exception {
-        mWfm.setWifiEnabled(true);
+        // We could call setWifiEnabled() here, but it might take sometime to be in a consistent
+        // state (for example, if one of the saved network is not properly authenticated), so it's
+        // better to let the hostside test take care of that.
+        assertTrue("wi-fi is disabled", mWfm.isWifiEnabled());
         // TODO: if it's not guaranteed the device has wi-fi, we need to change the tests
         // to make the actual verification of restrictions optional.
         final String ssid = mWfm.getConnectionInfo().getSSID();
@@ -357,7 +394,7 @@
      * The service must run in a separate app because otherwise it would be killed every time
      * {@link #runDeviceTests(String, String)} is executed.
      */
-    protected void registerApp2BroadcastReceiver() throws Exception {
+    protected void registerBroadcastReceiver() throws Exception {
         executeShellCommand("am startservice com.android.cts.net.hostside.app2/.MyService");
         // Wait until receiver is ready.
         final int maxTries = 5;
@@ -374,6 +411,11 @@
         fail("app2 receiver is not ready");
     }
 
+    protected void startForegroundService() throws Exception {
+        executeShellCommand(
+                "am startservice com.android.cts.net.hostside.app2/.MyForegroundService");
+    }
+
     private String toString(int status) {
         switch (status) {
             case RESTRICT_BACKGROUND_STATUS_DISABLED:
@@ -386,4 +428,27 @@
                 return "UNKNOWN_STATUS_" + status;
         }
     }
+
+    private ProcessState getProcessStateByUid(int uid) throws Exception {
+        return new ProcessState(executeShellCommand("cmd activity get-uid-state " + uid));
+    }
+
+    private static class ProcessState {
+        private final String fullState;
+        final int state;
+
+        ProcessState(String fullState) {
+            this.fullState = fullState;
+            try {
+                this.state = Integer.parseInt(fullState.split(" ")[0]);
+            } catch (Exception e) {
+                throw new IllegalArgumentException("Could not parse " + fullState);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return fullState;
+        }
+    }
 }
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeNonMeteredTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeNonMeteredTest.java
index 5181057..8e83fa2 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeNonMeteredTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeNonMeteredTest.java
@@ -25,7 +25,7 @@
 
         setPowerSaveMode(false);
         assertPowerSaveModeWhitelist(TEST_APP2_PKG, false); // Sanity check
-        registerApp2BroadcastReceiver();
+        registerBroadcastReceiver();
     }
 
     @Override
@@ -38,6 +38,10 @@
     public void testBackgroundNetworkAccess_enabled() throws Exception {
         setPowerSaveMode(true);
         assertBackgroundNetworkAccess(false);
+        // Make sure app is allowed if running a foreground service.
+        startForegroundService();
+        assertForegroundServiceState();
+        assertBackgroundNetworkAccess(true);
     }
 
     public void testBackgroundNetworkAccess_whitelisted() throws Exception {
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeTest.java
index 18e2b3e..6a8540a 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/BatterySaverModeTest.java
@@ -26,7 +26,7 @@
         setMeteredNetwork();
         setPowerSaveMode(false);
         assertPowerSaveModeWhitelist(TEST_APP2_PKG, false); // Sanity check
-        registerApp2BroadcastReceiver();
+        registerBroadcastReceiver();
     }
 
     @Override
@@ -39,6 +39,11 @@
     public void testBackgroundNetworkAccess_enabled() throws Exception {
         setPowerSaveMode(true);
         assertBackgroundNetworkAccess(false);
+
+        // Make sure app is allowed if running a foreground service.
+        startForegroundService();
+        assertForegroundServiceState();
+        assertBackgroundNetworkAccess(true);
     }
 
     public void testBackgroundNetworkAccess_whitelisted() throws Exception {
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
index b9fca39..ff68090 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
@@ -20,6 +20,15 @@
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
 
+/*
+ * TODO: need to add more scenarios:
+ * - test access on foreground app
+ * - test access on foreground service app
+ * - make sure it works when app is on foreground and state is transitioned:
+ *   - data saver is enabled
+ *   - app is added/removed to blacklist
+ *
+ */
 public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase {
 
     @Override
@@ -28,7 +37,7 @@
 
         setMeteredNetwork();
         setRestrictBackground(false);
-        registerApp2BroadcastReceiver();
+        registerBroadcastReceiver();
    }
 
     @Override
@@ -40,13 +49,13 @@
 
     public void testGetRestrictBackgroundStatus_disabled() throws Exception {
         removeRestrictBackgroundWhitelist(mUid);
-        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
         assertRestrictBackgroundChangedReceived(0);
+        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
 
         // Sanity check: make sure status is always disabled, never whitelisted
         addRestrictBackgroundWhitelist(mUid);
-        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
         assertRestrictBackgroundChangedReceived(0);
+        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
     }
 
     public void testGetRestrictBackgroundStatus_whitelisted() throws Exception {
@@ -54,40 +63,45 @@
         assertRestrictBackgroundChangedReceived(1);
 
         addRestrictBackgroundWhitelist(mUid);
-        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_WHITELISTED);
         assertRestrictBackgroundChangedReceived(2);
+        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_WHITELISTED);
     }
 
     public void testGetRestrictBackgroundStatus_enabled() throws Exception {
         setRestrictBackground(true);
         assertRestrictBackgroundChangedReceived(1);
+        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_ENABLED);
 
         removeRestrictBackgroundWhitelist(mUid);
-        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_ENABLED);
         assertRestrictBackgroundChangedReceived(1);
+        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_ENABLED);
+
+        // Make sure app is allowed if running a foreground service.
+        assertBackgroundNetworkAccess(false);
+        startForegroundService();
+        assertForegroundServiceState();
+        assertBackgroundNetworkAccess(true);
     }
 
     public void testGetRestrictBackgroundStatus_blacklisted() throws Exception {
         addRestrictBackgroundBlacklist(mUid);
         assertRestrictBackgroundChangedReceived(1);
-
         assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_ENABLED);
 
-        // TODO: currently whitelist is prevailing, hence remaining of the test below is disabled
-        if (true) return;
-
         // Make sure blacklist prevails over whitelist.
         setRestrictBackground(true);
         assertRestrictBackgroundChangedReceived(2);
+        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_ENABLED);
         addRestrictBackgroundWhitelist(mUid);
+        assertRestrictBackgroundChangedReceived(3);
         assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_ENABLED);
 
         // Check status after removing blacklist.
         removeRestrictBackgroundBlacklist(mUid);
-        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_WHITELISTED);
-        assertRestrictBackgroundChangedReceived(3);
-        setRestrictBackground(false);
-        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
         assertRestrictBackgroundChangedReceived(4);
+        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_WHITELISTED);
+        setRestrictBackground(false);
+        assertRestrictBackgroundChangedReceived(5);
+        assertRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
     }
 }
diff --git a/hostsidetests/net/app2/AndroidManifest.xml b/hostsidetests/net/app2/AndroidManifest.xml
index fa4cb43..9ce5781 100644
--- a/hostsidetests/net/app2/AndroidManifest.xml
+++ b/hostsidetests/net/app2/AndroidManifest.xml
@@ -32,6 +32,7 @@
     -->
     <application>
         <service android:name=".MyService" android:exported="true"/>
+        <service android:name=".MyForegroundService" android:exported="true"/>
 
         <receiver android:name=".MyBroadcastReceiver" >
             <intent-filter>
diff --git a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java
new file mode 100644
index 0000000..bbafd4c
--- /dev/null
+++ b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyForegroundService.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.net.hostside.app2;
+
+import static com.android.cts.net.hostside.app2.Common.TAG;
+import android.R;
+import android.app.Notification;
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.util.Log;
+
+/**
+ * Service used to change app state to FOREGROUND_SERVICE.
+ */
+public class MyForegroundService extends Service {
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        Log.d(TAG, "MyForegroundService.onStartCommand: " + intent);
+        startForeground(42, new Notification.Builder(this)
+            .setSmallIcon(R.drawable.ic_dialog_alert) // any icon is fine
+            .build());
+        return START_STICKY;
+    }
+}
diff --git a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyService.java b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyService.java
index 55249f2..e6454c7 100644
--- a/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyService.java
+++ b/hostsidetests/net/app2/src/com/android/cts/net/hostside/app2/MyService.java
@@ -39,7 +39,7 @@
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
-        Log.d(TAG, "onStartCommand: " + intent);
+        Log.d(TAG, "MyService.onStartCommand: " + intent);
         final Context context = getApplicationContext();
         final MyBroadcastReceiver myReceiver = new MyBroadcastReceiver(DYNAMIC_RECEIVER);
         context.registerReceiver(myReceiver, new IntentFilter(ACTION_RECEIVER_READY));
diff --git a/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTestCase.java b/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTestCase.java
index 08fb887..ab1b7d6 100644
--- a/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTestCase.java
+++ b/hostsidetests/net/src/com/android/cts/net/HostsideNetworkTestCase.java
@@ -63,6 +63,8 @@
         assertNotNull(mAbi);
         assertNotNull(mCtsBuild);
 
+        assertTrue("device not connected to network", getDevice().checkConnectivity());
+
         uninstallPackage(TEST_PKG, false);
         installPackage(TEST_APK);
     }
diff --git a/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
index 2bd76e6..15a4e0a 100644
--- a/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
+++ b/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
@@ -30,7 +30,6 @@
 
         uninstallPackage(TEST_APP2_PKG, false);
         installPackage(TEST_APP2_APK);
-
     }
 
     @Override
diff --git a/hostsidetests/security/Android.mk b/hostsidetests/security/Android.mk
index a8a07ef..1b32669 100644
--- a/hostsidetests/security/Android.mk
+++ b/hostsidetests/security/Android.mk
@@ -43,7 +43,6 @@
 selinux_general_service_contexts := $(call intermediates-dir-for,ETC,general_service_contexts)/general_service_contexts
 
 LOCAL_JAVA_RESOURCE_FILES := \
-    $(HOST_OUT_EXECUTABLES)/sepolicy-analyze \
     $(HOST_OUT_EXECUTABLES)/checkseapp \
     $(HOST_OUT_EXECUTABLES)/checkfc \
     $(selinux_general_seapp_contexts) \
@@ -58,6 +57,8 @@
 
 selinux_neverallow_gen_data := cts/tools/selinux/SELinuxNeverallowTestFrame.py
 
+LOCAL_ADDITIONAL_DEPENDENCIES := $(COMPATIBILITY_TESTCASES_OUT_cts)/sepolicy-analyze
+
 LOCAL_GENERATED_SOURCES := $(call local-generated-sources-dir)/android/cts/security/SELinuxNeverallowRulesTest.java
 
 $(LOCAL_GENERATED_SOURCES) : PRIVATE_SELINUX_GENERAL_POLICY := $(selinux_general_policy)
diff --git a/hostsidetests/security/AndroidTest.xml b/hostsidetests/security/AndroidTest.xml
index e521761..0056e81 100644
--- a/hostsidetests/security/AndroidTest.xml
+++ b/hostsidetests/security/AndroidTest.xml
@@ -16,6 +16,6 @@
 <configuration description="Config for the CTS Security host tests">
     <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
         <option name="jar" value="CtsSecurityHostTestCases.jar" />
-        <option name="runtime-hint" value="12m13s" />
+        <option name="runtime-hint" value="32s" />
     </test>
 </configuration>
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index eb5f51e..222533a 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -16,12 +16,14 @@
 
 package android.security.cts;
 
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.CollectingOutputReceiver;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceTestCase;
 import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IDeviceTest;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -48,7 +50,7 @@
  * 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 {
+public class SELinuxHostTest extends DeviceTestCase implements IBuildReceiver, IDeviceTest {
 
     private File sepolicyAnalyze;
     private File checkSeapp;
@@ -69,6 +71,25 @@
      */
     private ITestDevice mDevice;
 
+    private CompatibilityBuildHelper mHelper;
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setBuild(IBuildInfo build) {
+        mHelper = new CompatibilityBuildHelper(build);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setDevice(ITestDevice device) {
+        super.setDevice(device);
+        mDevice = device;
+    }
+
     private File copyResourceToTempFile(String resName) throws IOException {
         InputStream is = this.getClass().getResourceAsStream(resName);
         File tempFile = File.createTempFile("SELinuxHostTest", ".tmp");
@@ -86,51 +107,13 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mDevice = getDevice();
-
-        /* retrieve the sepolicy-analyze executable from jar */
-        sepolicyAnalyze = copyResourceToTempFile("/sepolicy-analyze");
+        sepolicyAnalyze = new File(mHelper.getTestsDir(), "sepolicy-analyze");
         sepolicyAnalyze.setExecutable(true);
 
-        /* retrieve the checkseapp executable from jar */
-        checkSeapp = copyResourceToTempFile("/checkseapp");
-        checkSeapp.setExecutable(true);
-
-        /* retrieve the checkfc executable from jar */
-        checkFc = copyResourceToTempFile("/checkfc");
-        checkFc.setExecutable(true);
-
         /* obtain sepolicy file from running device */
         devicePolicyFile = File.createTempFile("sepolicy", ".tmp");
         devicePolicyFile.deleteOnExit();
         mDevice.pullFile("/sys/fs/selinux/policy", devicePolicyFile);
-
-        /* obtain seapp_contexts file from running device */
-        deviceSeappFile = File.createTempFile("seapp_contexts", ".tmp");
-        deviceSeappFile.deleteOnExit();
-        mDevice.pullFile("/seapp_contexts", deviceSeappFile);
-
-        /* obtain file_contexts.bin file from running device */
-        deviceFcFile = File.createTempFile("file_contexts", ".bin");
-        deviceFcFile.deleteOnExit();
-        mDevice.pullFile("/file_contexts.bin", deviceFcFile);
-
-        /* obtain property_contexts file from running device */
-        devicePcFile = File.createTempFile("property_contexts", ".tmp");
-        devicePcFile.deleteOnExit();
-        mDevice.pullFile("/property_contexts", devicePcFile);
-
-        /* obtain service_contexts file from running device */
-        deviceSvcFile = File.createTempFile("service_contexts", ".tmp");
-        deviceSvcFile.deleteOnExit();
-        mDevice.pullFile("/service_contexts", deviceSvcFile);
-
-        /* retrieve the AOSP *_contexts files from jar */
-        aospSeappFile = copyResourceToTempFile("/general_seapp_contexts");
-        aospFcFile = copyResourceToTempFile("/general_file_contexts.bin");
-        aospPcFile = copyResourceToTempFile("/general_property_contexts");
-        aospSvcFile = copyResourceToTempFile("/general_service_contexts");
-        seappNeverAllowFile = copyResourceToTempFile("/general_seapp_neverallows");
     }
 
     /**
@@ -214,6 +197,18 @@
      */
     public void testValidSeappContexts() throws Exception {
 
+        /* obtain seapp_contexts file from running device */
+        deviceSeappFile = File.createTempFile("seapp_contexts", ".tmp");
+        deviceSeappFile.deleteOnExit();
+        mDevice.pullFile("/seapp_contexts", deviceSeappFile);
+
+        /* retrieve the checkseapp executable from jar */
+        checkSeapp = copyResourceToTempFile("/checkseapp");
+        checkSeapp.setExecutable(true);
+
+        /* retrieve the AOSP seapp_neverallows file from jar */
+        seappNeverAllowFile = copyResourceToTempFile("/general_seapp_neverallows");
+
         /* run checkseapp on seapp_contexts */
         ProcessBuilder pb = new ProcessBuilder(checkSeapp.getAbsolutePath(),
                 "-p", devicePolicyFile.getAbsolutePath(),
@@ -260,6 +255,15 @@
      * @throws Exception
      */
     public void testAospSeappContexts() throws Exception {
+
+        /* obtain seapp_contexts file from running device */
+        deviceSeappFile = File.createTempFile("seapp_contexts", ".tmp");
+        deviceSeappFile.deleteOnExit();
+        mDevice.pullFile("/seapp_contexts", deviceSeappFile);
+
+        /* retrieve the AOSP seapp_contexts file from jar */
+        aospSeappFile = copyResourceToTempFile("/general_seapp_contexts");
+
         assertFileStartsWith(aospSeappFile, deviceSeappFile);
     }
 
@@ -270,6 +274,19 @@
      * @throws Exception
      */
     public void testAospFileContexts() throws Exception {
+
+        /* retrieve the checkfc executable from jar */
+        checkFc = copyResourceToTempFile("/checkfc");
+        checkFc.setExecutable(true);
+
+        /* obtain file_contexts.bin file from running device */
+        deviceFcFile = File.createTempFile("file_contexts", ".bin");
+        deviceFcFile.deleteOnExit();
+        mDevice.pullFile("/file_contexts.bin", deviceFcFile);
+
+        /* retrieve the AOSP file_contexts file from jar */
+        aospFcFile = copyResourceToTempFile("/general_file_contexts.bin");
+
         /* run checkfc -c general_file_contexts.bin file_contexts.bin */
         ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
                 "-c", aospFcFile.getAbsolutePath(),
@@ -292,6 +309,15 @@
      * @throws Exception
      */
     public void testAospPropertyContexts() throws Exception {
+
+        /* obtain property_contexts file from running device */
+        devicePcFile = File.createTempFile("property_contexts", ".tmp");
+        devicePcFile.deleteOnExit();
+        mDevice.pullFile("/property_contexts", devicePcFile);
+
+        /* retrieve the AOSP property_contexts file from jar */
+        aospPcFile = copyResourceToTempFile("/general_property_contexts");
+
         assertFileStartsWith(aospPcFile, devicePcFile);
     }
 
@@ -302,6 +328,15 @@
      * @throws Exception
      */
     public void testAospServiceContexts() throws Exception {
+
+        /* obtain service_contexts file from running device */
+        deviceSvcFile = File.createTempFile("service_contexts", ".tmp");
+        deviceSvcFile.deleteOnExit();
+        mDevice.pullFile("/service_contexts", deviceSvcFile);
+
+        /* retrieve the AOSP service_contexts file from jar */
+        aospSvcFile = copyResourceToTempFile("/general_service_contexts");
+
         assertFileStartsWith(aospSvcFile, deviceSvcFile);
     }
 
@@ -312,6 +347,15 @@
      */
     public void testValidFileContexts() throws Exception {
 
+        /* retrieve the checkfc executable from jar */
+        checkFc = copyResourceToTempFile("/checkfc");
+        checkFc.setExecutable(true);
+
+        /* obtain file_contexts.bin file from running device */
+        deviceFcFile = File.createTempFile("file_contexts", ".bin");
+        deviceFcFile.deleteOnExit();
+        mDevice.pullFile("/file_contexts.bin", deviceFcFile);
+
         /* run checkfc sepolicy file_contexts.bin */
         ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
                 devicePolicyFile.getAbsolutePath(),
@@ -338,6 +382,15 @@
      */
     public void testValidPropertyContexts() throws Exception {
 
+        /* retrieve the checkfc executable from jar */
+        checkFc = copyResourceToTempFile("/checkfc");
+        checkFc.setExecutable(true);
+
+        /* obtain property_contexts file from running device */
+        devicePcFile = File.createTempFile("property_contexts", ".tmp");
+        devicePcFile.deleteOnExit();
+        mDevice.pullFile("/property_contexts", devicePcFile);
+
         /* run checkfc -p on property_contexts */
         ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
                 "-p", devicePolicyFile.getAbsolutePath(),
@@ -364,6 +417,15 @@
      */
     public void testValidServiceContexts() throws Exception {
 
+        /* retrieve the checkfc executable from jar */
+        checkFc = copyResourceToTempFile("/checkfc");
+        checkFc.setExecutable(true);
+
+        /* obtain service_contexts file from running device */
+        deviceSvcFile = File.createTempFile("service_contexts", ".tmp");
+        deviceSvcFile.deleteOnExit();
+        mDevice.pullFile("/service_contexts", deviceSvcFile);
+
         /* run checkfc -s on service_contexts */
         ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
                 "-s", devicePolicyFile.getAbsolutePath(),
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/AutoEnterPipActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/AutoEnterPipActivity.java
index dbd92b5..97bc041 100644
--- a/hostsidetests/services/activitymanager/app/src/android/server/app/AutoEnterPipActivity.java
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/AutoEnterPipActivity.java
@@ -22,6 +22,6 @@
     @Override
     protected void onResume() {
         super.onResume();
-        enterPictureInPicture();
+        enterPictureInPictureMode();
     }
 }
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchPipOnPipActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchPipOnPipActivity.java
index dba7cde..d7b4cc1 100644
--- a/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchPipOnPipActivity.java
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/LaunchPipOnPipActivity.java
@@ -20,8 +20,8 @@
 
 public class LaunchPipOnPipActivity extends Activity {
     @Override
-    public void onPictureInPictureChanged(boolean inPictureInPicture) {
-        super.onPictureInPictureChanged(inPictureInPicture);
+    public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+        super.onPictureInPictureModeChanged(isInPictureInPictureMode);
         AlwaysFocusablePipActivity.launchAlwaysFocusablePipActivity(this);
     }
 }
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java
index 3de4c0e..d11cdb4 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityAndWindowManagersState.java
@@ -29,6 +29,7 @@
 import java.awt.Rectangle;
 import java.util.Objects;
 
+import static android.server.cts.ActivityManagerTestBase.FREEFORM_WORKSPACE_STACK_ID;
 import static com.android.ddmlib.Log.LogLevel.INFO;
 
 /** Combined state of the activity manager and window manager. */
@@ -38,11 +39,21 @@
     private WindowManagerState mWmState = new WindowManagerState();
 
     void computeState(ITestDevice device, String[] waitForActivitiesVisible) throws Exception {
-        computeState(device, true, waitForActivitiesVisible);
+        computeState(device, waitForActivitiesVisible, true);
+    }
+
+    void computeState(ITestDevice device, String[] waitForActivitiesVisible,
+                      boolean compareTaskAndStackBounds) throws Exception {
+        computeState(device, true, waitForActivitiesVisible, compareTaskAndStackBounds);
     }
 
     void computeState(ITestDevice device, boolean visibleOnly, String[] waitForActivitiesVisible)
             throws Exception {
+        computeState(device, visibleOnly, waitForActivitiesVisible, true);
+    }
+
+    void computeState(ITestDevice device, boolean visibleOnly, String[] waitForActivitiesVisible,
+                      boolean compareTaskAndStackBounds) throws Exception {
         int retriesLeft = 5;
         boolean retry = waitForActivitiesVisible != null && waitForActivitiesVisible.length > 0;
         do {
@@ -62,7 +73,7 @@
         } while (retry && retriesLeft-- > 0);
 
         assertSanity();
-        assertValidBounds();
+        assertValidBounds(compareTaskAndStackBounds);
     }
 
     private boolean shouldRetry(String[] waitForActivitiesVisible) {
@@ -227,7 +238,7 @@
         return true;
     }
 
-    void assertValidBounds() {
+    void assertValidBounds(boolean compareTaskAndStackBounds) {
         for (ActivityStack aStack : mAmState.getStacks()) {
             final int stackId = aStack.mStackId;
             final WindowStack wStack = mWmState.getStack(stackId);
@@ -255,10 +266,12 @@
                 final boolean aTaskIsFullscreen = aTask.isFullscreen();
                 final boolean wTaskIsFullscreen = wTask.isFullscreen();
                 assertEquals("Task fullscreen state in AM and WM must be equal taskId=" + taskId
-                                + ", stackId=" + stackId, aTaskIsFullscreen, wTaskIsFullscreen);
+                        + ", stackId=" + stackId, aTaskIsFullscreen, wTaskIsFullscreen);
 
                 final Rectangle aTaskBounds = aTask.getBounds();
                 final Rectangle wTaskBounds = wTask.getBounds();
+                final int aTaskMinWidth = aTask.getMinimalWidth();
+                final int aTaskMinHeight = aTask.getMinimalHeight();
 
                 if (aTaskIsFullscreen) {
                     assertNull("Task bounds in AM must be null for fullscreen taskId=" + taskId,
@@ -266,6 +279,28 @@
                 } else {
                     assertEquals("Task bounds in AM and WM must be equal taskId=" + taskId
                             + ", stackId=" + stackId, aTaskBounds, wTaskBounds);
+
+                    if (compareTaskAndStackBounds && stackId != FREEFORM_WORKSPACE_STACK_ID) {
+                        if (aTaskMinWidth == -1 && aTaskMinHeight == -1) {
+                            // Minimal size not set for task - checking for equality of bounds with
+                            // stack.
+                            assertEquals("Task bounds must be equal to stack bounds taskId="
+                                    + taskId + ", stackId=" + stackId, aStackBounds, wTaskBounds);
+                        } else {
+                            // Minimal width and/or height set for task - bounds of task and stack
+                            // can be different.
+                            int targetWidth = aTaskMinWidth == -1
+                                    ? (int) aStackBounds.getWidth()
+                                    : (int) Math.max(aTaskMinWidth, aStackBounds.getWidth());
+                            int targetHeight = aTaskMinHeight == -1
+                                    ? (int) aStackBounds.getHeight()
+                                    : (int) Math.max(aTaskMinHeight, aStackBounds.getHeight());
+                            final Rectangle targetBounds = new Rectangle((int) aStackBounds.getX(),
+                                    (int) aStackBounds.getY(), targetWidth, targetHeight);
+                            assertEquals("Task bounds must be set according to minimal size taskId="
+                                    + taskId + ", stackId=" + stackId, targetBounds, wTaskBounds);
+                        }
+                    }
                 }
             }
         }
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
index 58a7ae6..b2163b5 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
@@ -69,6 +69,68 @@
         mAmWmState.assertContainsStack("Must contain docked stack.", DOCKED_STACK_ID);
     }
 
+    public void testLaunchToSideAndBringToFront() throws Exception {
+        launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
+        printStacksAndTasks();
+        final String[] waitForFirstVisible = new String[] {TEST_ACTIVITY_NAME};
+        final String[] waitForSecondVisible = new String[] {NO_RELAUNCH_ACTIVITY_NAME};
+
+        // Launch activity to side.
+        launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
+        mAmWmState.computeState(mDevice, waitForFirstVisible);
+        int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
+                .getTasks().size();
+        mAmWmState.assertFocusedActivity("Launched to side activity must be in front.",
+                TEST_ACTIVITY_NAME);
+
+        // Launch another activity to side to cover first one.
+        launchActivityInStack(NO_RELAUNCH_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
+        mAmWmState.computeState(mDevice, waitForSecondVisible);
+        int taskNumberCovered = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
+                .getTasks().size();
+        mAmWmState.assertEquals("Fullscreen stack must have one task added.",
+                taskNumberInitial + 1, taskNumberCovered);
+        mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
+                NO_RELAUNCH_ACTIVITY_NAME);
+
+        // Launch activity that was first launched to side. It should be brought to front.
+        launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
+        mAmWmState.computeState(mDevice, waitForFirstVisible);
+        int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
+                .getTasks().size();
+        mAmWmState.assertEquals("Task number in fullscreen stack must remain the same.",
+                taskNumberCovered, taskNumberFinal);
+        mAmWmState.assertFocusedActivity("Launched to side covering activity must be in front.",
+                TEST_ACTIVITY_NAME);
+    }
+
+    public void testLaunchToSideMultiple() throws Exception {
+        launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
+        printStacksAndTasks();
+        final String[] waitForActivitiesVisible = new String[] {TEST_ACTIVITY_NAME};
+
+        // Launch activity to side.
+        launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
+        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
+        int taskNumberInitial = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
+                .getTasks().size();
+        mAmWmState.assertNotNull("Launched to side activity must be in fullscreen stack.",
+                mAmWmState.getAmState()
+                        .getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));
+
+        // Try to launch to side same activity again.
+        launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
+        mAmWmState.computeState(mDevice, waitForActivitiesVisible);
+        int taskNumberFinal = mAmWmState.getAmState().getStackById(FULLSCREEN_WORKSPACE_STACK_ID)
+                .getTasks().size();
+        mAmWmState.assertEquals("Task number mustn't change.", taskNumberInitial, taskNumberFinal);
+        mAmWmState.assertFocusedActivity("Launched to side activity must remain in front.",
+                TEST_ACTIVITY_NAME);
+        mAmWmState.assertNotNull("Launched to side activity must remain in fullscreen stack.",
+                mAmWmState.getAmState()
+                        .getTaskByActivityName(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID));
+    }
+
     public void testRotationWhenDocked() throws Exception {
         launchActivityInDockStack(LAUNCH_TO_SIDE_ACTIVITY_NAME);
         launchActivityToSide(LAUNCH_TO_SIDE_ACTIVITY_NAME);
@@ -137,7 +199,8 @@
         mDevice.executeShellCommand(getAmStartCmd(TEST_ACTIVITY_NAME));
         launchActivityInDockStack(DOCKED_ACTIVITY_NAME);
         resizeDockedStack(STACK_SIZE, STACK_SIZE, TASK_SIZE, TASK_SIZE);
-        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME, DOCKED_ACTIVITY_NAME});
+        mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME, DOCKED_ACTIVITY_NAME},
+                false /* compareTaskAndStackBounds */);
         mAmWmState.assertContainsStack("Must contain docked stack", DOCKED_STACK_ID);
         mAmWmState.assertContainsStack("Must contain fullscreen stack",
                 FULLSCREEN_WORKSPACE_STACK_ID);
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java
index 9b3957d..c689f46 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerState.java
@@ -239,12 +239,18 @@
     }
 
     ActivityTask getTaskByActivityName(String activityName) {
+        return getTaskByActivityName(activityName, -1);
+    }
+
+    ActivityTask getTaskByActivityName(String activityName, int stackId) {
         String fullName = ActivityManagerTestBase.getActivityComponentName(activityName);
         for (ActivityStack stack : mStacks) {
-            for (ActivityTask task : stack.mTasks) {
-                for (Activity activity : task.mActivities) {
-                    if (activity.name.equals(fullName)) {
-                        return task;
+            if (stackId == -1 || stackId == stack.mStackId) {
+                for (ActivityTask task : stack.mTasks) {
+                    for (Activity activity : task.mActivities) {
+                        if (activity.name.equals(fullName)) {
+                            return task;
+                        }
                     }
                 }
             }
@@ -405,6 +411,10 @@
                     continue;
                 }
 
+                if (extractMinimalSize(line)) {
+                    continue;
+                }
+
                 Matcher matcher = TASK_RECORD_PATTERN.matcher(line);
                 if (matcher.matches()) {
                     CLog.logAndDisplay(INFO, line);
@@ -515,9 +525,15 @@
         protected static final Pattern FULLSCREEN_PATTERN = Pattern.compile("mFullscreen=(\\S+)");
         protected static final Pattern BOUNDS_PATTERN =
                 Pattern.compile("mBounds=Rect\\((\\d+), (\\d+) - (\\d+), (\\d+)\\)");
+        protected static final Pattern MINIMAL_WIDTH_PATTERN =
+                Pattern.compile("mMinimalWidth=(\\d+)");
+        protected static final Pattern MINIMAL_HEIGHT_PATTERN =
+                Pattern.compile("mMinimalHeight=(\\d+)");
 
         protected boolean mFullscreen;
         protected Rectangle mBounds;
+        protected int mMinimalWidth = -1;
+        protected int mMinimalHeight = -1;
 
         boolean extractFullscreen(String line) {
             final Matcher matcher = FULLSCREEN_PATTERN.matcher(line);
@@ -552,6 +568,22 @@
             return rect;
         }
 
+        boolean extractMinimalSize(String line) {
+            final Matcher minWidthMatcher = MINIMAL_WIDTH_PATTERN.matcher(line);
+            final Matcher minHeightMatcher = MINIMAL_HEIGHT_PATTERN.matcher(line);
+
+            if (minWidthMatcher.matches()) {
+                CLog.logAndDisplay(INFO, line);
+                mMinimalWidth = Integer.valueOf(minWidthMatcher.group(1));
+            } else if (minHeightMatcher.matches()) {
+                CLog.logAndDisplay(INFO, line);
+                mMinimalHeight = Integer.valueOf(minHeightMatcher.group(1));
+            } else {
+                return false;
+            }
+            return true;
+        }
+
         Rectangle getBounds() {
             return mBounds;
         }
@@ -559,6 +591,14 @@
         boolean isFullscreen() {
             return mFullscreen;
         }
+
+        int getMinimalWidth() {
+            return mMinimalWidth;
+        }
+
+        int getMinimalHeight() {
+            return mMinimalHeight;
+        }
     }
 
     static boolean doneExtracting(LinkedList<String> dump, Pattern[] exitPatterns) {
diff --git a/hostsidetests/systemui/src/android/host/systemui/BaseTileServiceTest.java b/hostsidetests/systemui/src/android/host/systemui/BaseTileServiceTest.java
index 56be695..50d25e8 100644
--- a/hostsidetests/systemui/src/android/host/systemui/BaseTileServiceTest.java
+++ b/hostsidetests/systemui/src/android/host/systemui/BaseTileServiceTest.java
@@ -14,17 +14,8 @@
 
 package android.host.systemui;
 
-import com.android.compatibility.common.util.AbiUtils;
-import com.android.cts.migration.MigrationHelper;
-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;
 
 public class BaseTileServiceTest extends DeviceTestCase {
     // Constants for generating commands below.
@@ -47,7 +38,7 @@
     // Time between checks for logs we expect.
     private static final long CHECK_DELAY = 500;
     // Number of times to check before failing.
-    private static final long CHECK_RETRIES = 15;
+    private static final long CHECK_RETRIES = 30;
 
     private final String mService;
     private final String mComponent;
diff --git a/hostsidetests/theme/app/src/android/theme/app/GenerateImagesActivity.java b/hostsidetests/theme/app/src/android/theme/app/GenerateImagesActivity.java
index d0e7fc8..1bf4da1 100644
--- a/hostsidetests/theme/app/src/android/theme/app/GenerateImagesActivity.java
+++ b/hostsidetests/theme/app/src/android/theme/app/GenerateImagesActivity.java
@@ -30,7 +30,9 @@
 import android.view.WindowManager.LayoutParams;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Generates images by iterating through all themes and launching instances of
@@ -47,6 +49,8 @@
     private final CountDownLatch mLatch = new CountDownLatch(1);
 
     private File mOutputDir;
+    private File mOutputZip;
+
     private int mCurrentTheme;
     private String mFinishReason;
     private boolean mFinishSuccess;
@@ -88,14 +92,6 @@
         }.start();
     }
 
-    private void finish(String reason, boolean success) {
-        mFinishSuccess = success;
-        mFinishReason = reason;
-
-        Log.i(TAG, (success ? "OKAY" : "FAIL") + ":" + reason);
-        finish();
-    }
-
     public boolean isFinishSuccess() {
         return mFinishSuccess;
     }
@@ -146,10 +142,6 @@
         public abstract void onFailure();
     }
 
-    public File getOutputDir() {
-        return mOutputDir;
-    }
-
     /**
      * Starts the activity to generate the next image.
      */
@@ -174,9 +166,8 @@
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (resultCode != RESULT_OK) {
-            Log.i(TAG, "FAIL:Failed to generate images for theme " + mCurrentTheme + " ("
-                    + data.getStringExtra(EXTRA_REASON) + ")");
-            finish();
+            finish("Failed to generate images for theme " + mCurrentTheme + " ("
+                    + data.getStringExtra(EXTRA_REASON) + ")", false);
             return;
         }
 
@@ -188,16 +179,47 @@
 
         // If we ran out of themes, we're done.
         if (!success) {
+            compressOutput();
+
             finish("Image generation complete!", true);
         }
     }
 
+    private void compressOutput() {
+        mOutputZip = new File(mOutputDir.getParentFile(), mOutputDir.getName() + ".zip");
+
+        if (mOutputZip.exists()) {
+            // Remove any old test results.
+            mOutputZip.delete();
+        }
+
+        try {
+            ThemeTestUtils.compressDirectory(mOutputDir, mOutputZip);
+            ThemeTestUtils.deleteDirectory(mOutputDir);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void finish(String reason, boolean success) {
+        mFinishSuccess = success;
+        mFinishReason = reason;
+
+        finish();
+    }
+
+    @Override
     public void finish() {
         mLatch.countDown();
+
         super.finish();
     }
 
-    public void waitForCompletion() throws InterruptedException {
-        mLatch.await();
+    public File getOutputZip() {
+        return mOutputZip;
+    }
+
+    public boolean waitForCompletion(long timeoutMillis) throws InterruptedException {
+        return mLatch.await(timeoutMillis, TimeUnit.MILLISECONDS);
     }
 }
diff --git a/hostsidetests/theme/app/src/android/theme/app/ReferenceImagesTest.java b/hostsidetests/theme/app/src/android/theme/app/ReferenceImagesTest.java
index 7569252..6e0731d 100644
--- a/hostsidetests/theme/app/src/android/theme/app/ReferenceImagesTest.java
+++ b/hostsidetests/theme/app/src/android/theme/app/ReferenceImagesTest.java
@@ -25,6 +25,9 @@
  */
 public class ReferenceImagesTest extends ActivityInstrumentationTestCase2<GenerateImagesActivity> {
 
+    /** Overall test timeout is 30 minutes. Should only take about 5. */
+    private static final int TEST_RESULT_TIMEOUT = 30 * 60 * 1000;
+
     public ReferenceImagesTest() {
         super(GenerateImagesActivity.class);
     }
@@ -33,20 +36,12 @@
         setActivityInitialTouchMode(true);
 
         final GenerateImagesActivity activity = getActivity();
-        activity.waitForCompletion();
-
+        assertTrue("Activity failed to complete within " + TEST_RESULT_TIMEOUT + " ms",
+                activity.waitForCompletion(TEST_RESULT_TIMEOUT));
         assertTrue(activity.getFinishReason(), activity.isFinishSuccess());
 
-        final File outputDir = activity.getOutputDir();
-        final File outputZip = new File(outputDir.getParentFile(), outputDir.getName() + ".zip");
-        if (outputZip.exists()) {
-            // Remove any old test results.
-            outputZip.delete();
-        }
-
-        ThemeTestUtils.compressDirectory(outputDir, outputZip);
-        ThemeTestUtils.deleteDirectory(outputDir);
-
-        assertTrue("Generated reference image ZIP", outputZip.exists());
+        final File outputZip = activity.getOutputZip();
+        assertTrue("Failed to generate reference image ZIP",
+                outputZip != null && outputZip.exists());
     }
 }
diff --git a/hostsidetests/theme/assets/23/560dpi.zip b/hostsidetests/theme/assets/23/560dpi.zip
index cf0a559..231b4f5 100644
--- a/hostsidetests/theme/assets/23/560dpi.zip
+++ b/hostsidetests/theme/assets/23/560dpi.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 0e11111..c7a5d7c 100755
--- a/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java
+++ b/hostsidetests/theme/src/android/theme/cts/ComparisonTask.java
@@ -18,7 +18,6 @@
 
 import com.android.ddmlib.Log;
 import com.android.ddmlib.Log.LogLevel;
-import com.android.tradefed.device.ITestDevice;
 
 import java.awt.Color;
 import java.awt.image.BufferedImage;
@@ -37,12 +36,10 @@
 
     private static final int IMAGE_THRESHOLD = 2;
 
-    private final ITestDevice mDevice;
     private final File mExpected;
     private final File mActual;
 
-    public ComparisonTask(ITestDevice device, File expected, File actual) {
-        mDevice = device;
+    public ComparisonTask(File expected, File actual) {
         mExpected = expected;
         mActual = actual;
     }
diff --git a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
index 9961d1f..855f74c 100644
--- a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
+++ b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
@@ -21,6 +21,7 @@
 import com.android.ddmlib.Log;
 import com.android.ddmlib.Log.LogLevel;
 import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.CollectingOutputReceiver;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.testtype.DeviceTestCase;
@@ -28,20 +29,16 @@
 import com.android.tradefed.testtype.IAbiReceiver;
 import com.android.tradefed.testtype.IBuildReceiver;
 
-import java.io.Closeable;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.String;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Scanner;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executors;
 import java.util.concurrent.ExecutorCompletionService;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
@@ -58,12 +55,11 @@
     private static final String GENERATED_ASSETS_ZIP = "/sdcard/cts-theme-assets.zip";
 
     /** The class name of the main activity in the APK. */
-    private static final String CLASS = "GenerateImagesActivity";
     private static final String TEST_CLASS = "android.support.test.runner.AndroidJUnitRunner";
 
     /** The command to launch the main instrumentation test. */
     private static final String START_CMD = String.format(
-            "am instrument -w %s/%s", APP_PACKAGE_NAME, TEST_CLASS);
+            "am instrument -w --no-window-animation %s/%s", APP_PACKAGE_NAME, TEST_CLASS);
 
     private static final String CLEAR_GENERATED_CMD = "rm -rf %s/*.png";
     private static final String STOP_CMD = String.format("am force-stop %s", APP_PACKAGE_NAME);
@@ -71,7 +67,7 @@
     private static final String DENSITY_PROP_DEVICE = "ro.sf.lcd_density";
     private static final String DENSITY_PROP_EMULATOR = "qemu.sf.lcd_density";
 
-    /** Overall test timeout is 30 minutes. */
+    /** Overall test timeout is 30 minutes. Should only take about 5. */
     private static final int TEST_RESULT_TIMEOUT = 30 * 60 * 1000;
 
     /** Map of reference image names and files. */
@@ -155,9 +151,7 @@
     @Override
     protected void tearDown() throws Exception {
         // Delete the temp files
-        for (File ref : mReferences.values()) {
-            ref.delete();
-        }
+        mReferences.values().forEach(File::delete);
 
         mExecutionService.shutdown();
 
@@ -222,7 +216,7 @@
                     pngOutput.flush();
                     pngOutput.close();
 
-                    mCompletionService.submit(new ComparisonTask(mDevice, expected, actual));
+                    mCompletionService.submit(new ComparisonTask(expected, actual));
                     numTasks++;
                 } else {
                     Log.logAndDisplay(LogLevel.INFO, LOG_TAG,
@@ -237,85 +231,15 @@
     }
 
     private boolean generateDeviceImages() throws Exception {
-        // Clear logcat
-        mDevice.executeAdbCommand("logcat", "-c");
-
-        // Stop any existing instances
+        // Stop any existing instances.
         mDevice.executeShellCommand(STOP_CMD);
 
-        // Start activity
-        mDevice.executeShellCommand(START_CMD);
+        // Start instrumentation test.
+        final CollectingOutputReceiver receiver = new CollectingOutputReceiver();
+        mDevice.executeShellCommand(START_CMD, receiver, TEST_RESULT_TIMEOUT,
+                TimeUnit.MILLISECONDS, 0);
 
-        final long testTimeout = System.currentTimeMillis() + TEST_RESULT_TIMEOUT;
-        boolean aborted = false;
-        boolean waiting = true;
-        do {
-            // Dump logcat.
-            final String logs = mDevice.executeAdbCommand(
-                    "logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
-
-            // Search for string.
-            try (Scanner in = new Scanner(logs)) {
-                while (in.hasNextLine()) {
-                    final CloseTimeout timeout = new CloseTimeout(in, TEST_RESULT_TIMEOUT);
-                    timeout.start();
-                    final String line = in.nextLine();
-                    timeout.cancel();
-
-                    if (line.startsWith("I/" + CLASS)) {
-                        final String[] lineSplit = line.split(":");
-                        if (lineSplit.length >= 3) {
-                            final String cmd = lineSplit[1].trim();
-                            final String arg = lineSplit[2].trim();
-                            switch (cmd) {
-                                case "FAIL":
-                                    Log.logAndDisplay(LogLevel.WARN, LOG_TAG, line);
-                                    Log.logAndDisplay(LogLevel.WARN, LOG_TAG,
-                                            "Aborting! Check host logs for details.");
-                                    aborted = true;
-                                    // fall-through
-                                case "OKAY":
-                                    waiting = false;
-                                    break;
-                            }
-                        }
-                    }
-                }
-            }
-            if (testTimeout < System.currentTimeMillis()) {
-                Log.logAndDisplay(LogLevel.WARN, LOG_TAG, "Aborting! Test results took too long.");
-                aborted = true;
-            }
-        } while (waiting && !aborted);
-
-        return !aborted;
-    }
-
-    private static class CloseTimeout extends Thread {
-        private final CountDownLatch mCancelLatch = new CountDownLatch(1);
-
-        private final Closeable mCloseable;
-        private final long mTimeout;
-
-        public CloseTimeout(Closeable closeable, long timeout) {
-            mCloseable = closeable;
-            mTimeout = timeout;
-        }
-
-        @Override
-        public void run() {
-            try {
-                if (!mCancelLatch.await(mTimeout, TimeUnit.MILLISECONDS)) {
-                    mCloseable.close();
-                }
-            } catch (InterruptedException | IOException e) {
-                // Well, at least we tried.
-            }
-        }
-
-        public void cancel() {
-            mCancelLatch.countDown();
-        }
+        return receiver.getOutput().contains("OK ");
     }
 
     private static String getDensityBucketForDevice(ITestDevice device) {
@@ -354,10 +278,6 @@
     }
 
     private static boolean checkHardwareTypeSkipTest(String hardwareTypeString) {
-        if (hardwareTypeString.contains("android.hardware.type.watch")) {
-            return true;
-        }
-
-        return false;
+        return hardwareTypeString.contains("android.hardware.type.watch");
     }
 }
diff --git a/libs/deviceutil/src/android/cts/util/BitmapUtils.java b/libs/deviceutil/src/android/cts/util/BitmapUtils.java
new file mode 100644
index 0000000..7234425
--- /dev/null
+++ b/libs/deviceutil/src/android/cts/util/BitmapUtils.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.cts.util;
+
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.Color;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.lang.reflect.Method;
+import java.util.Random;
+
+public class BitmapUtils {
+    private BitmapUtils() {}
+
+    // Compares two bitmaps by pixels.
+    public static boolean compareBitmaps(Bitmap bmp1, Bitmap bmp2) {
+        if (bmp1 == bmp2) {
+            return true;
+        }
+
+        if ((bmp1.getWidth() != bmp2.getWidth()) || (bmp1.getHeight() != bmp2.getHeight())) {
+            return false;
+        }
+
+        for (int i = 0; i < bmp1.getWidth(); i++) {
+            for (int j = 0; j < bmp1.getHeight(); j++) {
+                if (bmp1.getPixel(i, j) != bmp2.getPixel(i, j)) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    public static Bitmap generateRandomBitmap(int width, int height) {
+        final Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        final Random generator = new Random();
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                bmp.setPixel(x, y, generator.nextInt(Integer.MAX_VALUE));
+            }
+        }
+        return bmp;
+    }
+
+    public static Bitmap generateWhiteBitmap(int width, int height) {
+        final Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                bmp.setPixel(x, y, Color.WHITE);
+            }
+        }
+        return bmp;
+    }
+
+    public static Bitmap getWallpaperBitmap(Context context) throws Exception {
+        WallpaperManager wallpaperManager = WallpaperManager.getInstance(context);
+        Class<?> noparams[] = {};
+        Class<?> wmClass = wallpaperManager.getClass();
+        Method methodGetBitmap = wmClass.getDeclaredMethod("getBitmap", noparams);
+        return (Bitmap) methodGetBitmap.invoke(wallpaperManager, null);
+    }
+
+    public static ByteArrayInputStream bitmapToInputStream(Bitmap bmp) {
+        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        bmp.compress(CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
+        byte[] bitmapData = bos.toByteArray();
+        return new ByteArrayInputStream(bitmapData);
+    }
+}
diff --git a/tests/accessibilityservice/Android.mk b/tests/accessibilityservice/Android.mk
index da02ef2..8ce6e99 100644
--- a/tests/accessibilityservice/Android.mk
+++ b/tests/accessibilityservice/Android.mk
@@ -18,7 +18,7 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner mockito-target
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/accessibilityservice/AndroidManifest.xml b/tests/accessibilityservice/AndroidManifest.xml
index 43a7baf..1dfb5e0 100644
--- a/tests/accessibilityservice/AndroidManifest.xml
+++ b/tests/accessibilityservice/AndroidManifest.xml
@@ -1,5 +1,4 @@
 <?xml version="1.0" encoding="utf-8"?>
-
 <!--
  * Copyright (C) 2010 The Android Open Source Project
  *
@@ -17,69 +16,93 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="android.accessibilityservice.cts">
+          package="android.accessibilityservice.cts">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
 
-    <application android:theme="@android:style/Theme.Holo.NoActionBar" >
+    <application android:theme="@android:style/Theme.Material.NoActionBar">
 
-      <uses-library android:name="android.test.runner"/>
+        <uses-library android:name="android.test.runner" />
 
-      <activity android:label="@string/accessibility_end_to_end_test_activity"
-              android:name=".AccessibilityEndToEndActivity"/>
+        <activity
+            android:label="@string/accessibility_end_to_end_test_activity"
+            android:name=".AccessibilityEndToEndActivity" />
 
-      <activity android:label="@string/accessibility_query_window_test_activity"
-              android:name=".AccessibilityWindowQueryActivity"/>
+        <activity
+            android:label="@string/accessibility_query_window_test_activity"
+            android:name=".AccessibilityWindowQueryActivity" />
 
-      <activity android:label="@string/accessibility_view_tree_reporting_test_activity"
-              android:name=".AccessibilityViewTreeReportingActivity"/>
+        <activity
+            android:label="@string/accessibility_view_tree_reporting_test_activity"
+            android:name=".AccessibilityViewTreeReportingActivity" />
 
-      <activity android:label="@string/accessibility_focus_and_input_focus_sync_test_activity"
-              android:name=".AccessibilityFocusAndInputFocusSyncActivity"/>
+        <activity
+            android:label="@string/accessibility_focus_and_input_focus_sync_test_activity"
+            android:name=".AccessibilityFocusAndInputFocusSyncActivity" />
 
-      <activity android:label="@string/accessibility_text_traversal_test_activity"
-              android:name=".AccessibilityTextTraversalActivity"/>
+        <activity
+            android:label="@string/accessibility_text_traversal_test_activity"
+            android:name=".AccessibilityTextTraversalActivity"/>
 
-      <activity android:label="Full screen activity for gesture dispatch testing"
-              android:name=".AccessibilityGestureDispatchTest$GestureDispatchActivity"/>
+        <activity
+            android:label="Full screen activity for gesture dispatch testing"
+            android:name=".AccessibilityGestureDispatchTest$GestureDispatchActivity" />
 
-      <service
-              android:name="android.accessibilityservice.cts.StubGestureAccessibilityService"
-              android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" >
-          <intent-filter>
-              <action android:name="android.accessibilityservice.AccessibilityService" />
+        <service
+            android:name=".StubGestureAccessibilityService"
+            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
+            <intent-filter>
+                <action android:name="android.accessibilityservice.AccessibilityService" />
+                <category android:name="android.accessibilityservice.category.FEEDBACK_GENERIC" />
+            </intent-filter>
 
-              <category android:name="android.accessibilityservice.category.FEEDBACK_GENERIC" />
-          </intent-filter>
+            <meta-data
+                android:name="android.accessibilityservice"
+                android:resource="@xml/stub_gesture_a11y_service" />
+        </service>
 
-          <meta-data
-                  android:name="android.accessibilityservice"
-                  android:resource="@xml/stub_gesture_a11y_service" />
-      </service>
+        <activity
+            android:label="@string/accessibility_soft_keyboard_modes_activity"
+            android:name=".AccessibilitySoftKeyboardModesTest$SoftKeyboardModesActivity"
+            android:windowSoftInputMode="stateAlwaysVisible" />
 
-      <activity android:label="@string/accessibility_soft_keyboard_modes_activity"
-              android:name=".AccessibilitySoftKeyboardModesTest$SoftKeyboardModesActivity"
-              android:windowSoftInputMode="stateAlwaysVisible" />
+        <service
+            android:name=".StubSoftKeyboardModesAccessibilityService"
+            android:label="@string/title_soft_keyboard_modes_accessibility_service"
+            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
+            <intent-filter>
+                <action android:name="android.accessibilityservice.AccessibilityService" />
+                <category android:name="android.accessibilityservice.category.FEEDBACK_GENERIC" />
+            </intent-filter>
+            <meta-data
+                android:name="android.accessibilityservice"
+                android:resource="@xml/stub_soft_keyboard_modes_accessibility_service" />
+        </service>
 
-      <service android:name=".StubSoftKeyboardModesAccessibilityService"
-               android:label="@string/title_soft_keyboard_modes_accessibility_service"
-               android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
-          <intent-filter>
-              <action android:name="android.accessibilityservice.AccessibilityService"/>
-              <category android:name="android.accessibilityservice.category.FEEDBACK_GENERIC" />
-          </intent-filter>
-          <meta-data android:name="android.accessibilityservice"
-                    android:resource="@xml/stub_soft_keyboard_modes_accessibility_service" />
-      </service>
+        <service
+            android:name=".StubMagnificationAccessibilityService"
+            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
+            <intent-filter>
+                <action android:name="android.accessibilityservice.AccessibilityService" />
+                <category android:name="android.accessibilityservice.category.FEEDBACK_GENERIC" />
+            </intent-filter>
+
+            <meta-data
+                android:name="android.accessibilityservice"
+                android:resource="@xml/stub_magnification_a11y_service" />
+        </service>
 
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                   android:targetPackage="android.accessibilityservice.cts"
-                   android:label="Tests for the accessibility APIs.">
-        <meta-data android:name="listener"
+    <instrumentation
+        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:targetPackage="android.accessibilityservice.cts"
+        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/accessibilityservice/AndroidTest.xml b/tests/accessibilityservice/AndroidTest.xml
index fe261dc..b2cb477 100644
--- a/tests/accessibilityservice/AndroidTest.xml
+++ b/tests/accessibilityservice/AndroidTest.xml
@@ -13,7 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Config for CTS Accessibility test cases">
+<configuration description="Config for CTS accessibility service test cases">
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="CtsAccessibilityServiceTestCases.apk" />
diff --git a/tests/accessibilityservice/res/values/strings.xml b/tests/accessibilityservice/res/values/strings.xml
index ff87cb0..7c9547c 100644
--- a/tests/accessibilityservice/res/values/strings.xml
+++ b/tests/accessibilityservice/res/values/strings.xml
@@ -22,6 +22,9 @@
     <!-- String title of the accessibility end-to-end test activity -->
     <string name="accessibility_end_to_end_test_activity">End-to-end test</string>
 
+    <!-- String title of the accessibility test activity -->
+    <string name="accessibility_test_activity">Test</string>
+
     <!-- String value of used as text input -->
     <string name="text_input_blah">Blah</string>
 
diff --git a/tests/accessibilityservice/res/xml/stub_magnification_a11y_service.xml b/tests/accessibilityservice/res/xml/stub_magnification_a11y_service.xml
new file mode 100644
index 0000000..110f741
--- /dev/null
+++ b/tests/accessibilityservice/res/xml/stub_magnification_a11y_service.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:accessibilityEventTypes="typeAllMask"
+    android:accessibilityFeedbackType="feedbackGeneric"
+    android:canRetrieveWindowContent="true"
+    android:canRequestTouchExplorationMode="true"
+    android:canRequestEnhancedWebAccessibility="true"
+    android:canRequestFilterKeyEvents="true"
+    android:canControlMagnification="true" />
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
index 52af854..2867674 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
@@ -15,28 +15,18 @@
 package android.accessibilityservice.cts;
 
 import android.accessibilityservice.AccessibilityService;
-import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.GestureDescription;
-import android.accessibilityservice.GestureDescription.Builder;
-import android.accessibilityservice.GestureDescription.StrokeDescription;
-import android.app.UiAutomation;
-import android.content.ContentResolver;
-import android.content.Context;
 import android.graphics.Matrix;
 import android.graphics.Path;
 import android.graphics.Rect;
 import android.os.Bundle;
-import android.os.ParcelFileDescriptor;
 import android.os.SystemClock;
-import android.provider.Settings;
 import android.test.ActivityInstrumentationTestCase2;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
-import android.view.accessibility.AccessibilityManager;
 import android.widget.TextView;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -45,13 +35,11 @@
  */
 public class AccessibilityGestureDispatchTest extends
         ActivityInstrumentationTestCase2<AccessibilityGestureDispatchTest.GestureDispatchActivity> {
-    // Match com.android.server.accessibility.AccessibilityManagerService#COMPONENT_NAME_SEPARATOR
-    private static final String COMPONENT_NAME_SEPARATOR = ":";
-    private static final int TIMEOUT_FOR_SERVICE_ENABLE = 10000; // millis; 10s
     private static final int GESTURE_COMPLETION_TIMEOUT = 5000; // millis
     private static final int MOTION_EVENT_TIMEOUT = 1000; // millis
 
     final List<MotionEvent> mMotionEvents = new ArrayList<>();
+    StubGestureAccessibilityService mService;
     MyTouchListener mMyTouchListener = new MyTouchListener();
     MyGestureCallback mCallback;
     TextView mFullScreenTextView;
@@ -65,33 +53,26 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
+
         mFullScreenTextView =
                 (TextView) getActivity().findViewById(R.id.full_screen_text_view);
-        getInstrumentation().runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mFullScreenTextView.getGlobalVisibleRect(mViewBounds);
-                mFullScreenTextView.setOnTouchListener(mMyTouchListener);
-            }
+        getInstrumentation().runOnMainSync(() -> {
+            mFullScreenTextView.getGlobalVisibleRect(mViewBounds);
+            mFullScreenTextView.setOnTouchListener(mMyTouchListener);
         });
-        Context context = getInstrumentation().getContext();
-        UiAutomation uiAutomation = getInstrumentation()
-                .getUiAutomation(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
-        ParcelFileDescriptor fd = uiAutomation.executeShellCommand(
-                "pm grant " + context.getPackageName()
-                        + "android.permission.WRITE_SECURE_SETTINGS");
-        uiAutomation.destroy();
-        fd.close();
-        turnAccessibilityOff();
-        enableService();
+
+        mService = StubGestureAccessibilityService.enableSelf(this);
+
         mMotionEvents.clear();
         mCallback = new MyGestureCallback();
         mGotUpEvent = false;
     }
 
     @Override
-    public void tearDown() {
-        turnAccessibilityOff();
+    public void tearDown() throws Exception {
+        mService.runOnServiceSync(() -> mService.disableSelf());
+
+        super.tearDown();
     }
 
     public void testClickAt_producesDownThenUp() throws InterruptedException {
@@ -100,8 +81,7 @@
         int clickX = clickXInsideView + mViewBounds.left;
         int clickY = clickYInsideView + mViewBounds.top;
         GestureDescription click = createClick(clickX, clickY);
-        assertTrue(StubGestureAccessibilityService.sConnectedInstance
-                .doDispatchGesture(click, mCallback, null));
+        mService.runOnServiceSync(() -> mService.doDispatchGesture(click, mCallback, null));
         mCallback.assertGestureCompletes(GESTURE_COMPLETION_TIMEOUT);
         waitForMotionEvents(3);
 
@@ -148,8 +128,7 @@
         int clickX = clickXInsideView + mViewBounds.left;
         int clickY = clickYInsideView + mViewBounds.top;
         GestureDescription longClick = createLongClick(clickX, clickY);
-        assertTrue(StubGestureAccessibilityService.sConnectedInstance
-                .doDispatchGesture(longClick, mCallback, null));
+        mService.runOnServiceSync(() -> mService.doDispatchGesture(longClick, mCallback, null));
         mCallback.assertGestureCompletes(
                 ViewConfiguration.getLongPressTimeout() + GESTURE_COMPLETION_TIMEOUT);
 
@@ -190,8 +169,7 @@
         float swipeTolerance = 2.0f;
 
         GestureDescription swipe = createSwipe(startX, startY, endX, endY, gestureTime);
-        assertTrue(StubGestureAccessibilityService.sConnectedInstance
-                .doDispatchGesture(swipe, mCallback, null));
+        mService.runOnServiceSync(() -> mService.doDispatchGesture(swipe, mCallback, null));
         mCallback.assertGestureCompletes(gestureTime + GESTURE_COMPLETION_TIMEOUT);
         waitForUpEvent();
         int numEvents = mMotionEvents.size();
@@ -234,8 +212,7 @@
         int gestureTime = 1000;
 
         GestureDescription swipe = createSwipe(startX, startY, endX, endY, gestureTime);
-        assertTrue(StubGestureAccessibilityService.sConnectedInstance
-                .doDispatchGesture(swipe, mCallback, null));
+        mService.runOnServiceSync(() -> mService.doDispatchGesture(swipe, mCallback, null));
         mCallback.assertGestureCompletes(gestureTime + GESTURE_COMPLETION_TIMEOUT);
         waitForUpEvent();
 
@@ -272,8 +249,7 @@
 
         GestureDescription pinch = createPinch(centerX, centerY, startSpacing,
                 endSpacing, 45.0F, gestureTime);
-        assertTrue(StubGestureAccessibilityService.sConnectedInstance
-                .doDispatchGesture(pinch, mCallback, null));
+        mService.runOnServiceSync(() -> mService.doDispatchGesture(pinch, mCallback, null));
         mCallback.assertGestureCompletes(gestureTime + GESTURE_COMPLETION_TIMEOUT);
         waitForUpEvent();
         int numEvents = mMotionEvents.size();
@@ -335,76 +311,6 @@
         }
     }
 
-    private void enableService() throws IOException {
-        Context context = getInstrumentation().getContext();
-        AccessibilityManager manager =
-                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
-        List<AccessibilityServiceInfo> serviceInfos =
-                manager.getInstalledAccessibilityServiceList();
-        for (int i = 0; i < serviceInfos.size(); i++) {
-            AccessibilityServiceInfo serviceInfo = serviceInfos.get(i);
-            if (context.getString(R.string.stub_gesture_a11y_service_description)
-                    .equals(serviceInfo.getDescription())) {
-                ContentResolver cr = context.getContentResolver();
-                String enabledServices = Settings.Secure.getString(cr,
-                        Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
-                Settings.Secure.putString(cr, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
-                        enabledServices + COMPONENT_NAME_SEPARATOR + serviceInfo.getId());
-                Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_ENABLED, 1);
-                long timeoutTimeMillis = SystemClock.uptimeMillis() + TIMEOUT_FOR_SERVICE_ENABLE;
-                while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
-                    synchronized(StubGestureAccessibilityService.sWaitObjectForConnecting) {
-                        if (StubGestureAccessibilityService.sConnectedInstance != null) {
-                            return;
-                        }
-                        try {
-                            StubGestureAccessibilityService.sWaitObjectForConnecting.wait(
-                                    timeoutTimeMillis - SystemClock.uptimeMillis());
-                        } catch (InterruptedException e) {
-                            // Ignored; loop again
-                        }
-                    }
-                }
-                throw new RuntimeException("Stub accessibility service not starting");
-            }
-        }
-        throw new RuntimeException("Stub accessibility service not found");
-    }
-
-    private void turnAccessibilityOff() {
-        final Object waitLockForA11yOff = new Object();
-        Context context = getInstrumentation().getContext();
-        AccessibilityManager manager =
-                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
-        manager.addAccessibilityStateChangeListener(
-                new AccessibilityManager.AccessibilityStateChangeListener() {
-                    @Override
-                    public void onAccessibilityStateChanged(boolean b) {
-                        synchronized (waitLockForA11yOff) {
-                            waitLockForA11yOff.notifyAll();
-                        }
-                    }
-                });
-        ContentResolver cr = context.getContentResolver();
-        Settings.Secure.putString(
-                cr, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, null);
-        StubGestureAccessibilityService.sConnectedInstance = null;
-        long timeoutTimeMillis = SystemClock.uptimeMillis() + TIMEOUT_FOR_SERVICE_ENABLE;
-        while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
-            synchronized (waitLockForA11yOff) {
-                if (!manager.isEnabled()) {
-                    return;
-                }
-                try {
-                    waitLockForA11yOff.wait(timeoutTimeMillis - SystemClock.uptimeMillis());
-                } catch (InterruptedException e) {
-                    // Ignored; loop again
-                }
-            }
-        }
-        throw new RuntimeException("Unable to turn accessibility off");
-    }
-
     public static class GestureDispatchActivity extends AccessibilityTestActivity {
         public GestureDispatchActivity() {
             super();
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
new file mode 100644
index 0000000..c021922
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityMagnificationTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.accessibilityservice.cts;
+
+import android.accessibilityservice.AccessibilityService.MagnificationController;
+import android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener;
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.res.Resources;
+import android.graphics.Region;
+import android.test.InstrumentationTestCase;
+import android.util.DisplayMetrics;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * Class for testing {@link AccessibilityServiceInfo}.
+ */
+public class AccessibilityMagnificationTest extends InstrumentationTestCase {
+
+    /** Maximum timeout when waiting for a magnification callback. */
+    public static final int LISTENER_TIMEOUT_MILLIS = 500;
+
+    private StubMagnificationAccessibilityService mService;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        mService = StubMagnificationAccessibilityService.enableSelf(this);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mService.runOnServiceSync(() -> mService.disableSelf());
+        mService = null;
+
+        super.tearDown();
+    }
+
+    public void testSetScale() {
+        final MagnificationController controller = mService.getMagnificationController();
+        final float scale = 2.0f;
+        final AtomicBoolean result = new AtomicBoolean();
+
+        mService.runOnServiceSync(() -> result.set(controller.setScale(scale, false)));
+
+        assertTrue("Failed to set scale", result.get());
+        assertEquals("Failed to apply scale", scale, controller.getScale());
+
+        mService.runOnServiceSync(() -> result.set(controller.reset(false)));
+
+        assertTrue("Failed to reset", result.get());
+        assertEquals("Failed to apply reset", 1.0f, controller.getScale());
+    }
+
+    public void testSetScaleAndCenter() {
+        final MagnificationController controller = mService.getMagnificationController();
+        final Resources res = getInstrumentation().getTargetContext().getResources();
+        final DisplayMetrics metrics = res.getDisplayMetrics();
+        final float scale = 2.0f;
+        final float x = metrics.widthPixels / 2.0f;
+        final float y = metrics.heightPixels / 2.0f;
+        final AtomicBoolean setScale = new AtomicBoolean();
+        final AtomicBoolean setCenter = new AtomicBoolean();
+        final AtomicBoolean result = new AtomicBoolean();
+
+        mService.runOnServiceSync(() -> {
+            setScale.set(controller.setScale(scale, false));
+            setCenter.set(controller.setCenter(x, y, false));
+        });
+
+        assertTrue("Failed to set scale", setScale.get());
+        assertEquals("Failed to apply scale", scale, controller.getScale());
+
+        assertTrue("Failed to set center", setCenter.get());
+        assertEquals("Failed to apply center X", x, controller.getCenterX());
+        assertEquals("Failed to apply center Y", y, controller.getCenterY());
+
+        mService.runOnServiceSync(() -> result.set(controller.reset(false)));
+
+        assertTrue("Failed to reset", result.get());
+        assertEquals("Failed to apply reset", 1.0f, controller.getScale());
+    }
+
+    public void testListener() {
+        final MagnificationController controller = mService.getMagnificationController();
+        final OnMagnificationChangedListener listener = mock(OnMagnificationChangedListener.class);
+        controller.addListener(listener);
+
+        try {
+            final float scale = 2.0f;
+            final AtomicBoolean result = new AtomicBoolean();
+
+            mService.runOnServiceSync(() -> result.set(controller.setScale(scale, false)));
+
+            assertTrue("Failed to set scale", result.get());
+            verify(listener, timeout(LISTENER_TIMEOUT_MILLIS).atLeastOnce()).onMagnificationChanged(
+                    eq(controller), any(Region.class), eq(scale), anyFloat(), anyFloat());
+
+            mService.runOnServiceSync(() -> result.set(controller.reset(false)));
+
+            assertTrue("Failed to reset", result.get());
+            verify(listener, timeout(LISTENER_TIMEOUT_MILLIS).atLeastOnce()).onMagnificationChanged(
+                    eq(controller), any(Region.class), eq(1.0f), anyFloat(), anyFloat());
+        } finally {
+            controller.removeListener(listener);
+        }
+    }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/InstrumentedAccessibilityService.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/InstrumentedAccessibilityService.java
new file mode 100644
index 0000000..2aeb5b8
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/InstrumentedAccessibilityService.java
@@ -0,0 +1,179 @@
+package android.accessibilityservice.cts;
+
+import android.accessibilityservice.AccessibilityService;
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.Context;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.test.InstrumentationTestCase;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+public class InstrumentedAccessibilityService extends AccessibilityService {
+    // Match com.android.server.accessibility.AccessibilityManagerService#COMPONENT_NAME_SEPARATOR
+    private static final String COMPONENT_NAME_SEPARATOR = ":";
+
+    private static final int TIMEOUT_SERVICE_ENABLE = 10000;
+    private static final int TIMEOUT_SERVICE_PERFORM_SYNC = 5000;
+
+    private static final HashMap<Class, WeakReference<InstrumentedAccessibilityService>>
+            sInstances = new HashMap<>();
+
+    private final Handler mHandler = new Handler();
+
+    @Override
+    protected void onServiceConnected() {
+        synchronized (sInstances) {
+            sInstances.put(getClass(), new WeakReference<>(this));
+            sInstances.notifyAll();
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        synchronized (sInstances) {
+            sInstances.remove(getClass());
+        }
+    }
+
+    @Override
+    public void onAccessibilityEvent(AccessibilityEvent event) {
+        // Stub method.
+    }
+
+    @Override
+    public void onInterrupt() {
+        // Stub method.
+    }
+
+    public void runOnServiceSync(Runnable runner) {
+        final SyncRunnable sr = new SyncRunnable(runner, TIMEOUT_SERVICE_PERFORM_SYNC);
+        mHandler.post(sr);
+        assertTrue("Timed out waiting for runOnServiceSync()", sr.waitForComplete());
+    }
+
+    private static final class SyncRunnable implements Runnable {
+        private final CountDownLatch mLatch = new CountDownLatch(1);
+        private final Runnable mTarget;
+        private final long mTimeout;
+
+        public SyncRunnable(Runnable target, long timeout) {
+            mTarget = target;
+            mTimeout = timeout;
+        }
+
+        public void run() {
+            mTarget.run();
+            mLatch.countDown();
+        }
+
+        public boolean waitForComplete() {
+            try {
+                return mLatch.await(mTimeout, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException e) {
+                return false;
+            }
+        }
+    }
+
+    protected static <T extends InstrumentedAccessibilityService> T enableService(
+            InstrumentationTestCase testCase, Class<T> clazz) {
+        final String serviceName = clazz.getSimpleName();
+        final Context context = testCase.getInstrumentation().getContext();
+        final String enabledServices = Settings.Secure.getString(
+                context.getContentResolver(),
+                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+        assertFalse("Service is already enabled", enabledServices.contains(serviceName));
+
+        final AccessibilityManager manager = (AccessibilityManager) context.getSystemService(
+                Context.ACCESSIBILITY_SERVICE);
+        final List<AccessibilityServiceInfo> serviceInfos =
+                manager.getInstalledAccessibilityServiceList();
+        for (AccessibilityServiceInfo serviceInfo : serviceInfos) {
+            final String serviceId = serviceInfo.getId();
+            if (serviceId.endsWith(serviceName)) {
+                ShellCommandBuilder.create(testCase)
+                        .putSecureSetting(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                                enabledServices + COMPONENT_NAME_SEPARATOR + serviceId)
+                        .putSecureSetting(Settings.Secure.ACCESSIBILITY_ENABLED, "1")
+                        .run();
+
+                final T instance = getInstanceForClass(clazz, TIMEOUT_SERVICE_ENABLE);
+                if (instance == null) {
+                    throw new RuntimeException("Starting accessibility service " + serviceName
+                            + " took longer than " + TIMEOUT_SERVICE_ENABLE + "ms");
+                }
+                return instance;
+            }
+        }
+        throw new RuntimeException("Accessibility service " + serviceName + " not found");
+    }
+
+    private static <T extends InstrumentedAccessibilityService> T getInstanceForClass(Class clazz,
+            long timeoutMillis) {
+        final long timeoutTimeMillis = SystemClock.uptimeMillis() + timeoutMillis;
+        while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
+            synchronized (sInstances) {
+                final WeakReference<InstrumentedAccessibilityService> ref = sInstances.get(clazz);
+                if (ref != null) {
+                    final T instance = (T) ref.get();
+                    if (instance == null) {
+                        sInstances.remove(clazz);
+                    } else {
+                        return instance;
+                    }
+                }
+                try {
+                    sInstances.wait(timeoutTimeMillis - SystemClock.uptimeMillis());
+                } catch (InterruptedException e) {
+                    return null;
+                }
+            }
+        }
+        return null;
+    }
+
+    public static void disableAllServices(InstrumentationTestCase testCase) {
+        final Object waitLockForA11yOff = new Object();
+        final Context context = testCase.getInstrumentation().getContext();
+        final AccessibilityManager manager =
+                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+        manager.addAccessibilityStateChangeListener(b -> {
+            synchronized (waitLockForA11yOff) {
+                waitLockForA11yOff.notifyAll();
+            }
+        });
+
+        ShellCommandBuilder.create(testCase)
+                .deleteSecureSetting(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES)
+                .deleteSecureSetting(Settings.Secure.ACCESSIBILITY_ENABLED)
+                .run();
+
+        final long timeoutTimeMillis = SystemClock.uptimeMillis() + TIMEOUT_SERVICE_ENABLE;
+        while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
+            synchronized (waitLockForA11yOff) {
+                if (manager.getEnabledAccessibilityServiceList(
+                        AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) {
+                    return;
+                }
+                try {
+                    waitLockForA11yOff.wait(timeoutTimeMillis - SystemClock.uptimeMillis());
+                } catch (InterruptedException e) {
+                    // Ignored; loop again
+                }
+            }
+        }
+        throw new RuntimeException("Disabling all accessibility services took longer than "
+                + TIMEOUT_SERVICE_ENABLE + "ms");
+    }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/ShellCommandBuilder.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/ShellCommandBuilder.java
new file mode 100644
index 0000000..7509f18
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/ShellCommandBuilder.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.accessibilityservice.cts;
+
+import android.app.UiAutomation;
+import android.os.ParcelFileDescriptor;
+import android.test.InstrumentationTestCase;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedList;
+
+public class ShellCommandBuilder {
+    private final LinkedList<String> mCommands = new LinkedList<>();
+
+    private final InstrumentationTestCase mTestCase;
+
+    public static ShellCommandBuilder create(InstrumentationTestCase testCase) {
+        return new ShellCommandBuilder(testCase);
+    }
+
+    private ShellCommandBuilder(InstrumentationTestCase testCase) {
+        mTestCase = testCase;
+    }
+
+    public void run() {
+        final UiAutomation automation = getUiAutomationSafe(mTestCase);
+        for (String command : mCommands) {
+            execShellCommand(automation, command);
+        }
+    }
+
+    public ShellCommandBuilder deleteSecureSetting(String name) {
+        mCommands.add("settings delete secure " + name);
+        return this;
+    }
+
+    public ShellCommandBuilder putSecureSetting(String name, String value) {
+        mCommands.add("settings put secure " + name + " " + value);
+        return this;
+    }
+
+    public ShellCommandBuilder grantPermission(String packageName, String permission) {
+        mCommands.add("pm grant " + packageName + " " + permission);
+        return this;
+    }
+
+    public ShellCommandBuilder addCommand(String command) {
+        mCommands.add(command);
+        return this;
+    }
+
+    private static UiAutomation getUiAutomationSafe(InstrumentationTestCase testCase) {
+        UiAutomation uiAutomation;
+        try {
+            uiAutomation = getUiAutomation(testCase);
+        } catch (RuntimeException e) {
+            // Clean up UI Automation after other tests as we cannot request UI Automation with
+            // different flags if one already exists.
+            uiAutomation = testCase.getInstrumentation().getUiAutomation();
+            uiAutomation.destroy();
+
+            // Try to get UI Automation again.
+            uiAutomation = getUiAutomation(testCase);
+        }
+        return uiAutomation;
+    }
+
+    private static UiAutomation getUiAutomation(InstrumentationTestCase testCase) {
+        return testCase.getInstrumentation().getUiAutomation(
+                UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
+    }
+
+    private static void execShellCommand(UiAutomation automation, String command) {
+        try (ParcelFileDescriptor fd = automation.executeShellCommand(command)) {
+            try (InputStream inputStream = new FileInputStream(fd.getFileDescriptor())) {
+                try (BufferedReader reader = new BufferedReader(
+                        new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
+                    while (reader.readLine() != null) {
+                        // Keep reading.
+                    }
+                }
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to exec shell command", e);
+        }
+    }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/StubGestureAccessibilityService.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/StubGestureAccessibilityService.java
index 40f62a83..caf5ab3 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/StubGestureAccessibilityService.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/StubGestureAccessibilityService.java
@@ -14,45 +14,25 @@
 
 package android.accessibilityservice.cts;
 
-import android.accessibilityservice.AccessibilityService;
-import android.accessibilityservice.AccessibilityService.GestureResultCallback;
 import android.accessibilityservice.GestureDescription;
 import android.os.Handler;
+import android.test.InstrumentationTestCase;
 import android.view.accessibility.AccessibilityEvent;
 
+import java.io.IOException;
+
 /**
  * A stub accessibility service to install for testing gesture dispatch
  */
-public class StubGestureAccessibilityService extends AccessibilityService {
-    public static Object sWaitObjectForConnecting = new Object();
-
-    public static StubGestureAccessibilityService sConnectedInstance;
-
-    @Override
-    public void onDestroy() {
-        sConnectedInstance = null;
-    }
-
-    @Override
-    public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
-
-    }
-
-    @Override
-    public void onInterrupt() {
-
-    }
-
-    @Override
-    protected void onServiceConnected() {
-        synchronized (sWaitObjectForConnecting) {
-            sConnectedInstance = this;
-            sWaitObjectForConnecting.notifyAll();
-        }
-    }
+public class StubGestureAccessibilityService extends InstrumentedAccessibilityService {
 
     public boolean doDispatchGesture(GestureDescription description, GestureResultCallback callback,
             Handler handler) {
         return dispatchGesture(description, callback, handler);
     }
+
+    public static StubGestureAccessibilityService enableSelf(InstrumentationTestCase test) {
+        return InstrumentedAccessibilityService.enableService(
+                test, StubGestureAccessibilityService.class);
+    }
 }
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/StubMagnificationAccessibilityService.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/StubMagnificationAccessibilityService.java
new file mode 100644
index 0000000..e5e1949
--- /dev/null
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/StubMagnificationAccessibilityService.java
@@ -0,0 +1,33 @@
+/**
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.accessibilityservice.cts;
+
+import android.accessibilityservice.GestureDescription;
+import android.os.Handler;
+import android.test.InstrumentationTestCase;
+import android.view.accessibility.AccessibilityEvent;
+
+import java.io.IOException;
+
+/**
+ * A stub accessibility service to install for testing gesture dispatch
+ */
+public class StubMagnificationAccessibilityService extends InstrumentedAccessibilityService {
+
+    public static StubMagnificationAccessibilityService enableSelf(InstrumentationTestCase test) {
+        return InstrumentedAccessibilityService.enableService(
+                test, StubMagnificationAccessibilityService.class);
+    }
+}
diff --git a/tests/app/src/android/app/cts/PipActivityTest.java b/tests/app/src/android/app/cts/PipActivityTest.java
index 3f053cb..1a10a5d 100644
--- a/tests/app/src/android/app/cts/PipActivityTest.java
+++ b/tests/app/src/android/app/cts/PipActivityTest.java
@@ -44,20 +44,20 @@
                 final boolean supportsPip =
                         mActivity.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
                 if (supportsPip) {
-                    mActivity.enterPictureInPicture();
-                    assertTrue(mActivity.inMultiWindow());
-                    assertTrue(mActivity.inPictureInPicture());
+                    mActivity.enterPictureInPictureMode();
+                    assertTrue(mActivity.isInMultiWindowMode());
+                    assertTrue(mActivity.isInPictureInPictureMode());
                 } else {
                     boolean pipSupportDisabled = false;
                     try {
-                        mActivity.enterPictureInPicture();
+                        mActivity.enterPictureInPictureMode();
                     } catch (IllegalStateException e) {
                         // Pip not supported
                         pipSupportDisabled = true;
                     }
                     assertTrue(pipSupportDisabled);
-                    assertFalse(mActivity.inMultiWindow());
-                    assertFalse(mActivity.inPictureInPicture());
+                    assertFalse(mActivity.isInMultiWindowMode());
+                    assertFalse(mActivity.isInPictureInPictureMode());
                 }
             }
         });
diff --git a/tests/app/src/android/app/cts/PipNotResizeableActivityTest.java b/tests/app/src/android/app/cts/PipNotResizeableActivityTest.java
index e2908cd..7189dc1 100644
--- a/tests/app/src/android/app/cts/PipNotResizeableActivityTest.java
+++ b/tests/app/src/android/app/cts/PipNotResizeableActivityTest.java
@@ -42,7 +42,7 @@
                 public void run() {
                     boolean pipSupportDisabled = false;
                     try {
-                        mActivity.enterPictureInPicture();
+                        mActivity.enterPictureInPictureMode();
                     } catch (IllegalStateException e) {
                         // Pip not supported
                         pipSupportDisabled = true;
@@ -51,8 +51,8 @@
                         pipSupportDisabled = true;
                     }
                     assertTrue(pipSupportDisabled);
-                    assertFalse(mActivity.inMultiWindow());
-                    assertFalse(mActivity.inPictureInPicture());
+                    assertFalse(mActivity.isInMultiWindowMode());
+                    assertFalse(mActivity.isInPictureInPictureMode());
                 }
             });
             mInstrumentation.waitForIdleSync();
diff --git a/tests/app/src/android/app/cts/PipNotSupportedActivityTest.java b/tests/app/src/android/app/cts/PipNotSupportedActivityTest.java
index c9ce69c..e8d13dc 100644
--- a/tests/app/src/android/app/cts/PipNotSupportedActivityTest.java
+++ b/tests/app/src/android/app/cts/PipNotSupportedActivityTest.java
@@ -42,7 +42,7 @@
             public void run() {
                 boolean pipSupportDisabled = false;
                 try {
-                    mActivity.enterPictureInPicture();
+                    mActivity.enterPictureInPictureMode();
                 } catch (IllegalStateException e) {
                     // Pip not supported
                     pipSupportDisabled = true;
@@ -51,8 +51,8 @@
                     pipSupportDisabled = true;
                 }
                 assertTrue(pipSupportDisabled);
-                assertFalse(mActivity.inMultiWindow());
-                assertFalse(mActivity.inPictureInPicture());
+                assertFalse(mActivity.isInMultiWindowMode());
+                assertFalse(mActivity.isInPictureInPictureMode());
             }
         });
         mInstrumentation.waitForIdleSync();
diff --git a/tests/app/src/android/app/cts/SystemFeaturesTest.java b/tests/app/src/android/app/cts/SystemFeaturesTest.java
index c34ecdf..864f1be 100644
--- a/tests/app/src/android/app/cts/SystemFeaturesTest.java
+++ b/tests/app/src/android/app/cts/SystemFeaturesTest.java
@@ -421,22 +421,22 @@
      * Check that the {@link TelephonyManager#getPhoneType()} matches the reported features.
      */
     public void testTelephonyFeatures() {
+        if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+            return;
+        }
+
         int phoneType = mTelephonyManager.getPhoneType();
         switch (phoneType) {
             case TelephonyManager.PHONE_TYPE_GSM:
-                assertAvailable(PackageManager.FEATURE_TELEPHONY);
                 assertAvailable(PackageManager.FEATURE_TELEPHONY_GSM);
                 break;
 
             case TelephonyManager.PHONE_TYPE_CDMA:
-                assertAvailable(PackageManager.FEATURE_TELEPHONY);
                 assertAvailable(PackageManager.FEATURE_TELEPHONY_CDMA);
                 break;
 
             case TelephonyManager.PHONE_TYPE_NONE:
-                assertNotAvailable(PackageManager.FEATURE_TELEPHONY);
-                assertNotAvailable(PackageManager.FEATURE_TELEPHONY_CDMA);
-                assertNotAvailable(PackageManager.FEATURE_TELEPHONY_GSM);
+                fail("FEATURE_TELEPHONY is present; phone type should not be PHONE_TYPE_NONE");
                 break;
 
             default:
diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
index 5f80001..f9ff6ba 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
@@ -969,7 +969,8 @@
                 CaptureRequest request = videoSnapshotRequestBuilder.build();
 
                 // Start recording
-                startRecording(/* useMediaRecorder */true, resultListener, /*useVideoStab*/false);
+                startRecording(/* useMediaRecorder */true, resultListener,
+                        /*useVideoStab*/mStaticInfo.isVideoStabilizationSupported());
                 long startTime = SystemClock.elapsedRealtime();
 
                 // Record certain duration.
@@ -1198,10 +1199,6 @@
         mRecordingStartTime = SystemClock.elapsedRealtime();
     }
 
-    private void startRecording(boolean useMediaRecorder)  throws Exception {
-        startRecording(useMediaRecorder, /*listener*/null, /*useVideoStab*/false);
-    }
-
     private void stopCameraStreaming() throws Exception {
         if (VERBOSE) {
             Log.v(TAG, "Stopping camera streaming and waiting for idle");
diff --git a/tests/deviceadmin/Android.mk b/tests/deviceadmin/Android.mk
new file mode 100644
index 0000000..3d02f9c
--- /dev/null
+++ b/tests/deviceadmin/Android.mk
@@ -0,0 +1,17 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/uiautomator/app/Android.mk b/tests/deviceadmin/deviceadminapp/Android.mk
similarity index 73%
rename from tests/uiautomator/app/Android.mk
rename to tests/deviceadmin/deviceadminapp/Android.mk
index 4fe2688..6ee3943 100644
--- a/tests/uiautomator/app/Android.mk
+++ b/tests/deviceadmin/deviceadminapp/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2012 The Android Open Source Project
+# Copyright (C) 2016 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -16,21 +16,19 @@
 
 include $(CLEAR_VARS)
 
+LOCAL_PACKAGE_NAME := CtsEmptyDeviceAdmin
+
 LOCAL_MODULE_TAGS := optional
+
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
+LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res
+
 LOCAL_SDK_VERSION := current
 
-LOCAL_PACKAGE_NAME := CtsUiAutomatorTestApp
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4
-
-# Tag this module as a cts test artifact
+# tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/deviceadmin/deviceadminapp/AndroidManifest.xml b/tests/deviceadmin/deviceadminapp/AndroidManifest.xml
new file mode 100644
index 0000000..9ce61a6
--- /dev/null
+++ b/tests/deviceadmin/deviceadminapp/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="android.devicepolicy.cts.emptydeviceadmin" >
+
+    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="24"/>
+
+    <application>
+        <receiver
+                android:name=".EmptyDeviceAdmin"
+                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>
+    </application>
+</manifest>
diff --git a/tests/deviceadmin/deviceadminapp/res/xml/device_admin.xml b/tests/deviceadmin/deviceadminapp/res/xml/device_admin.xml
new file mode 100644
index 0000000..c601371
--- /dev/null
+++ b/tests/deviceadmin/deviceadminapp/res/xml/device_admin.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<device-admin xmlns:android="http://schemas.android.com/apk/res/android" android:visible="false">
+    <uses-policies>
+        <limit-password />
+        <watch-login />
+        <reset-password />
+        <force-lock />
+        <wipe-data />
+        <expire-password />
+        <encrypted-storage />
+        <disable-camera />
+        <disable-keyguard-features />
+    </uses-policies>
+</device-admin>
diff --git a/tests/uiautomator/app/res/values/styles.xml b/tests/deviceadmin/deviceadminapp/src/android/devicepolicy/cts/emptydeviceadmin/EmptyDeviceAdmin.java
similarity index 71%
copy from tests/uiautomator/app/res/values/styles.xml
copy to tests/deviceadmin/deviceadminapp/src/android/devicepolicy/cts/emptydeviceadmin/EmptyDeviceAdmin.java
index bce88ae..82339ef 100644
--- a/tests/uiautomator/app/res/values/styles.xml
+++ b/tests/deviceadmin/deviceadminapp/src/android/devicepolicy/cts/emptydeviceadmin/EmptyDeviceAdmin.java
@@ -1,7 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- * Copyright (C) 2011 The Android Open Source Project
+/*
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,9 +12,10 @@
  * WITHOUT 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>
+ */
+package android.devicepolicy.cts.emptydeviceadmin;
 
-    <style name="AppTheme" parent="android:Theme.Light" />
+import android.app.admin.DeviceAdminReceiver;
 
-</resources>
+public class EmptyDeviceAdmin extends DeviceAdminReceiver {
+}
diff --git a/tests/uiautomator/app/Android.mk b/tests/deviceadmin/uninstalltest/Android.mk
similarity index 73%
copy from tests/uiautomator/app/Android.mk
copy to tests/deviceadmin/uninstalltest/Android.mk
index 4fe2688..ceee809 100644
--- a/tests/uiautomator/app/Android.mk
+++ b/tests/deviceadmin/uninstalltest/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2012 The Android Open Source Project
+# Copyright (C) 2016 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -16,21 +16,19 @@
 
 include $(CLEAR_VARS)
 
+LOCAL_PACKAGE_NAME := CtsDeviceAdminUninstallerTestCases
+
 LOCAL_MODULE_TAGS := optional
+
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
+LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator android-support-test
+
 LOCAL_SDK_VERSION := current
 
-LOCAL_PACKAGE_NAME := CtsUiAutomatorTestApp
-LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4
-
-# Tag this module as a cts test artifact
+# tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
 
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_DEX_PREOPT := false
-
-include $(BUILD_CTS_SUPPORT_PACKAGE)
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/deviceadmin/uninstalltest/AndroidManifest.xml b/tests/deviceadmin/uninstalltest/AndroidManifest.xml
new file mode 100644
index 0000000..52a681a
--- /dev/null
+++ b/tests/deviceadmin/uninstalltest/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="android.devicepolicy.cts.uiautomatertest" >
+
+    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="24"/>
+
+    <application>
+        <uses-library android:name="android.test.runner"/>
+    </application>
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+          android:functionalTest="true"
+          android:targetPackage="android.devicepolicy.cts.uiautomatertest"
+          android:label="Device Admin Uninstall CTS tests"/>
+</manifest>
diff --git a/tests/deviceadmin/uninstalltest/AndroidTest.xml b/tests/deviceadmin/uninstalltest/AndroidTest.xml
new file mode 100644
index 0000000..51615f7
--- /dev/null
+++ b/tests/deviceadmin/uninstalltest/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for the CTS device admin uninstall tests">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="CtsEmptyDeviceAdmin.apk" />
+        <option name="test-file-name" value="CtsDeviceAdminUninstallerTestCases.apk" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="dpm set-active-admin --user cur android.devicepolicy.cts.emptydeviceadmin/.EmptyDeviceAdmin" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.devicepolicy.cts.uiautomatertest" />
+    </test>
+
+</configuration>
\ No newline at end of file
diff --git a/tests/deviceadmin/uninstalltest/src/android/devicepolicy/cts/uiautomatertest/DeviceAdminUninstallTest.java b/tests/deviceadmin/uninstalltest/src/android/devicepolicy/cts/uiautomatertest/DeviceAdminUninstallTest.java
new file mode 100644
index 0000000..23b3755
--- /dev/null
+++ b/tests/deviceadmin/uninstalltest/src/android/devicepolicy/cts/uiautomatertest/DeviceAdminUninstallTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.devicepolicy.cts.uiautomatertest;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.Uri;
+import android.provider.Settings;
+import android.widget.ScrollView;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.filters.LargeTest;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiScrollable;
+import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.Until;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class DeviceAdminUninstallTest {
+
+    private static final String DEVICE_ADMIN_PACKAGE_NAME =
+            "android.devicepolicy.cts.emptydeviceadmin";
+    private static final String URI_PACKAGE_PREFIX = "package:";
+
+    private static final UiSelector DEACTIVATE_AND_UNINSTALL_BUTTON_SELECTOR = new UiSelector()
+            .resourceId("com.android.settings:id/action_button");
+    private static final UiSelector UNINSTALL_BUTTON_SELECTOR = new UiSelector()
+            .resourceId("com.android.settings:id/left_button");
+    private static final BySelector UNINSTALL_BUTTON_BYSELECTOR = By
+            .res("com.android.settings", "left_button");
+    private static final UiSelector OK_BUTTON_SELECTOR = new UiSelector()
+            .resourceId("android:id/button1");
+    private static final long DEACTIVATE_ADMIN_TIMEOUT = 15000;
+    private static final long WAIT_FOR_ACTIVITY_TIMEOUT = 6000;
+
+    private UiDevice mUiDevice;
+    private Context mContext;
+    private DevicePolicyManager mDpm;
+    private PackageManager mPm;
+
+    @Before
+    public void setUp() throws Exception {
+        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        mContext = InstrumentationRegistry.getTargetContext();
+        mDpm = mContext.getSystemService(DevicePolicyManager.class);
+        mPm = mContext.getPackageManager();
+    }
+
+    private boolean hasActiveAdmin() {
+        final List<ComponentName> activeAdmins = mDpm.getActiveAdmins();
+        if (activeAdmins == null) {
+            return false;
+        }
+        for (ComponentName activeAdmin : activeAdmins) {
+            if (DEVICE_ADMIN_PACKAGE_NAME.equals(activeAdmin.getPackageName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void waitTillNoActiveAdmin() {
+        boolean interrupted = false;
+        final long timeOut = System.currentTimeMillis() + DEACTIVATE_ADMIN_TIMEOUT;
+        while (hasActiveAdmin() && System.currentTimeMillis() <= timeOut) {
+            try {
+                Thread.sleep(2500);
+            } catch (InterruptedException err) {
+                interrupted = true;
+            }
+        }
+        if (interrupted) {
+            Thread.currentThread().interrupt();
+        }
+        Assert.assertFalse(
+                "Package " + DEVICE_ADMIN_PACKAGE_NAME + " still has an active device admin",
+                hasActiveAdmin());
+    }
+
+    private boolean packageExists() {
+        PackageInfo packageInfo = null;
+        try {
+            packageInfo = mPm.getPackageInfo(DEVICE_ADMIN_PACKAGE_NAME, 0);
+        } catch (NameNotFoundException exc) {
+        }
+        return packageInfo != null;
+    }
+
+    private void launchApplicationDetailsActivity() {
+        final Uri packageURI = Uri.parse(URI_PACKAGE_PREFIX + DEVICE_ADMIN_PACKAGE_NAME);
+        final Intent displayAppDetailsIntent = new Intent(
+                Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+                packageURI);
+        displayAppDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mContext.startActivity(displayAppDetailsIntent);
+    }
+
+    private void automateUninstallThroughUi() {
+        StringBuilder failMessageBuilder = new StringBuilder();
+        UiObject uninstallButton = mUiDevice
+                .findObject(UNINSTALL_BUTTON_SELECTOR);
+        UiScrollable scrollable = new UiScrollable(new UiSelector().className(ScrollView.class));
+        UiObject deactivateButton = mUiDevice
+                .findObject(DEACTIVATE_AND_UNINSTALL_BUTTON_SELECTOR);
+        UiObject okButton = mUiDevice
+                .findObject(OK_BUTTON_SELECTOR);
+        mUiDevice.wait(Until.hasObject(UNINSTALL_BUTTON_BYSELECTOR), WAIT_FOR_ACTIVITY_TIMEOUT);
+        try {
+            uninstallButton.clickAndWaitForNewWindow();
+            scrollable.scrollIntoView(DEACTIVATE_AND_UNINSTALL_BUTTON_SELECTOR);
+            deactivateButton.clickAndWaitForNewWindow();
+            waitTillNoActiveAdmin();
+            okButton.clickAndWaitForNewWindow();
+        } catch (UiObjectNotFoundException exc) {
+            failMessageBuilder.append(exc.getMessage());
+        } finally {
+            Assert.assertFalse(
+                    "Package " + DEVICE_ADMIN_PACKAGE_NAME + " was not uninstalled.\n"
+                    + failMessageBuilder.toString(), packageExists());
+        }
+    }
+
+    @Test
+    public void uninstallPackageWithActiveAdmin() {
+        Assert.assertTrue("Package " + DEVICE_ADMIN_PACKAGE_NAME + " was not found installed",
+                packageExists());
+        Assert.assertTrue("Package " + DEVICE_ADMIN_PACKAGE_NAME
+                + " does not have any active admin component", hasActiveAdmin());
+        launchApplicationDetailsActivity();
+        automateUninstallThroughUi();
+    }
+}
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 56475fd..9b3a09d 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -158,6 +158,14 @@
   bug: 17508787
 },
 {
+  description: "This test is not working on Android Player",
+  names: [
+    "com.android.cts.devicepolicy.MixedDeviceOwnerTest#testPackageInstallUserRestrictions",
+    "com.android.cts.devicepolicy.MixedProfileOwnerTest#testPackageInstallUserRestrictions"
+  ],
+  bug: 27949133
+},
+{
   description: "Test is not yet properly implemented",
   names: [
     "android.voicesettings.cts.ZenModeTest#testAll"
diff --git a/tests/jank/AndroidManifest.xml b/tests/jank/AndroidManifest.xml
index cbb4cba..f7b3232 100644
--- a/tests/jank/AndroidManifest.xml
+++ b/tests/jank/AndroidManifest.xml
@@ -19,6 +19,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="android.jank.cts">
 
+  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
   <application>
       <uses-library android:name="android.test.runner"/>
   </application>
diff --git a/tests/sample/AndroidManifest.xml b/tests/sample/AndroidManifest.xml
index b27e0d3..108321f 100755
--- a/tests/sample/AndroidManifest.xml
+++ b/tests/sample/AndroidManifest.xml
@@ -18,7 +18,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="android.sample.cts">
 
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
index 9860000..a005aa3 100644
--- a/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/ValueAnimatorTest.java
@@ -18,7 +18,6 @@
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.test.ActivityInstrumentationTestCase2;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.LinearInterpolator;
@@ -344,8 +343,6 @@
         animator.setCurrentPlayTime(150);
         EventWatcher watcher = new EventWatcher();
         animator.addListener(watcher);
-        UpdateListenerLatch updateListener = new UpdateListenerLatch();
-        animator.addUpdateListener(updateListener);
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -353,15 +350,8 @@
             }
         });
         assertTrue(watcher.start.await(0, TimeUnit.MILLISECONDS));
-        float startFraction = animator.getAnimatedFraction();
         assertTrue(((Float)animator.getAnimatedValue()) >= 0.5f);
-        assertTrue(startFraction >= 0.5f);
-        if (updateListener.updateLatch.getCount() == 0) {
-            updateListener.updateLatch = new CountDownLatch(1);
-        }
-        assertTrue(updateListener.updateLatch.await(100, TimeUnit.MILLISECONDS));
-        assertTrue(startFraction < animator.getAnimatedFraction());
-
+        assertTrue(animator.getAnimatedFraction() >= 0.5f);
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -455,13 +445,4 @@
             start.countDown();
         }
     }
-
-    class UpdateListenerLatch implements AnimatorUpdateListener {
-        public CountDownLatch updateLatch = new CountDownLatch(0);
-
-        @Override
-        public void onAnimationUpdate(ValueAnimator animation) {
-            updateLatch.countDown();
-        }
-    }
 }
diff --git a/tests/tests/assist/src/android/assist/cts/AssistStructureTest.java b/tests/tests/assist/src/android/assist/cts/AssistStructureTest.java
index c21bc9c..cc6e89a 100644
--- a/tests/tests/assist/src/android/assist/cts/AssistStructureTest.java
+++ b/tests/tests/assist/src/android/assist/cts/AssistStructureTest.java
@@ -79,7 +79,7 @@
         }
     }
 
-    public void testAssistStructure() throws Exception {
+    public void testAssistStructure() throws Throwable {
         if (mActivityManager.isLowRamDevice()) {
             Log.d(TAG, "Not running assist tests on low-RAM device.");
             return;
@@ -91,9 +91,13 @@
         startSession();
         waitForContext();
         verifyAssistDataNullness(false, false, false, false);
-
-        verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE),
-                false /*FLAG_SECURE set*/);
+        getInstrumentation().waitForIdleSync();
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                verifyAssistStructure(Utils.getTestAppComponent(TEST_CASE_TYPE), false /*FLAG_SECURE set*/);
+            }
+        });
     }
 
     private class AssistStructureTestBroadcastReceiver extends BroadcastReceiver {
diff --git a/tests/tests/calllog/src/android/calllog/cts/CallLogBackupTest.java b/tests/tests/calllog/src/android/calllog/cts/CallLogBackupTest.java
index 695a138..56cb3da 100644
--- a/tests/tests/calllog/src/android/calllog/cts/CallLogBackupTest.java
+++ b/tests/tests/calllog/src/android/calllog/cts/CallLogBackupTest.java
@@ -61,6 +61,8 @@
     private static final int CALL_START_TIME = 0;
     private static final int CALL_DURATION = 2000;
     private static final int TIMEOUT_BACKUP = 4000;
+    private static final String TEST_POST_DIAL_DIGITS = ";1234";
+    private static final String TEST_VIA_NUMBER = "555-1112";
 
     private static final Pattern BMGR_ENABLED_PATTERN = Pattern.compile(
             "^Backup Manager currently (enabled|disabled)$");
@@ -77,7 +79,9 @@
         CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME,
         CallLog.Calls.PHONE_ACCOUNT_ID,
         CallLog.Calls.DATA_USAGE,
-        CallLog.Calls.FEATURES
+        CallLog.Calls.FEATURES,
+        CallLog.Calls.POST_DIAL_DIGITS,
+        CallLog.Calls.VIA_NUMBER
     };
 
     class Call {
@@ -89,6 +93,8 @@
         String phoneAccountComponent;
         String phoneAccountId;
         int presentation;
+        String postDialDigits;
+        String viaNumber;
     }
 
     private String mCallLogBackupPackageName;
@@ -175,6 +181,8 @@
         assertEquals(CALL_START_TIME, call.date);
         assertEquals(CALL_DURATION, call.duration);
         assertEquals(Calls.OUTGOING_TYPE, call.type);
+        assertEquals(TEST_POST_DIAL_DIGITS, call.postDialDigits);
+        assertEquals(TEST_VIA_NUMBER, call.viaNumber);
         return call;
     }
 
@@ -248,6 +256,8 @@
         values.put(Calls.DATE, Long.valueOf(CALL_START_TIME));
         values.put(Calls.DURATION, Long.valueOf(CALL_DURATION));
         values.put(Calls.NEW, Integer.valueOf(1));
+        values.put(Calls.POST_DIAL_DIGITS, TEST_POST_DIAL_DIGITS);
+        values.put(Calls.VIA_NUMBER, TEST_VIA_NUMBER);
 
         getContext().getContentResolver().insert(Calls.CONTENT_URI, values);
     }
@@ -272,6 +282,10 @@
                             cursor.getColumnIndex(Calls.PHONE_ACCOUNT_ID));
                     call.presentation = cursor.getInt(
                             cursor.getColumnIndex(Calls.NUMBER_PRESENTATION));
+                    call.postDialDigits = cursor.getString(
+                            cursor.getColumnIndex(Calls.POST_DIAL_DIGITS));
+                    call.viaNumber = cursor.getString(
+                            cursor.getColumnIndex(Calls.VIA_NUMBER));
                     calls.add(call);
                 }
             } finally {
diff --git a/tests/tests/display/Android.mk b/tests/tests/display/Android.mk
index 2b81ec1..5de5610 100644
--- a/tests/tests/display/Android.mk
+++ b/tests/tests/display/Android.mk
@@ -27,7 +27,7 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test platform-test-annotations
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/tests/tests/display/src/android/display/cts/DisplayTest.java b/tests/tests/display/src/android/display/cts/DisplayTest.java
index 1f9f8d1..1d1db2b 100644
--- a/tests/tests/display/src/android/display/cts/DisplayTest.java
+++ b/tests/tests/display/src/android/display/cts/DisplayTest.java
@@ -28,6 +28,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
+import android.platform.test.annotations.Presubmit;
 import android.test.InstrumentationTestCase;
 import android.util.DisplayMetrics;
 import android.view.Display;
@@ -139,6 +140,7 @@
     /**
      * Verify that the WindowManager returns the default display.
      */
+    @Presubmit
     public void testDefaultDisplay() {
         assertEquals(Display.DEFAULT_DISPLAY, mWindowManager.getDefaultDisplay().getDisplayId());
     }
diff --git a/tests/tests/graphics/res/drawable/avd_single_frame.xml b/tests/tests/graphics/res/drawable/avd_single_frame.xml
new file mode 100644
index 0000000..483a0f3
--- /dev/null
+++ b/tests/tests/graphics/res/drawable/avd_single_frame.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+                 xmlns:android="http://schemas.android.com/apk/res/android">
+    <aapt:attr name="android:drawable">
+        <vector
+                android:width="32dp"
+                android:viewportWidth="32"
+                android:height="32dp"
+                android:viewportHeight="32">
+            <group
+                    android:name="btn_radio_to_off_mtrl_0"
+                    android:translateX="16"
+                    android:translateY="16">
+                <group
+                        android:name="ring_outer">
+                    <path
+                            android:name="ring_outer_path"
+                            android:fillColor="#FF000000"
+                            android:pathData="M 0.0,-9.0 c 4.9705627482,0.0 9.0,4.0294372518 9.0,9.0 c 0.0,4.9705627482 -4.0294372518,9.0 -9.0,9.0 c -4.9705627482,0.0 -9.0,-4.0294372518 -9.0,-9.0 c 0.0,-4.9705627482 4.0294372518,-9.0 9.0,-9.0 Z"/>
+                </group>
+            </group>
+        </vector>
+    </aapt:attr>
+    <target android:name="ring_outer_path">
+        <aapt:attr name="android:animation">
+            <set
+                    xmlns:android="http://schemas.android.com/apk/res/android" >
+                <objectAnimator
+                        android:duration="16"
+                        android:propertyName="fillColor"
+                        android:valueFrom="#f00"
+                        android:valueTo="#0f0"
+                        android:valueType="intType"
+                        android:interpolator="@interpolator/avd_single_frame_interpolator" />
+
+            </set>
+        </aapt:attr>
+    </target>
+</animated-vector>
\ No newline at end of file
diff --git a/tests/tests/graphics/res/interpolator/avd_single_frame_interpolator.xml b/tests/tests/graphics/res/interpolator/avd_single_frame_interpolator.xml
new file mode 100644
index 0000000..d3728c4
--- /dev/null
+++ b/tests/tests/graphics/res/interpolator/avd_single_frame_interpolator.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 c 0.4,0.0 0.4,1.0 1.0,1.0" />
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index 92f31b0..aa8348a 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -1171,6 +1171,11 @@
         }
 
         // TODO: when we support variation selectors, add positive tests
+
+        // Unicode 7.0, 8.0, and 9.0 emoji should be supported.
+        assertTrue(p.hasGlyph("\uD83D\uDD75"));  // SLEUTH OR SPY is introduced in Unicode 7.0
+        assertTrue(p.hasGlyph("\uD83C\uDF2E"));  // TACO is introduced in Unicode 8.0
+        assertTrue(p.hasGlyph("\uD83E\uDD33"));  // SELFIE is introduced in Unicode 9.0
     }
 
     public void testGetRunAdvance() {
@@ -1184,6 +1189,13 @@
                 assertEquals(0.0f, width);
             }
             {
+                for (int i = 0; i < string.length(); i++) {
+                    final float width = p.getRunAdvance(string, i, i + 1, 0, string.length(),
+                            false, i);
+                    assertEquals(0.0f, width);
+                }
+            }
+            {
                 final float widthToMid = p.getRunAdvance(string, 0, string.length(), 0,
                         string.length(), false, string.length() / 2);
                 final float widthToTail = p.getRunAdvance(string, 0, string.length(), 0,
@@ -1198,11 +1210,32 @@
                         string.length(), false, string.length());
                 assertTrue(widthFromHead > widthFromSecond);
             }
+            {
+                float width = 0.0f;
+                for (int i = 0; i < string.length(); i++) {
+                    width += p.getRunAdvance(string, i, i + 1, 0, string.length(), false, i + 1);
+                }
+                final float totalWidth = p.getRunAdvance(string, 0, string.length(), 0,
+                        string.length(), false, string.length());
+                assertEquals(totalWidth, width, 1.0f);
+            }
         }
         {
             // RTL
             String string = "\u0644\u063A\u0629 \u0639\u0631\u0628\u064A\u0629"; // Arabic
             {
+                final float width = p.getRunAdvance(string, 0, string.length(), 0,
+                        string.length(), true, 0);
+                assertEquals(0.0f, width);
+            }
+            {
+                for (int i = 0; i < string.length(); i++) {
+                    final float width = p.getRunAdvance(string, i, i + 1, 0, string.length(),
+                            true, i);
+                    assertEquals(0.0f, width);
+                }
+            }
+            {
                 final float widthToMid = p.getRunAdvance(string, 0, string.length(), 0,
                         string.length(), true, string.length() / 2);
                 final float widthToTail = p.getRunAdvance(string, 0, string.length(), 0,
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
index 92f3125..487eb3b 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
@@ -53,7 +53,6 @@
 
     private DrawableStubActivity mActivity;
     private Resources mResources;
-    private AnimatedVectorDrawable mAnimatedVectorDrawable;
     private Bitmap mBitmap;
     private Canvas mCanvas;
     private static final boolean DBG_DUMP_PNG = false;
@@ -72,7 +71,6 @@
 
         mBitmap = Bitmap.createBitmap(IMAGE_WIDTH, IMAGE_HEIGHT, Bitmap.Config.ARGB_8888);
         mCanvas = new Canvas(mBitmap);
-        mAnimatedVectorDrawable = new AnimatedVectorDrawable();
 
         mActivity = getActivity();
         mResources = mActivity.getResources();
@@ -125,11 +123,11 @@
         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);
+        AnimatedVectorDrawable drawable = new AnimatedVectorDrawable();
+        drawable.inflate(mResources, parser, attrs);
+        drawable.setBounds(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
         mBitmap.eraseColor(0);
-        mAnimatedVectorDrawable.draw(mCanvas);
+        drawable.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);
@@ -140,6 +138,35 @@
         }
     }
 
+    @MediumTest
+    public void testSingleFrameAnimation() throws Exception {
+        int resId = R.drawable.avd_single_frame;
+        final AnimatedVectorDrawable d1 =
+                (AnimatedVectorDrawable) mResources.getDrawable(resId);
+        // The AVD has a duration as 16ms.
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                d1.start();
+                d1.stop();
+
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+
+        d1.setBounds(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
+        mBitmap.eraseColor(0);
+        d1.draw(mCanvas);
+
+        int endColor = mBitmap.getPixel(IMAGE_WIDTH / 2, IMAGE_HEIGHT / 2);
+
+        assertEquals("Center point's color must be green", 0xFF00FF00, endColor);
+
+        if (DBG_DUMP_PNG) {
+            saveVectorDrawableIntoPNG(mBitmap, resId);
+        }
+    }
+
     @SmallTest
     public void testGetChangingConfigurations() {
         AnimatedVectorDrawable avd = new AnimatedVectorDrawable();
diff --git a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
index c991b6f..8bbf448 100644
--- a/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
+++ b/tests/tests/graphics/src/android/opengl/cts/OpenGlEsVersionTest.java
@@ -135,6 +135,54 @@
                 mActivity.getAepEs31Support());
     }
 
+    public void testOpenGlEsVersionForVrHighPerformance() throws InterruptedException {
+        if (!supportsVrHighPerformance())
+            return;
+        restartActivityWithClientVersion(3);
+
+        int reportedVersion = getVersionFromActivityManager(mActivity);
+        int major = getMajorVersion(reportedVersion);
+        int minor = getMinorVersion(reportedVersion);
+
+        assertTrue("OpenGL ES version 3.2 or higher is required for VR high-performance devices " +
+            " but this device supports only version " + major + "." + minor,
+            (major == 3 && minor >= 2) || major > 3);
+    }
+
+    public void testRequiredExtensionsForVrHighPerformance() throws InterruptedException {
+        if (!supportsVrHighPerformance())
+            return;
+        restartActivityWithClientVersion(3);
+
+        String extensions = mActivity.getExtensionsString();
+        final String requiredList[] = {
+            "EXT_protected_textures",
+            "EXT_multisampled_render_to_texture",
+            "OVR_multiview",
+            "OVR_multiview_multisampled_render_to_texture",
+            "OVR_multiview2",
+        };
+
+        for (int i = 0; i < requiredList.length; ++i) {
+            assertTrue("Required extension for VR high-performance is missing: " + requiredList[i],
+                    hasExtension(extensions, requiredList[i]));
+        }
+
+        EGL10 egl = (EGL10) EGLContext.getEGL();
+        EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+        extensions = egl.eglQueryString(display, EGL10.EGL_EXTENSIONS);
+        final String requiredEglList[] = {
+            "EGL_ANDROID_front_buffer_auto_refresh",
+            "EGL_EXT_protected_content",
+            "EGL_KHR_mutable_render_buffer",
+        };
+
+        for (int i = 0; i < requiredList.length; ++i) {
+            assertTrue("Required EGL extension for VR high-performance is missing: " +
+                requiredEglList[i], hasExtension(extensions, requiredEglList[i]));
+        }
+    }
+
     private static boolean hasExtension(String extensions, String name) {
         return OpenGlEsVersionCtsActivity.hasExtension(extensions, name);
     }
@@ -264,4 +312,13 @@
             setActivityIntent(null);
         }
     }
+
+    /**
+     * Return whether the system supports FEATURE_VR_MODE and
+     * FEATURE_VR_MODE_HIGH_PERFORMANCE. This is used to skip some tests.
+     */
+    private boolean supportsVrHighPerformance() {
+        PackageManager pm = mActivity.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
+    }
 }
diff --git a/tests/tests/keystore/Android.mk b/tests/tests/keystore/Android.mk
index 8e86c0e..66d3ebc 100644
--- a/tests/tests/keystore/Android.mk
+++ b/tests/tests/keystore/Android.mk
@@ -24,7 +24,7 @@
 LOCAL_COMPATIBILITY_SUITE := cts
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
-    ctstestrunner core-tests-support platform-test-annotations
+    ctstestrunner core-tests-support platform-test-annotations ctsdeviceutil
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyStoreTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyStoreTest.java
new file mode 100644
index 0000000..988f75a
--- /dev/null
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyStoreTest.java
@@ -0,0 +1,2546 @@
+/*
+ * 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.keystore.cts;
+
+import com.android.cts.util.TimeoutReq;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.KeyStore.Builder;
+import java.security.KeyStore.Entry;
+import java.security.KeyStore.LoadStoreParameter;
+import java.security.KeyStore.PasswordProtection;
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.KeyStore.ProtectionParameter;
+import java.security.KeyStore.SecretKeyEntry;
+import java.security.KeyStore.TrustedCertificateEntry;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import junit.framework.TestCase;
+
+import libcore.java.security.StandardNames;
+import libcore.java.security.TestKeyStore;
+
+public class KeyStoreTest extends TestCase {
+
+    private static final HashMap<String, PrivateKeyEntry> sPrivateKeys
+            = new HashMap<String, PrivateKeyEntry>();
+
+    private static TestKeyStore sTestKeyStore;
+
+    private static final String[] KEY_TYPES = new String[] { "DH", "DSA", "RSA", "EC" };
+
+    private static PrivateKeyEntry sPrivateKey2;
+
+    private static SecretKey sSecretKey;
+    private static SecretKey sSecretKey2;
+
+    private static final String ALIAS_PRIVATE = "private";
+    private static final String ALIAS_CERTIFICATE = "certificate";
+    private static final String ALIAS_SECRET = "secret";
+
+    private static final String ALIAS_ALT_CASE_PRIVATE = "pRiVaTe";
+    private static final String ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE = "PrIvAtE-no-password";
+    private static final String ALIAS_ALT_CASE_CERTIFICATE = "cErTiFiCaTe";
+    private static final String ALIAS_ALT_CASE_SECRET = "sEcRet";
+
+    private static final String ALIAS_UNICODE_PRIVATE = "\u6400\u7902\u3101\u8c02\u5002\u8702\udd01";
+    private static final String ALIAS_UNICODE_NO_PASSWORD_PRIVATE = "\u926c\u0967\uc65b\ubc78";
+    private static final String ALIAS_UNICODE_CERTIFICATE = "\u5402\udd01\u7902\u8702\u3101\u5f02\u3101\u5402\u5002\u8702\udd01";
+    private static final String ALIAS_UNICODE_SECRET = "\ue224\ud424\ud224\ue124\ud424\ue324";
+
+    private static final String ALIAS_NO_PASSWORD_PRIVATE = "private-no-password";
+    private static final String ALIAS_NO_PASSWORD_SECRET = "secret-no-password";
+
+    private static final char[] PASSWORD_STORE = "store password".toCharArray();
+    private static final char[] PASSWORD_KEY = "key password".toCharArray();
+    private static final char[] PASSWORD_BAD = "dummy".toCharArray();
+
+    private static final ProtectionParameter PARAM_STORE = new PasswordProtection(PASSWORD_STORE);
+    private static final ProtectionParameter PARAM_KEY = new PasswordProtection(PASSWORD_KEY);
+    private static final ProtectionParameter PARAM_BAD = new PasswordProtection(PASSWORD_BAD);
+
+    private static PrivateKeyEntry getPrivateKey() {
+        return getPrivateKey("RSA");
+    }
+
+    private static PrivateKeyEntry getPrivateKey(String keyType) {
+        // Avoiding initialization of TestKeyStore in the static initializer: it breaks CTS tests
+        // by causing a NetworkOnMainThreadException.
+        if (sTestKeyStore == null) {
+            sTestKeyStore = new TestKeyStore.Builder()
+                .keyAlgorithms("RSA", "DH_RSA", "DSA", "EC")
+                .aliasPrefix("rsa-dsa-ec-dh")
+                .build();
+        }
+
+        PrivateKeyEntry entry = sPrivateKeys.get(keyType);
+        if (entry == null) {
+            if ("RSA".equals(keyType)) {
+                entry = sTestKeyStore.getPrivateKey("RSA", "RSA");
+            } else if ("DH".equals(keyType)) {
+                entry = sTestKeyStore.getPrivateKey("DH", "RSA");
+            } else if ("DSA".equals(keyType)) {
+                entry = sTestKeyStore.getPrivateKey("DSA", "DSA");
+            } else if ("EC".equals(keyType)) {
+                entry = sTestKeyStore.getPrivateKey("EC", "EC");
+            } else {
+                throw new IllegalArgumentException("Unexpected key type " + keyType);
+            }
+            sPrivateKeys.put(keyType, entry);
+        }
+        return entry;
+    }
+
+    private static PrivateKeyEntry getPrivateKey2() {
+        if (sPrivateKey2 == null) {
+            sPrivateKey2 = TestKeyStore.getClientCertificate().getPrivateKey("RSA", "RSA");
+        }
+        return sPrivateKey2;
+    }
+
+    private static SecretKey getSecretKey() {
+        if (sSecretKey == null) {
+            sSecretKey = generateSecretKey();
+        }
+        return sSecretKey;
+    }
+
+    private static SecretKey getSecretKey2() {
+        if (sSecretKey2 == null) {
+            sSecretKey2 = generateSecretKey();
+        }
+        return sSecretKey2;
+    }
+
+    private static SecretKey generateSecretKey() {
+        try {
+            KeyGenerator kg = KeyGenerator.getInstance("DES");
+            return kg.generateKey();
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static List<KeyStore> keyStores() throws Exception {
+        List<KeyStore> keyStores = new ArrayList<KeyStore>();
+        Provider[] providers = Security.getProviders();
+        for (Provider provider : providers) {
+            Set<Provider.Service> services = provider.getServices();
+            for (Provider.Service service : services) {
+                String type = service.getType();
+                if (!type.equals("KeyStore")) {
+                    continue;
+                }
+                String algorithm = service.getAlgorithm();
+                KeyStore ks = KeyStore.getInstance(algorithm, provider);
+                assertEquals(provider, ks.getProvider());
+                assertEquals(algorithm, ks.getType());
+                if (!isUnsupported(ks)) {
+                    keyStores.add(ks);
+                }
+            }
+        }
+        return keyStores;
+    }
+
+    private static boolean isSecretKeyEnabled(KeyStore ks) {
+        // JKS key stores cannot store secret keys, neither can the RI's PKCS12
+        return (!(ks.getType().equals("JKS")
+                  || ks.getType().equals("CaseExactJKS")
+                  || (ks.getType().equals("PKCS12"))
+                  || (ks.getType().equals("AndroidKeyStore"))));
+    }
+
+    private static boolean isCertificateEnabled(KeyStore ks) {
+        // RI can't handle certificate in PKCS12, but BC can
+        return (!(ks.getType().equals("PKCS12") && ks.getProvider().getName().equals("SunJSSE")));
+    }
+
+    private static boolean isCaseSensitive(KeyStore ks) {
+        return (ks.getType().equals("CaseExactJKS")
+                || ks.getType().equals("BKS")
+                || ks.getType().equals("BouncyCastle")
+                || ks.getType().equals("AndroidKeyStore"));
+
+    }
+
+    private static boolean isUnsupported(KeyStore ks) {
+        // Don't bother testing BC on RI
+        // TODO enable AndroidKeyStore when CTS can set up the keystore
+        return (StandardNames.IS_RI && ks.getProvider().getName().equals("BC"))
+                || "AndroidKeyStore".equalsIgnoreCase(ks.getType())
+                || "TimaKeyStore".equalsIgnoreCase(ks.getType());
+    }
+
+    private static boolean isNullPasswordAllowed(KeyStore ks) {
+        return (!(ks.getType().equals("JKS")
+                  || ks.getType().equals("CaseExactJKS")
+                  || ks.getType().equals("JCEKS")
+                  || ks.getType().equals("PKCS12")));
+    }
+    private static boolean isKeyPasswordSupported(KeyStore ks) {
+        return !ks.getType().equals("AndroidKeyStore");
+    }
+    private static boolean isKeyPasswordIgnored(KeyStore ks) {
+        // BouncyCastle's PKCS12 ignores the key password unlike the RI which requires it
+        return (ks.getType().equals("PKCS12") && ks.getProvider().getName().equals("BC"));
+    }
+
+    private static boolean isLoadStoreParameterSupported(KeyStore ks) {
+        // BouncyCastle's PKCS12 allows a JDKPKCS12StoreParameter
+        return (ks.getType().equals("PKCS12") && ks.getProvider().getName().equals("BC"));
+    }
+
+    private static boolean isPersistentStorage(KeyStore ks) {
+        return ks.getType().equalsIgnoreCase("AndroidKeyStore");
+    }
+
+    private static boolean isLoadStoreUnsupported(KeyStore ks) {
+        return ks.getType().equalsIgnoreCase("AndroidKeyStore");
+    }
+
+    private static boolean isSetKeyByteArrayUnimplemented(KeyStore ks) {
+        // All of BouncyCastle's
+        // KeyStore.setKeyEntry(String,byte[],char[]) implementations
+        // throw RuntimeException
+        return (ks.getProvider().getName().equals("BC"));
+    }
+
+    private static boolean hasDefaultContents(KeyStore ks) {
+        // AndroidCAStore exposes CA cert files via the KeyStore
+        // interface, so it does start out empty like other KeyStores
+        return (ks.getType().equals("AndroidCAStore"));
+    }
+
+    private static boolean isReadOnly(KeyStore ks) {
+        // AndroidCAStore is read only, throwing
+        // UnsupportedOperationException on write operations
+        return (ks.getType().equals("AndroidCAStore"));
+    }
+
+    public static void populate(KeyStore ks) throws Exception {
+        boolean readOnly = clearKeyStore(ks);
+        if (readOnly) {
+            return;
+        }
+        if (isKeyPasswordSupported(ks)) {
+            setPrivateKey(ks);
+        }
+        if (isNullPasswordAllowed(ks)) {
+            ks.setKeyEntry(ALIAS_NO_PASSWORD_PRIVATE,
+                           getPrivateKey().getPrivateKey(),
+                           null,
+                           getPrivateKey().getCertificateChain());
+        }
+        if (isCertificateEnabled(ks)) {
+            ks.setCertificateEntry(ALIAS_CERTIFICATE,
+                                   getPrivateKey().getCertificate());
+        }
+        if (isSecretKeyEnabled(ks)) {
+            setSecretKey(ks);
+            if (isNullPasswordAllowed(ks)) {
+                ks.setKeyEntry(ALIAS_NO_PASSWORD_SECRET,
+                               getSecretKey(),
+                               null,
+                               null);
+            }
+        }
+    }
+
+    private static boolean clearKeyStore(KeyStore ks) throws Exception {
+        ks.load(null, null);
+        if (isReadOnly(ks)) {
+            try {
+                setPrivateKey(ks);
+                fail(ks.toString());
+            } catch (UnsupportedOperationException e) {
+            }
+            return true;
+        }
+        if (isPersistentStorage(ks)) {
+            Enumeration<String> aliases = ks.aliases();
+            while (aliases.hasMoreElements()) {
+                String alias = aliases.nextElement();
+                ks.deleteEntry(alias);
+            }
+        }
+        return false;
+    }
+
+    public static void setPrivateKeyNoPassword(KeyStore ks, String alias, PrivateKeyEntry privateKey)
+            throws Exception {
+        ks.setKeyEntry(alias, privateKey.getPrivateKey(), null, privateKey.getCertificateChain());
+    }
+    public static void setPrivateKey(KeyStore ks) throws Exception {
+        setPrivateKey(ks, ALIAS_PRIVATE);
+    }
+    public static void setPrivateKey(KeyStore ks, String alias) throws Exception {
+        setPrivateKey(ks, alias, getPrivateKey());
+    }
+    public static void setPrivateKey(KeyStore ks,
+                                     String alias,
+                                     PrivateKeyEntry privateKey)
+            throws Exception {
+        ks.setKeyEntry(alias,
+                       privateKey.getPrivateKey(),
+                       PASSWORD_KEY,
+                       privateKey.getCertificateChain());
+    }
+
+    public static void setPrivateKeyBytes(KeyStore ks) throws Exception {
+        setPrivateKeyBytes(ks, ALIAS_PRIVATE);
+    }
+    public static void setPrivateKeyBytes(KeyStore ks, String alias) throws Exception {
+        setPrivateKeyBytes(ks, alias, getPrivateKey());
+    }
+    public static void setPrivateKeyBytes(KeyStore ks,
+                                     String alias,
+                                     PrivateKeyEntry privateKey)
+            throws Exception {
+        ks.setKeyEntry(alias,
+                       privateKey.getPrivateKey().getEncoded(),
+                       privateKey.getCertificateChain());
+    }
+
+    public static void setSecretKey(KeyStore ks) throws Exception {
+        setSecretKey(ks, ALIAS_SECRET);
+    }
+    public static void setSecretKey(KeyStore ks, String alias) throws Exception {
+        setSecretKey(ks, alias, getSecretKey());
+    }
+    public static void setSecretKey(KeyStore ks, String alias, SecretKey key) throws Exception {
+        ks.setKeyEntry(alias,
+                       key,
+                       PASSWORD_KEY,
+                       null);
+    }
+
+    public static void setSecretKeyBytes(KeyStore ks) throws Exception {
+        setSecretKeyBytes(ks, ALIAS_SECRET);
+    }
+    public static void setSecretKeyBytes(KeyStore ks, String alias) throws Exception {
+        setSecretKeyBytes(ks, alias, getSecretKey());
+    }
+    public static void setSecretKeyBytes(KeyStore ks, String alias, SecretKey key)
+            throws Exception {
+        ks.setKeyEntry(alias,
+                       key.getEncoded(),
+                       null);
+    }
+
+    public static void setCertificate(KeyStore ks) throws Exception {
+        setCertificate(ks, ALIAS_CERTIFICATE);
+    }
+    public static void setCertificate(KeyStore ks, String alias) throws Exception {
+        setCertificate(ks, alias, getPrivateKey().getCertificate());
+    }
+    public static void setCertificate(KeyStore ks, String alias, Certificate certificate)
+            throws Exception {
+        ks.setCertificateEntry(alias, certificate);
+    }
+
+
+    public static void assertPrivateKey(Key actual)
+            throws Exception {
+        assertEquals(getPrivateKey().getPrivateKey(), actual);
+    }
+    public static void assertPrivateKey(String keyType, Key actual)
+            throws Exception {
+        assertEquals(getPrivateKey(keyType).getPrivateKey(), actual);
+    }
+    public static void assertPrivateKey2(Key actual)
+            throws Exception {
+        assertEquals(getPrivateKey2().getPrivateKey(), actual);
+    }
+    public static void assertPrivateKey(Entry actual)
+            throws Exception {
+        assertNotNull(actual);
+        assertSame(PrivateKeyEntry.class, actual.getClass());
+        PrivateKeyEntry privateKey = (PrivateKeyEntry) actual;
+        assertEquals(getPrivateKey().getPrivateKey(), privateKey.getPrivateKey());
+        assertEquals(getPrivateKey().getCertificate(), privateKey.getCertificate());
+        assertEquals(Arrays.asList(getPrivateKey().getCertificateChain()),
+                     Arrays.asList(privateKey.getCertificateChain()));
+    }
+
+    public static void assertSecretKey(Key actual)
+            throws Exception {
+        assertEquals(getSecretKey(), actual);
+    }
+    public static void assertSecretKey2(Key actual)
+            throws Exception {
+        assertEquals(getSecretKey2(), actual);
+    }
+    public static void assertSecretKey(Entry actual)
+            throws Exception {
+        assertSame(SecretKeyEntry.class, actual.getClass());
+        assertEquals(getSecretKey(), ((SecretKeyEntry) actual).getSecretKey());
+    }
+
+    public static void assertCertificate(Certificate actual)
+            throws Exception {
+        assertEquals(getPrivateKey().getCertificate(), actual);
+    }
+    public static void assertCertificate2(Certificate actual)
+            throws Exception {
+        assertEquals(getPrivateKey2().getCertificate(), actual);
+    }
+    public static void assertCertificate(Entry actual)
+            throws Exception {
+        assertSame(TrustedCertificateEntry.class, actual.getClass());
+        assertEquals(getPrivateKey().getCertificate(),
+                     ((TrustedCertificateEntry) actual).getTrustedCertificate());
+    }
+
+    public static void assertCertificateChain(Certificate[] actual)
+            throws Exception {
+        assertEquals(Arrays.asList(getPrivateKey().getCertificateChain()),
+                     Arrays.asList(actual));
+    }
+
+    public void test_KeyStore_create() throws Exception {
+        Provider[] providers = Security.getProviders();
+        for (Provider provider : providers) {
+            Set<Provider.Service> services = provider.getServices();
+            for (Provider.Service service : services) {
+                String type = service.getType();
+                if (!type.equals("KeyStore")) {
+                    continue;
+                }
+                String algorithm = service.getAlgorithm();
+                KeyStore ks = KeyStore.getInstance(algorithm, provider);
+                assertEquals(provider, ks.getProvider());
+                assertEquals(algorithm, ks.getType());
+            }
+        }
+    }
+
+    public void test_KeyStore_getInstance() throws Exception {
+        String type = KeyStore.getDefaultType();
+        try {
+            KeyStore.getInstance(null);
+            fail(type);
+        } catch (NullPointerException expected) {
+        }
+
+        assertNotNull(KeyStore.getInstance(type));
+
+        String providerName = StandardNames.SECURITY_PROVIDER_NAME;
+        try {
+            KeyStore.getInstance(null, (String)null);
+            fail(type);
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            KeyStore.getInstance(null, providerName);
+            fail(type);
+        } catch (Exception e) {
+            if (e.getClass() != NullPointerException.class
+                && e.getClass() != KeyStoreException.class) {
+                throw e;
+            }
+        }
+        try {
+            KeyStore.getInstance(type, (String)null);
+            fail(type);
+        } catch (IllegalArgumentException expected) {
+        }
+        assertNotNull(KeyStore.getInstance(type, providerName));
+
+        Provider provider = Security.getProvider(providerName);
+        try {
+            KeyStore.getInstance(null, (Provider)null);
+            fail(type);
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            KeyStore.getInstance(null, provider);
+            fail(type);
+        } catch (NullPointerException expected) {
+        }
+        try {
+            KeyStore.getInstance(type, (Provider)null);
+            fail(type);
+        } catch (IllegalArgumentException expected) {
+        }
+        assertNotNull(KeyStore.getInstance(type, provider));
+    }
+
+    public void test_KeyStore_getDefaultType() throws Exception {
+        String type = KeyStore.getDefaultType();
+        assertNotNull(type);
+        KeyStore ks = KeyStore.getInstance(type);
+        assertNotNull(ks);
+        assertEquals(type, ks.getType());
+    }
+
+    public void test_KeyStore_getProvider() throws Exception {
+        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+        assertNotNull(ks.getProvider());
+        assertNotNull(StandardNames.SECURITY_PROVIDER_NAME, ks.getProvider().getName());
+
+        for (KeyStore keyStore : keyStores()) {
+            assertNotNull(keyStore.getProvider());
+        }
+    }
+
+    public void test_KeyStore_getType() throws Exception {
+        String type = KeyStore.getDefaultType();
+        KeyStore ks = KeyStore.getInstance(type);
+        assertNotNull(ks.getType());
+        assertNotNull(type, ks.getType());
+
+        for (KeyStore keyStore : keyStores()) {
+            assertNotNull(keyStore.getType());
+        }
+    }
+
+    public void test_KeyStore_getKey() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.getKey(null, null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test odd inputs
+            try {
+                keyStore.getKey(null, null);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != IllegalArgumentException.class) {
+                    throw e;
+                }
+            }
+            try {
+                keyStore.getKey(null, PASSWORD_KEY);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != IllegalArgumentException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            assertNull(keyStore.getKey("", null));
+            assertNull(keyStore.getKey("", PASSWORD_KEY));
+
+            // test case sensitive
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            } else {
+                if (isKeyPasswordSupported(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                }
+                if (isNullPasswordAllowed(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                }
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                } else {
+                    assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                }
+            }
+
+            // test case insensitive
+            if (isCaseSensitive(keyStore) || isReadOnly(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+            } else {
+                if (isKeyPasswordSupported(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                }
+                if (isNullPasswordAllowed(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null));
+                }
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+            }
+
+            // test with null passwords
+            if (isKeyPasswordSupported(keyStore) && isKeyPasswordIgnored(keyStore)) {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, null));
+            } else {
+                if (isReadOnly(keyStore)) {
+                    assertNull(keyStore.getKey(ALIAS_PRIVATE, null));
+                } else if (isKeyPasswordSupported(keyStore)) {
+                    try {
+                        keyStore.getKey(ALIAS_PRIVATE, null);
+                        fail(keyStore.getType());
+                    } catch (Exception e) {
+                        if (e.getClass() != UnrecoverableKeyException.class
+                            && e.getClass() != IllegalArgumentException.class) {
+                            throw e;
+                        }
+                    }
+                }
+            }
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_SECRET, null));
+            } else if (isSecretKeyEnabled(keyStore)) {
+                try {
+                    keyStore.getKey(ALIAS_SECRET, null);
+                    fail(keyStore.getType());
+                } catch (Exception e) {
+                    if (e.getClass() != UnrecoverableKeyException.class
+                        && e.getClass() != IllegalArgumentException.class) {
+                        throw e;
+                    }
+                }
+            }
+
+            // test with bad passwords
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_PRIVATE, null));
+            } else if (isKeyPasswordSupported(keyStore) && isKeyPasswordIgnored(keyStore)) {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, null));
+            } else if (isKeyPasswordSupported(keyStore)) {
+                try {
+                    keyStore.getKey(ALIAS_PRIVATE, PASSWORD_BAD);
+                    fail(keyStore.getType());
+                } catch (UnrecoverableKeyException expected) {
+                }
+            }
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_BAD));
+            } else if (isSecretKeyEnabled(keyStore)) {
+                try {
+                    keyStore.getKey(ALIAS_SECRET, PASSWORD_BAD);
+                    fail(keyStore.getType());
+                } catch (UnrecoverableKeyException expected) {
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_getCertificateChain() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.getCertificateChain(null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test odd inputs
+            try {
+                keyStore.getCertificateChain(null);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != IllegalArgumentException.class) {
+                    throw e;
+                }
+            }
+            assertNull(keyStore.getCertificateChain(""));
+
+            // test case sensitive
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getCertificateChain(ALIAS_PRIVATE));
+            } else if (isKeyPasswordSupported(keyStore)) {
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE));
+            } else if (isNullPasswordAllowed(keyStore)) {
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_NO_PASSWORD_PRIVATE));
+            }
+
+            // test case insensitive
+            if (isReadOnly(keyStore) || isCaseSensitive(keyStore)) {
+                assertNull(keyStore.getCertificateChain(ALIAS_ALT_CASE_PRIVATE));
+            } else {
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_ALT_CASE_PRIVATE));
+            }
+        }
+    }
+
+    public void test_KeyStore_getCertificate() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.getCertificate(null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test odd inputs
+            try {
+                keyStore.getCertificate(null);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != IllegalArgumentException.class) {
+                    throw e;
+                }
+            }
+            assertNull(keyStore.getCertificate(""));
+
+            // test case sensitive
+            if (!isReadOnly(keyStore) && isCertificateEnabled(keyStore)) {
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+            } else {
+                assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE));
+            }
+
+            // test case insensitive
+            if (isReadOnly(keyStore) || isCaseSensitive(keyStore)) {
+                assertNull(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+            } else {
+                if (isCertificateEnabled(keyStore)) {
+                    assertCertificate(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_getCreationDate() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.getCreationDate(null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+        long before = System.currentTimeMillis();
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // add 1000 since some key stores round of time to nearest second
+            long after = System.currentTimeMillis() + 1000;
+
+            // test odd inputs
+            try {
+                keyStore.getCreationDate(null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+            assertNull(keyStore.getCreationDate(""));
+
+            // test case sensitive
+            if (!isReadOnly(keyStore) && isCertificateEnabled(keyStore)) {
+                Date date = keyStore.getCreationDate(ALIAS_CERTIFICATE);
+                assertNotNull(date);
+                assertTrue("date should be after start time: " + date.getTime() + " >= " + before,
+                        before <= date.getTime());
+                assertTrue("date should be before expiry time: " + date.getTime() + " <= " + after,
+                        date.getTime() <= after);
+            } else {
+                assertNull(keyStore.getCreationDate(ALIAS_CERTIFICATE));
+            }
+
+            // test case insensitive
+            if (isReadOnly(keyStore) || isCaseSensitive(keyStore)) {
+                assertNull(keyStore.getCreationDate(ALIAS_ALT_CASE_CERTIFICATE));
+            } else {
+                if (isCertificateEnabled(keyStore)) {
+                    Date date = keyStore.getCreationDate(ALIAS_ALT_CASE_CERTIFICATE);
+                    assertTrue(before <= date.getTime());
+                    assertTrue(date.getTime() <= after);
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_setKeyEntry_Key() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.setKeyEntry(null, null, null, null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            if (isReadOnly(keyStore)) {
+                try {
+                    keyStore.setKeyEntry(null, null, null, null);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                continue;
+            }
+
+            // test odd inputs
+            try {
+                keyStore.setKeyEntry(null, null, null, null);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            try {
+                keyStore.setKeyEntry(null, null, PASSWORD_KEY, null);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            try {
+                keyStore.setKeyEntry(ALIAS_PRIVATE,
+                                     getPrivateKey().getPrivateKey(),
+                                     PASSWORD_KEY,
+                                     null);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != IllegalArgumentException.class
+                        && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            clearKeyStore(keyStore);
+
+            // test case sensitive
+            if (isKeyPasswordSupported(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            }
+            if (isNullPasswordAllowed(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+            }
+            if (isReadOnly(keyStore)) {
+                try {
+                    keyStore.setKeyEntry(ALIAS_SECRET, getSecretKey(), PASSWORD_KEY, null);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                continue;
+            }
+            if (isKeyPasswordSupported(keyStore)) {
+                setPrivateKey(keyStore);
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE));
+            }
+            if (isNullPasswordAllowed(keyStore)) {
+                setPrivateKeyNoPassword(keyStore, ALIAS_NO_PASSWORD_PRIVATE, getPrivateKey());
+                assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_NO_PASSWORD_PRIVATE));
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                setSecretKey(keyStore);
+                assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+            } else {
+                try {
+                    keyStore.setKeyEntry(ALIAS_SECRET, getSecretKey(), PASSWORD_KEY, null);
+                    fail(keyStore.getType());
+                } catch (Exception e) {
+                    if (e.getClass() != KeyStoreException.class
+                        && e.getClass() != NullPointerException.class) {
+                        throw e;
+                    }
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+            } else if (isCaseSensitive(keyStore)) {
+                if (isKeyPasswordSupported(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                    assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                    setPrivateKey(keyStore, ALIAS_ALT_CASE_PRIVATE, getPrivateKey2());
+                    assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                    assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                }
+
+                if (isNullPasswordAllowed(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                    assertNull(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null));
+                    setPrivateKeyNoPassword(keyStore, ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE,
+                            getPrivateKey2());
+                    assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                    assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null));
+                }
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                    setSecretKey(keyStore, ALIAS_ALT_CASE_SECRET, getSecretKey2());
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey2(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+            } else {
+                if (isKeyPasswordSupported(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                    assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                    setPrivateKey(keyStore, ALIAS_ALT_CASE_PRIVATE, getPrivateKey2());
+                    assertPrivateKey2(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                    assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                }
+
+                if (isNullPasswordAllowed(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, null));
+                    assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null));
+                    setPrivateKey(keyStore, ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, getPrivateKey2());
+                    assertPrivateKey2(keyStore.getKey(ALIAS_PRIVATE, null));
+                    assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null));
+                }
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                    setSecretKey(keyStore, ALIAS_ALT_CASE_PRIVATE, getSecretKey2());
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            if (isReadOnly(keyStore)) {
+                try {
+                    keyStore.setKeyEntry(ALIAS_PRIVATE,
+                                         getPrivateKey().getPrivateKey(),
+                                         null,
+                                         getPrivateKey().getCertificateChain());
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                continue;
+            }
+
+            // test with null passwords
+            if (isNullPasswordAllowed(keyStore) || isKeyPasswordIgnored(keyStore)) {
+                keyStore.setKeyEntry(ALIAS_PRIVATE,
+                                     getPrivateKey().getPrivateKey(),
+                                     null,
+                                     getPrivateKey().getCertificateChain());
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, null));
+            } else {
+                try {
+                    keyStore.setKeyEntry(ALIAS_PRIVATE,
+                                         getPrivateKey().getPrivateKey(),
+                                         null,
+                                         getPrivateKey().getCertificateChain());
+                    fail(keyStore.getType());
+                } catch (Exception e) {
+                    if (e.getClass() != UnrecoverableKeyException.class
+                        && e.getClass() != IllegalArgumentException.class
+                        && e.getClass() != KeyStoreException.class) {
+                        throw e;
+                    }
+                }
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                if (isNullPasswordAllowed(keyStore) || isKeyPasswordIgnored(keyStore)) {
+                    keyStore.setKeyEntry(ALIAS_SECRET, getSecretKey(), null, null);
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, null));
+                } else {
+                    try {
+                        keyStore.setKeyEntry(ALIAS_SECRET, getSecretKey(), null, null);
+                        fail(keyStore.getType());
+                    } catch (Exception e) {
+                        if (e.getClass() != UnrecoverableKeyException.class
+                            && e.getClass() != IllegalArgumentException.class
+                            && e.getClass() != KeyStoreException.class) {
+                            throw e;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_setKeyEntry_array() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.setKeyEntry(null, null, null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            if (isReadOnly(keyStore)) {
+                try {
+                    keyStore.setKeyEntry(null, null, null);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                continue;
+            }
+
+            // test odd inputs
+            try {
+                keyStore.setKeyEntry(null, null, null);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != IllegalArgumentException.class
+                    && e.getClass() != KeyStoreException.class
+                    && e.getClass() != RuntimeException.class) {
+                    throw e;
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            if (!isNullPasswordAllowed(keyStore)) {
+                // TODO Use EncryptedPrivateKeyInfo to protect keys if
+                // password is required.
+                continue;
+            }
+            if (isSetKeyByteArrayUnimplemented(keyStore)) {
+                continue;
+            }
+
+            clearKeyStore(keyStore);
+
+            // test case sensitive
+            if (isKeyPasswordSupported(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            }
+            if (isNullPasswordAllowed(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+            }
+            if (isReadOnly(keyStore)) {
+                try {
+                    setPrivateKeyBytes(keyStore);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                continue;
+            }
+            if (isKeyPasswordSupported(keyStore)) {
+                setPrivateKeyBytes(keyStore);
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE));
+            }
+            if (isNullPasswordAllowed(keyStore)) {
+                setPrivateKeyNoPassword(keyStore, ALIAS_NO_PASSWORD_PRIVATE, getPrivateKey());
+                assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_NO_PASSWORD_PRIVATE));
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                setSecretKeyBytes(keyStore);
+                assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+            } else {
+                try {
+                    keyStore.setKeyEntry(ALIAS_SECRET, getSecretKey().getEncoded(), null);
+                    fail(keyStore.getType());
+                } catch (KeyStoreException expected) {
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            if (!isNullPasswordAllowed(keyStore)) {
+                // TODO Use EncryptedPrivateKeyInfo to protect keys if
+                // password is required.
+                continue;
+            }
+            if (isSetKeyByteArrayUnimplemented(keyStore)) {
+                continue;
+            }
+
+            populate(keyStore);
+
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+            } else if (isCaseSensitive(keyStore)) {
+                if (isKeyPasswordSupported(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                    assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                    setPrivateKeyBytes(keyStore, ALIAS_ALT_CASE_PRIVATE, getPrivateKey2());
+                    assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                    assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                }
+                if (isNullPasswordAllowed(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                    assertNull(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null));
+                    setPrivateKeyNoPassword(keyStore, ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE,
+                            getPrivateKey2());
+                    assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                    assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null));
+                }
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                    setSecretKeyBytes(keyStore, ALIAS_ALT_CASE_PRIVATE, getSecretKey2());
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey2(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+            } else {
+                if (isKeyPasswordSupported(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                    assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                    setPrivateKeyBytes(keyStore, ALIAS_ALT_CASE_PRIVATE, getPrivateKey2());
+                    assertPrivateKey2(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                    assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                }
+                if (isNullPasswordAllowed(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                    assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null));
+                    setPrivateKeyNoPassword(keyStore, ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE,
+                            getPrivateKey2());
+                    assertPrivateKey2(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                    assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null));
+                }
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                    setSecretKeyBytes(keyStore, ALIAS_ALT_CASE_PRIVATE, getSecretKey2());
+                    assertSecretKey2(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey2(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_setCertificateEntry() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.setCertificateEntry(null, null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test odd inputs
+            try {
+                keyStore.setCertificateEntry(null, null);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+
+            if (isReadOnly(keyStore)) {
+                try {
+                    assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    keyStore.setCertificateEntry(ALIAS_CERTIFICATE, null);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                continue;
+            }
+
+            // Sort of delete by setting null.  Note that even though
+            // certificate is null, size doesn't change,
+            // isCertificateEntry returns true, and it is still listed in aliases.
+            if (isCertificateEnabled(keyStore)) {
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                try {
+                    int size = keyStore.size();
+                    keyStore.setCertificateEntry(ALIAS_CERTIFICATE, null);
+                    assertNull(keyStore.getType(), keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    assertEquals(keyStore.getType(), size, keyStore.size());
+                    assertTrue(keyStore.getType(), keyStore.isCertificateEntry(ALIAS_CERTIFICATE));
+                    assertTrue(keyStore.getType(),
+                            Collections.list(keyStore.aliases()).contains(ALIAS_CERTIFICATE));
+                } catch (NullPointerException expectedSometimes) {
+                    if (!("PKCS12".equalsIgnoreCase(keyStore.getType()) &&
+                                "BC".equalsIgnoreCase(keyStore.getProvider().getName()))
+                            && !"AndroidKeyStore".equalsIgnoreCase(keyStore.getType())) {
+                        throw expectedSometimes;
+                    }
+                }
+            } else {
+                try {
+                    keyStore.setCertificateEntry(ALIAS_CERTIFICATE, null);
+                    fail(keyStore.getType());
+                } catch (KeyStoreException expected) {
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            if (!isCertificateEnabled(keyStore)) {
+                continue;
+            }
+
+            clearKeyStore(keyStore);
+
+            assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE));
+            if (isReadOnly(keyStore)) {
+                try {
+                    setCertificate(keyStore);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                continue;
+            }
+            setCertificate(keyStore);
+            assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            if (!isCertificateEnabled(keyStore)) {
+                continue;
+            }
+
+            populate(keyStore);
+
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                assertNull(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+            } else if (isCaseSensitive(keyStore)) {
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                assertNull(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                setCertificate(keyStore,
+                               ALIAS_ALT_CASE_CERTIFICATE,
+                               getPrivateKey2().getCertificate());
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                assertCertificate2(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+            } else {
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                assertCertificate(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                setCertificate(keyStore,
+                               ALIAS_ALT_CASE_CERTIFICATE,
+                               getPrivateKey2().getCertificate());
+                assertCertificate2(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                assertCertificate2(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+            }
+        }
+    }
+    public void test_KeyStore_deleteEntry() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.deleteEntry(null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            if (isReadOnly(keyStore)) {
+                try {
+                    keyStore.deleteEntry(null);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                continue;
+            }
+
+            // test odd inputs
+            try {
+                keyStore.deleteEntry(null);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            keyStore.deleteEntry("");
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            if (isReadOnly(keyStore)) {
+                try {
+                    keyStore.deleteEntry(ALIAS_PRIVATE);
+                } catch (UnsupportedOperationException e) {
+                }
+                continue;
+            }
+
+            // test case sensitive
+            if (isKeyPasswordSupported(keyStore)) {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE));
+                keyStore.deleteEntry(ALIAS_PRIVATE);
+                assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            }
+            if (isNullPasswordAllowed(keyStore)) {
+                assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_NO_PASSWORD_PRIVATE));
+                keyStore.deleteEntry(ALIAS_NO_PASSWORD_PRIVATE);
+                assertNull(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+            }
+
+            if (isSecretKeyEnabled(keyStore)) {
+                assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                keyStore.deleteEntry(ALIAS_SECRET);
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+            } else {
+                keyStore.deleteEntry(ALIAS_SECRET);
+            }
+
+            if (isCertificateEnabled(keyStore)) {
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                keyStore.deleteEntry(ALIAS_CERTIFICATE);
+                assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE));
+            } else {
+                keyStore.deleteEntry(ALIAS_CERTIFICATE);
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test case insensitive
+
+            if (isCaseSensitive(keyStore)) {
+                if (isKeyPasswordSupported(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                    keyStore.deleteEntry(ALIAS_ALT_CASE_PRIVATE);
+                    assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                }
+                if (isNullPasswordAllowed(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                    keyStore.deleteEntry(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE);
+                    assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                }
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    keyStore.deleteEntry(ALIAS_ALT_CASE_SECRET);
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                } else {
+                    keyStore.deleteEntry(ALIAS_SECRET);
+                }
+
+                if (isCertificateEnabled(keyStore)) {
+                    assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    keyStore.deleteEntry(ALIAS_ALT_CASE_CERTIFICATE);
+                    assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                } else {
+                    keyStore.deleteEntry(ALIAS_CERTIFICATE);
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_aliases() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.aliases();
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            if (isPersistentStorage(keyStore)) {
+                assertNotNull("Should be able to query size: " + keyStore.getType(),
+                        keyStore.aliases());
+            } else if (hasDefaultContents(keyStore)) {
+                assertTrue("Should have more than one alias already: " + keyStore.getType(),
+                        keyStore.aliases().hasMoreElements());
+            } else {
+                assertEquals("Should have no aliases:" + keyStore.getType(), Collections.EMPTY_SET,
+                        new HashSet(Collections.list(keyStore.aliases())));
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            Set<String> expected = new HashSet<String>();
+            if (isKeyPasswordSupported(keyStore)) {
+                expected.add(ALIAS_PRIVATE);
+            }
+            if (isNullPasswordAllowed(keyStore)) {
+                expected.add(ALIAS_NO_PASSWORD_PRIVATE);
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                expected.add(ALIAS_SECRET);
+                if (isNullPasswordAllowed(keyStore)) {
+                    expected.add(ALIAS_NO_PASSWORD_SECRET);
+                }
+            }
+            if (isCertificateEnabled(keyStore)) {
+                expected.add(ALIAS_CERTIFICATE);
+            }
+            if (isPersistentStorage(keyStore)) {
+                assertNotNull("Should be able to query size: " + keyStore.getType(),
+                        keyStore.aliases());
+            } else if (hasDefaultContents(keyStore)) {
+                assertTrue(keyStore.aliases().hasMoreElements());
+            } else {
+                assertEquals(expected, new HashSet<String>(Collections.list(keyStore.aliases())));
+            }
+        }
+    }
+
+    public void test_KeyStore_containsAlias() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.containsAlias(null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            try {
+                keyStore.containsAlias(null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+
+            assertFalse(keyStore.containsAlias(""));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            assertFalse(keyStore.containsAlias(""));
+
+            if (isReadOnly(keyStore)) {
+                assertFalse(keyStore.containsAlias(ALIAS_PRIVATE));
+                continue;
+            }
+            if (isKeyPasswordSupported(keyStore)) {
+                assertTrue(keyStore.containsAlias(ALIAS_PRIVATE));
+            } else if (isNullPasswordAllowed(keyStore)) {
+                assertTrue(keyStore.containsAlias(ALIAS_NO_PASSWORD_PRIVATE));
+            }
+            assertEquals(isSecretKeyEnabled(keyStore), keyStore.containsAlias(ALIAS_SECRET));
+            assertEquals(isCertificateEnabled(keyStore), keyStore.containsAlias(ALIAS_CERTIFICATE));
+
+            assertEquals(!isCaseSensitive(keyStore),
+                         keyStore.containsAlias(ALIAS_ALT_CASE_PRIVATE));
+            assertEquals(!isCaseSensitive(keyStore) && isSecretKeyEnabled(keyStore),
+                         keyStore.containsAlias(ALIAS_ALT_CASE_SECRET));
+            assertEquals(!isCaseSensitive(keyStore) && isCertificateEnabled(keyStore),
+                         keyStore.containsAlias(ALIAS_ALT_CASE_CERTIFICATE));
+        }
+    }
+
+    public void test_KeyStore_size() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.aliases();
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            if (isPersistentStorage(keyStore)) {
+                assertTrue("Should successfully query size: " + keyStore.getType(),
+                        keyStore.size() >= 0);
+            } else if (hasDefaultContents(keyStore)) {
+                assertTrue("Should have non-empty store: " + keyStore.getType(),
+                        keyStore.size() > 0);
+            } else {
+                assertEquals("Should have empty store: " + keyStore.getType(), 0, keyStore.size());
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            if (hasDefaultContents(keyStore)) {
+                assertTrue("Should have non-empty store: " + keyStore.getType(),
+                        keyStore.size() > 0);
+                continue;
+            }
+
+            int expected = 0;
+            if (isKeyPasswordSupported(keyStore)) {
+                expected++;
+            }
+            if (isNullPasswordAllowed(keyStore)) {
+                expected++;
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                expected++;
+                if (isNullPasswordAllowed(keyStore)) {
+                    expected++;
+                }
+            }
+            if (isCertificateEnabled(keyStore)) {
+                expected++;
+            }
+            assertEquals(expected, keyStore.size());
+        }
+    }
+
+    public void test_KeyStore_isKeyEntry() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.isKeyEntry(null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            try {
+                keyStore.isKeyEntry(null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+
+            assertFalse(keyStore.isKeyEntry(""));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            assertFalse(keyStore.isKeyEntry(""));
+            if (isReadOnly(keyStore)) {
+                assertFalse(keyStore.isKeyEntry(ALIAS_PRIVATE));
+                continue;
+            }
+            if (isKeyPasswordSupported(keyStore)) {
+                assertTrue(keyStore.isKeyEntry(ALIAS_PRIVATE));
+            }
+            if (isNullPasswordAllowed(keyStore)) {
+                assertTrue(keyStore.isKeyEntry(ALIAS_NO_PASSWORD_PRIVATE));
+            }
+            assertEquals(isSecretKeyEnabled(keyStore), keyStore.isKeyEntry(ALIAS_SECRET));
+            assertFalse(keyStore.isKeyEntry(ALIAS_CERTIFICATE));
+
+            assertEquals(!isCaseSensitive(keyStore),
+                         keyStore.isKeyEntry(ALIAS_ALT_CASE_PRIVATE));
+            assertEquals(!isCaseSensitive(keyStore) && isSecretKeyEnabled(keyStore),
+                         keyStore.isKeyEntry(ALIAS_ALT_CASE_SECRET));
+            assertFalse(keyStore.isKeyEntry(ALIAS_ALT_CASE_CERTIFICATE));
+        }
+    }
+
+    public void test_KeyStore_isCertificateEntry() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.isCertificateEntry(null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            if (isCertificateEnabled(keyStore)) {
+                try {
+                    keyStore.isCertificateEntry(null);
+                    fail(keyStore.getType());
+                } catch (NullPointerException expected) {
+                }
+            } else {
+                assertFalse(keyStore.isCertificateEntry(null));
+            }
+
+            assertFalse(keyStore.isCertificateEntry(""));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            assertFalse(keyStore.isCertificateEntry(""));
+
+            if (isKeyPasswordSupported(keyStore)) {
+                assertFalse(keyStore.isCertificateEntry(ALIAS_PRIVATE));
+            }
+            if (isNullPasswordAllowed(keyStore)) {
+                assertFalse(keyStore.isCertificateEntry(ALIAS_NO_PASSWORD_PRIVATE));
+            }
+            assertFalse(keyStore.isCertificateEntry(ALIAS_SECRET));
+            assertEquals(isCertificateEnabled(keyStore) && !isReadOnly(keyStore),
+                    keyStore.isCertificateEntry(ALIAS_CERTIFICATE));
+
+            assertFalse(keyStore.isCertificateEntry(ALIAS_ALT_CASE_PRIVATE));
+            assertFalse(keyStore.isCertificateEntry(ALIAS_ALT_CASE_SECRET));
+            assertEquals(!isCaseSensitive(keyStore)
+                    && isCertificateEnabled(keyStore)
+                    && !isReadOnly(keyStore),
+                    keyStore.isCertificateEntry(ALIAS_ALT_CASE_CERTIFICATE));
+        }
+    }
+
+    public void test_KeyStore_getCertificateAlias() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.getCertificateAlias(null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            assertNull(keyStore.getCertificateAlias(null));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            Set<String> expected = new HashSet<String>();
+            if (isKeyPasswordSupported(keyStore)) {
+                expected.add(ALIAS_PRIVATE);
+            }
+            if (isNullPasswordAllowed(keyStore)) {
+                expected.add(ALIAS_NO_PASSWORD_PRIVATE);
+            }
+            if (isCertificateEnabled(keyStore)) {
+                expected.add(ALIAS_CERTIFICATE);
+            }
+            String actual = keyStore.getCertificateAlias(getPrivateKey().getCertificate());
+            assertEquals(!isReadOnly(keyStore), expected.contains(actual));
+            assertNull(keyStore.getCertificateAlias(getPrivateKey2().getCertificate()));
+        }
+    }
+
+    public void assertEqualsKeyStores(File expected, char[] storePassword, KeyStore actual)
+            throws Exception{
+        KeyStore ks = KeyStore.getInstance(actual.getType(), actual.getProvider());
+        InputStream is = new FileInputStream(expected);
+        ks.load(is, storePassword);
+        is.close();
+        assertEqualsKeyStores(ks, actual);
+    }
+
+    public void assertEqualsKeyStores(KeyStore expected,
+                                      ByteArrayOutputStream actual, char[] storePassword)
+            throws Exception{
+        KeyStore ks = KeyStore.getInstance(expected.getType(), expected.getProvider());
+        ks.load(new ByteArrayInputStream(actual.toByteArray()), storePassword);
+        assertEqualsKeyStores(expected, ks);
+    }
+
+    public void assertEqualsKeyStores(KeyStore expected, KeyStore actual)
+            throws Exception{
+        assertEquals(expected.size(), actual.size());
+        for (String alias : Collections.list(actual.aliases())) {
+            if (alias.equals(ALIAS_NO_PASSWORD_PRIVATE)
+                    || alias.equals(ALIAS_NO_PASSWORD_SECRET)) {
+                assertEquals(expected.getKey(alias, null),
+                             actual.getKey(alias, null));
+            } else {
+                assertEquals(expected.getKey(alias, PASSWORD_KEY),
+                             actual.getKey(alias, PASSWORD_KEY));
+            }
+            assertEquals(expected.getCertificate(alias), actual.getCertificate(alias));
+        }
+    }
+
+    public void test_KeyStore_store_OutputStream() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.store(null, null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            if (isLoadStoreUnsupported(keyStore) || isReadOnly(keyStore)) {
+                try {
+                    keyStore.store(out, null);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                continue;
+            }
+
+            if (isNullPasswordAllowed(keyStore)) {
+                keyStore.store(out, null);
+                assertEqualsKeyStores(keyStore, out, null);
+                continue;
+            }
+
+            try {
+                keyStore.store(out, null);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != IllegalArgumentException.class
+                    && e.getClass() != NullPointerException.class) {
+                    throw e;
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            if (isLoadStoreUnsupported(keyStore) || isReadOnly(keyStore)) {
+                try {
+                    keyStore.store(out, null);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+            } else if (isNullPasswordAllowed(keyStore)) {
+                keyStore.store(out, null);
+                assertEqualsKeyStores(keyStore, out, null);
+            } else {
+                try {
+                    keyStore.store(out, null);
+                    fail(keyStore.getType());
+                } catch (Exception e) {
+                    if (e.getClass() != IllegalArgumentException.class
+                        && e.getClass() != NullPointerException.class) {
+                        throw e;
+                    }
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            if (isLoadStoreUnsupported(keyStore) || isReadOnly(keyStore)) {
+                try {
+                    keyStore.store(out, PASSWORD_STORE);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException e) {
+                }
+                continue;
+            }
+            keyStore.store(out, PASSWORD_STORE);
+            assertEqualsKeyStores(keyStore, out, PASSWORD_STORE);
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            if (isLoadStoreUnsupported(keyStore) || isReadOnly(keyStore)) {
+                try {
+                    keyStore.store(out, PASSWORD_STORE);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException e) {
+                }
+                continue;
+            }
+            keyStore.store(out, PASSWORD_STORE);
+            assertEqualsKeyStores(keyStore, out, PASSWORD_STORE);
+        }
+    }
+
+    public void test_KeyStore_store_LoadStoreParameter() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.store(null);
+                fail(keyStore.getType());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            try {
+                keyStore.store(null);
+                fail(keyStore.getType());
+            } catch (UnsupportedOperationException expected) {
+                assertFalse(isLoadStoreParameterSupported(keyStore));
+            } catch (IllegalArgumentException expected) {
+                // its supported, but null causes an exception
+                assertTrue(isLoadStoreParameterSupported(keyStore));
+            }
+        }
+    }
+
+    public void test_KeyStore_load_InputStream() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            if (isPersistentStorage(keyStore)) {
+                assertTrue("Should be able to query size: " + keyStore.getType(),
+                        keyStore.size() >= 0);
+            } else if (hasDefaultContents(keyStore)) {
+                assertTrue("Should have non-empty store: " + keyStore.getType(),
+                        keyStore.size() > 0);
+            } else {
+                assertEquals("Should have empty store: " + keyStore.getType(), 0, keyStore.size());
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            if (isLoadStoreUnsupported(keyStore)) {
+                continue;
+            }
+            keyStore.load(null, PASSWORD_STORE);
+            if (isPersistentStorage(keyStore)) {
+                assertTrue("Should be able to query size: " + keyStore.getType(),
+                        keyStore.size() >= 0);
+            } else if (hasDefaultContents(keyStore)) {
+                assertTrue("Should have non-empty store: " + keyStore.getType(),
+                        keyStore.size() > 0);
+            } else {
+                assertEquals("Should have empty store: " + keyStore.getType(), 0, keyStore.size());
+            }
+        }
+
+        // test_KeyStore_store_OutputStream effectively tests load as well as store
+    }
+
+    public void test_KeyStore_load_LoadStoreParameter() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null);
+            if (isPersistentStorage(keyStore)) {
+                assertTrue("Should be able to query size: " + keyStore.getType(),
+                        keyStore.size() >= 0);
+            } else if (hasDefaultContents(keyStore)) {
+                assertTrue("Should have non-empty store: " + keyStore.getType(),
+                        keyStore.size() > 0);
+            } else {
+                assertEquals("Should have empty store: " + keyStore.getType(), 0, keyStore.size());
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.load(new LoadStoreParameter() {
+                        public ProtectionParameter getProtectionParameter() {
+                            return null;
+                        }
+                    });
+                fail(keyStore.getType());
+            } catch (UnsupportedOperationException expected) {
+            }
+        }
+    }
+
+    public void test_KeyStore_getEntry() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.getEntry(null, null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test odd inputs
+            try {
+                keyStore.getEntry(null, null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+            try {
+                keyStore.getEntry(null, PARAM_KEY);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+            assertNull(keyStore.getEntry("", null));
+            assertNull(keyStore.getEntry("", PARAM_KEY));
+
+            // test case sensitive
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getEntry(ALIAS_PRIVATE, PARAM_KEY));
+            } else {
+                if (isKeyPasswordSupported(keyStore)) {
+                    assertPrivateKey(keyStore.getEntry(ALIAS_PRIVATE, PARAM_KEY));
+                } else if (isNullPasswordAllowed(keyStore)) {
+                    assertPrivateKey(keyStore.getEntry(ALIAS_NO_PASSWORD_PRIVATE, null));
+                }
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getEntry(ALIAS_SECRET, PARAM_KEY));
+                } else {
+                    assertNull(keyStore.getEntry(ALIAS_SECRET, PARAM_KEY));
+                }
+                if (isCertificateEnabled(keyStore)) {
+                    assertCertificate(keyStore.getEntry(ALIAS_CERTIFICATE, null));
+                } else {
+                    assertNull(keyStore.getEntry(ALIAS_CERTIFICATE, null));
+                }
+            }
+
+            // test case insensitive
+            if (isCaseSensitive(keyStore) || isReadOnly(keyStore)) {
+                assertNull(keyStore.getEntry(ALIAS_ALT_CASE_PRIVATE, PARAM_KEY));
+                assertNull(keyStore.getEntry(ALIAS_ALT_CASE_SECRET, PARAM_KEY));
+            } else {
+                assertPrivateKey(keyStore.getEntry(ALIAS_ALT_CASE_PRIVATE, PARAM_KEY));
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getEntry(ALIAS_ALT_CASE_SECRET, PARAM_KEY));
+                }
+            }
+            if (isCaseSensitive(keyStore) || isReadOnly(keyStore)) {
+                assertNull(keyStore.getEntry(ALIAS_ALT_CASE_CERTIFICATE, null));
+            } else {
+                if (isCertificateEnabled(keyStore)) {
+                    assertCertificate(keyStore.getEntry(ALIAS_ALT_CASE_CERTIFICATE, null));
+                }
+            }
+
+            // test with null passwords
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getEntry(ALIAS_NO_PASSWORD_PRIVATE, null));
+            } else if (isNullPasswordAllowed(keyStore)) {
+                assertPrivateKey(keyStore.getEntry(ALIAS_NO_PASSWORD_PRIVATE, null));
+            } else if (isKeyPasswordSupported(keyStore) && isKeyPasswordIgnored(keyStore)) {
+                assertPrivateKey(keyStore.getEntry(ALIAS_PRIVATE, null));
+            } else if (isKeyPasswordIgnored(keyStore)) {
+                try {
+                    keyStore.getEntry(ALIAS_PRIVATE, null);
+                    fail(keyStore.getType());
+                } catch (Exception e) {
+                    if (e.getClass() != UnrecoverableKeyException.class
+                        && e.getClass() != IllegalArgumentException.class) {
+                        throw e;
+                    }
+                }
+            }
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getEntry(ALIAS_SECRET, null));
+            } else if (isSecretKeyEnabled(keyStore)) {
+                try {
+                    keyStore.getEntry(ALIAS_SECRET, null);
+                    fail(keyStore.getType());
+                } catch (Exception e) {
+                    if (e.getClass() != UnrecoverableKeyException.class
+                        && e.getClass() != IllegalArgumentException.class) {
+                        throw e;
+                    }
+                }
+            }
+
+            // test with bad passwords
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getEntry(ALIAS_PRIVATE, PARAM_BAD));
+            } else if (isKeyPasswordSupported(keyStore) && isKeyPasswordIgnored(keyStore)) {
+                assertPrivateKey(keyStore.getEntry(ALIAS_PRIVATE, PARAM_BAD));
+            } else if (isKeyPasswordSupported(keyStore)) {
+                try {
+                    keyStore.getEntry(ALIAS_PRIVATE, PARAM_BAD);
+                    fail(keyStore.getType());
+                } catch (UnrecoverableKeyException expected) {
+                }
+            }
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getEntry(ALIAS_SECRET, PARAM_BAD));
+            } else if (isSecretKeyEnabled(keyStore)) {
+                try {
+                    keyStore.getEntry(ALIAS_SECRET, PARAM_BAD);
+                    fail(keyStore.getType());
+                } catch (UnrecoverableKeyException expected) {
+                }
+            }
+        }
+    }
+
+    public static class FakeProtectionParameter implements ProtectionParameter {
+    }
+
+    public void test_KeyStore_setEntry() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            try {
+                keyStore.setEntry(null, null, null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            try {
+                keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), new FakeProtectionParameter());
+                fail("Should not accept unknown ProtectionParameter: " + keyStore.getProvider());
+            } catch (KeyStoreException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            // test odd inputs
+            try {
+                keyStore.setEntry(null, null, null);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            try {
+                keyStore.setEntry(null, null, PARAM_KEY);
+                fail(keyStore.getType());
+            } catch (Exception e) {
+                if (e.getClass() != NullPointerException.class
+                    && e.getClass() != KeyStoreException.class) {
+                    throw e;
+                }
+            }
+            try {
+                keyStore.setEntry("", null, PARAM_KEY);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            clearKeyStore(keyStore);
+
+            // test case sensitive
+            assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+            if (isReadOnly(keyStore)) {
+                try {
+                    keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), PARAM_KEY);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                continue;
+            }
+            if (isKeyPasswordSupported(keyStore)) {
+                keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), PARAM_KEY);
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_PRIVATE));
+            }
+            if (isNullPasswordAllowed(keyStore)) {
+                keyStore.setEntry(ALIAS_NO_PASSWORD_PRIVATE, getPrivateKey(), null);
+                assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_NO_PASSWORD_PRIVATE));
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                keyStore.setEntry(ALIAS_SECRET, new SecretKeyEntry(getSecretKey()), PARAM_KEY);
+                assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+            } else {
+                try {
+                    keyStore.setKeyEntry(ALIAS_SECRET, getSecretKey(), PASSWORD_KEY, null);
+                    fail(keyStore.getType());
+                } catch (KeyStoreException expected) {
+                }
+            }
+            if (isCertificateEnabled(keyStore)) {
+                assertNull(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                keyStore.setEntry(ALIAS_CERTIFICATE,
+                                  new TrustedCertificateEntry(getPrivateKey().getCertificate()),
+                                  null);
+                assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+            } else {
+                try {
+                    keyStore.setEntry(ALIAS_CERTIFICATE,
+                                      new TrustedCertificateEntry(getPrivateKey().getCertificate()),
+                                      null);
+                    fail(keyStore.getType());
+                } catch (KeyStoreException expected) {
+                }
+            }
+            if (isKeyPasswordSupported(keyStore)) {
+                keyStore.setEntry(ALIAS_UNICODE_PRIVATE, getPrivateKey(), PARAM_KEY);
+                assertPrivateKey(keyStore.getKey(ALIAS_UNICODE_PRIVATE, PASSWORD_KEY));
+                assertCertificateChain(keyStore.getCertificateChain(ALIAS_UNICODE_PRIVATE));
+            }
+            if (isNullPasswordAllowed(keyStore)) {
+                keyStore.setEntry(ALIAS_UNICODE_NO_PASSWORD_PRIVATE, getPrivateKey(), null);
+                assertPrivateKey(keyStore.getKey(ALIAS_UNICODE_NO_PASSWORD_PRIVATE, null));
+                assertCertificateChain(keyStore
+                        .getCertificateChain(ALIAS_UNICODE_NO_PASSWORD_PRIVATE));
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_UNICODE_SECRET, PASSWORD_KEY));
+                keyStore.setEntry(ALIAS_UNICODE_SECRET, new SecretKeyEntry(getSecretKey()), PARAM_KEY);
+                assertSecretKey(keyStore.getKey(ALIAS_UNICODE_SECRET, PASSWORD_KEY));
+            } else {
+                try {
+                    keyStore.setKeyEntry(ALIAS_UNICODE_SECRET, getSecretKey(), PASSWORD_KEY, null);
+                    fail(keyStore.getType());
+                } catch (KeyStoreException expected) {
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            if (isReadOnly(keyStore)) {
+                assertNull(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+            } else if (isCaseSensitive(keyStore)) {
+                if (isKeyPasswordSupported(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                    assertNull(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                    keyStore.setEntry(ALIAS_ALT_CASE_PRIVATE, getPrivateKey2(), PARAM_KEY);
+                    assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                    assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                }
+
+                if (isNullPasswordAllowed(keyStore)) {
+                    assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                    assertNull(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null));
+                    keyStore.setEntry(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, getPrivateKey2(), null);
+                    assertPrivateKey(keyStore.getKey(ALIAS_NO_PASSWORD_PRIVATE, null));
+                    assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_NO_PASSWORD_PRIVATE, null));
+                }
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertNull(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                    keyStore.setEntry(ALIAS_ALT_CASE_SECRET,
+                                      new SecretKeyEntry(getSecretKey2()),
+                                      PARAM_KEY);
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey2(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+
+                if (isCertificateEnabled(keyStore)) {
+                    assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    assertNull(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                    keyStore.setEntry(ALIAS_ALT_CASE_CERTIFICATE,
+                                      new TrustedCertificateEntry(
+                                              getPrivateKey2().getCertificate()),
+                                      null);
+                    assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    assertCertificate2(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                    keyStore.setEntry(ALIAS_UNICODE_CERTIFICATE,
+                                      new TrustedCertificateEntry(
+                                              getPrivateKey().getCertificate()),
+                                      null);
+                    assertCertificate(keyStore.getCertificate(ALIAS_UNICODE_CERTIFICATE));
+                }
+            } else {
+                assertPrivateKey(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertPrivateKey(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+                keyStore.setEntry(ALIAS_ALT_CASE_PRIVATE, getPrivateKey2(), PARAM_KEY);
+                assertPrivateKey2(keyStore.getKey(ALIAS_PRIVATE, PASSWORD_KEY));
+                assertPrivateKey2(keyStore.getKey(ALIAS_ALT_CASE_PRIVATE, PASSWORD_KEY));
+
+                if (isSecretKeyEnabled(keyStore)) {
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                    keyStore.setEntry(ALIAS_ALT_CASE_SECRET,
+                                      new SecretKeyEntry(getSecretKey2()),
+                                      PARAM_KEY);
+                    assertSecretKey2(keyStore.getKey(ALIAS_SECRET, PASSWORD_KEY));
+                    assertSecretKey2(keyStore.getKey(ALIAS_ALT_CASE_SECRET, PASSWORD_KEY));
+                }
+
+                if (isCertificateEnabled(keyStore)) {
+                    assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    assertCertificate(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                    keyStore.setEntry(ALIAS_ALT_CASE_CERTIFICATE,
+                                      new TrustedCertificateEntry(
+                                              getPrivateKey2().getCertificate()),
+                                      null);
+                    assertCertificate2(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                    assertCertificate2(keyStore.getCertificate(ALIAS_ALT_CASE_CERTIFICATE));
+                    keyStore.setEntry(ALIAS_UNICODE_CERTIFICATE,
+                                      new TrustedCertificateEntry(
+                                              getPrivateKey().getCertificate()),
+                                      null);
+                    assertCertificate(keyStore.getCertificate(ALIAS_UNICODE_CERTIFICATE));
+                }
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            // test with null/non-null passwords
+            if (isReadOnly(keyStore)) {
+                try {
+                    keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), null);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                try {
+                    keyStore.setEntry(ALIAS_SECRET, new SecretKeyEntry(getSecretKey()), null);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                try {
+                    keyStore.setEntry(ALIAS_CERTIFICATE,
+                                      new TrustedCertificateEntry(getPrivateKey().getCertificate()),
+                                      null);
+                    fail(keyStore.getType());
+                } catch (UnsupportedOperationException expected) {
+                }
+                continue;
+            }
+            if (isNullPasswordAllowed(keyStore) || isKeyPasswordIgnored(keyStore)) {
+                for (String keyType : KEY_TYPES) {
+                    keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(keyType), null);
+                    assertPrivateKey(keyType, keyStore.getKey(ALIAS_PRIVATE, null));
+                }
+            } else {
+                try {
+                    keyStore.setEntry(ALIAS_PRIVATE, getPrivateKey(), null);
+                    fail(keyStore.getType());
+                } catch (Exception e) {
+                    if (e.getClass() != UnrecoverableKeyException.class
+                        && e.getClass() != IllegalArgumentException.class
+                        && e.getClass() != KeyStoreException.class) {
+                        throw e;
+                    }
+                }
+            }
+            if (isSecretKeyEnabled(keyStore)) {
+                if (isNullPasswordAllowed(keyStore) || isKeyPasswordIgnored(keyStore)) {
+                    keyStore.setEntry(ALIAS_SECRET, new SecretKeyEntry(getSecretKey()), null);
+                    assertSecretKey(keyStore.getKey(ALIAS_SECRET, null));
+                } else {                    
+                    try {
+                        keyStore.setEntry(ALIAS_SECRET, new SecretKeyEntry(getSecretKey()), null);
+                        fail(keyStore.getType());
+                    } catch (Exception e) {
+                        if (e.getClass() != UnrecoverableKeyException.class
+                            && e.getClass() != IllegalArgumentException.class
+                            && e.getClass() != KeyStoreException.class) {
+                            throw e;
+                        }
+                    }
+                }
+            }
+            if (isCertificateEnabled(keyStore)) {
+                if (isNullPasswordAllowed(keyStore) || isKeyPasswordIgnored(keyStore)) {
+                    keyStore.setEntry(ALIAS_CERTIFICATE,
+                                      new TrustedCertificateEntry(getPrivateKey().getCertificate()),
+                                      PARAM_KEY);
+                    assertCertificate(keyStore.getCertificate(ALIAS_CERTIFICATE));
+                } else {
+                    try {
+                        keyStore.setEntry(ALIAS_CERTIFICATE,
+                                          new TrustedCertificateEntry(
+                                                  getPrivateKey().getCertificate()),
+                                          PARAM_KEY);
+                        fail(keyStore.getType());
+                    } catch (KeyStoreException expected) {
+                    }
+                }
+            }
+        }
+    }
+
+    public void test_KeyStore_entryInstanceOf() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                keyStore.entryInstanceOf(null, null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+
+            try {
+                keyStore.entryInstanceOf(null, null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+            try {
+                keyStore.entryInstanceOf(null, Entry.class);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+            try {
+                keyStore.entryInstanceOf("", null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+
+            assertFalse(keyStore.entryInstanceOf("", Entry.class));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            // test odd inputs
+            assertFalse(keyStore.entryInstanceOf("", Entry.class));
+            assertFalse(keyStore.entryInstanceOf("", PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf("", SecretKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf("", TrustedCertificateEntry.class));
+
+            if (isReadOnly(keyStore)) {
+                assertFalse(keyStore.entryInstanceOf(ALIAS_PRIVATE, PrivateKeyEntry.class));
+                assertFalse(keyStore.entryInstanceOf(ALIAS_PRIVATE, SecretKeyEntry.class));
+                assertFalse(keyStore.entryInstanceOf(ALIAS_PRIVATE, TrustedCertificateEntry.class));
+
+                assertFalse(keyStore.entryInstanceOf(ALIAS_SECRET, SecretKeyEntry.class));
+                assertFalse(keyStore.entryInstanceOf(ALIAS_SECRET, PrivateKeyEntry.class));
+                assertFalse(keyStore.entryInstanceOf(ALIAS_SECRET, TrustedCertificateEntry.class));
+
+                assertFalse(keyStore.entryInstanceOf(ALIAS_CERTIFICATE,
+                                                     TrustedCertificateEntry.class));
+                assertFalse(keyStore.entryInstanceOf(ALIAS_CERTIFICATE, PrivateKeyEntry.class));
+                assertFalse(keyStore.entryInstanceOf(ALIAS_CERTIFICATE, SecretKeyEntry.class));
+                continue;
+            }
+
+            // test case sensitive
+            assertEquals(isKeyPasswordSupported(keyStore),
+                    keyStore.entryInstanceOf(ALIAS_PRIVATE, PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_PRIVATE, SecretKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_PRIVATE, TrustedCertificateEntry.class));
+
+            assertEquals(isNullPasswordAllowed(keyStore),
+                    keyStore.entryInstanceOf(ALIAS_NO_PASSWORD_PRIVATE, PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_NO_PASSWORD_PRIVATE, SecretKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_NO_PASSWORD_PRIVATE,
+                    TrustedCertificateEntry.class));
+
+            assertEquals(isSecretKeyEnabled(keyStore),
+                         keyStore.entryInstanceOf(ALIAS_SECRET, SecretKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_SECRET, PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_SECRET, TrustedCertificateEntry.class));
+
+            assertEquals(isCertificateEnabled(keyStore),
+                         keyStore.entryInstanceOf(ALIAS_CERTIFICATE,
+                                                  TrustedCertificateEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_CERTIFICATE, PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_CERTIFICATE, SecretKeyEntry.class));
+
+            // test case insensitive
+            assertEquals(!isCaseSensitive(keyStore),
+                         keyStore.entryInstanceOf(ALIAS_ALT_CASE_PRIVATE, PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_ALT_CASE_PRIVATE, SecretKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_ALT_CASE_PRIVATE,
+                                                 TrustedCertificateEntry.class));
+
+            assertEquals(!isCaseSensitive(keyStore) && isSecretKeyEnabled(keyStore),
+                         keyStore.entryInstanceOf(ALIAS_ALT_CASE_SECRET, SecretKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_ALT_CASE_SECRET, PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_ALT_CASE_SECRET,
+                                                 TrustedCertificateEntry.class));
+
+            assertEquals(!isCaseSensitive(keyStore) && isCertificateEnabled(keyStore),
+                         keyStore.entryInstanceOf(ALIAS_ALT_CASE_CERTIFICATE,
+                                                  TrustedCertificateEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_ALT_CASE_CERTIFICATE,
+                                                 PrivateKeyEntry.class));
+            assertFalse(keyStore.entryInstanceOf(ALIAS_ALT_CASE_CERTIFICATE, SecretKeyEntry.class));
+        }
+    }
+
+    // TODO(27810271): investigate why this is taking too long for armeabi-v7a
+    @TimeoutReq(minutes=10)
+    public void test_KeyStore_Builder() throws Exception {
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            try {
+                Builder.newInstance(keyStore, null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                Builder.newInstance(keyStore.getType(),
+                                    keyStore.getProvider(),
+                                    null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            try {
+                Builder.newInstance(null,
+                                    null,
+                                    null,
+                                    null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+            try {
+                Builder.newInstance(keyStore.getType(),
+                                    keyStore.getProvider(),
+                                    null,
+                                    null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            keyStore.load(null, null);
+            Builder builder = Builder.newInstance(keyStore, PARAM_STORE);
+            try {
+                builder.getProtectionParameter(null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+            assertEquals(keyStore, builder.getKeyStore());
+            try {
+                builder.getProtectionParameter(null);
+                fail(keyStore.getType());
+            } catch (NullPointerException expected) {
+            }
+            assertEquals(PARAM_STORE, builder.getProtectionParameter(""));
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            populate(keyStore);
+
+            File file = File.createTempFile("keystore", keyStore.getProvider().getName());
+            OutputStream os = null;
+            try {
+                os = new FileOutputStream(file);
+                if (isLoadStoreUnsupported(keyStore) || isReadOnly(keyStore)) {
+                    try {
+                        keyStore.store(os, PASSWORD_STORE);
+                        fail(keyStore.getType());
+                    } catch (UnsupportedOperationException expected) {
+                    }
+                    continue;
+                }
+
+                keyStore.store(os, PASSWORD_STORE);
+                os.close();
+                Builder builder = Builder.newInstance(keyStore.getType(),
+                                                      keyStore.getProvider(),
+                                                      file,
+                                                      PARAM_STORE);
+                assertEquals(keyStore.getType(), builder.getKeyStore().getType());
+                assertEquals(keyStore.getProvider(), builder.getKeyStore().getProvider());
+                assertEquals(PARAM_STORE, builder.getProtectionParameter(""));
+                assertEqualsKeyStores(file, PASSWORD_STORE, keyStore);
+            } finally {
+                try {
+                    if (os != null) {
+                        os.close();
+                    }
+                } catch (IOException ignored) {
+                }
+                file.delete();
+            }
+        }
+
+        for (KeyStore keyStore : keyStores()) {
+            if (isLoadStoreUnsupported(keyStore)) {
+                continue;
+            }
+            Builder builder = Builder.newInstance(keyStore.getType(),
+                                                  keyStore.getProvider(),
+                                                  PARAM_STORE);
+            assertEquals(keyStore.getType(), builder.getKeyStore().getType());
+            assertEquals(keyStore.getProvider(), builder.getKeyStore().getProvider());
+            assertEquals(PARAM_STORE, builder.getProtectionParameter(""));
+        }
+    }
+
+    public void test_KeyStore_cacerts() throws Exception {
+        if (StandardNames.IS_RI) {
+            return;
+        }
+        KeyStore ks = KeyStore.getInstance("AndroidCAStore");
+        assertEquals("AndroidCAStore", ks.getType());
+        assertEquals("HarmonyJSSE", ks.getProvider().getName());
+
+        ks.load(null, null);
+        for (String alias : Collections.list(ks.aliases())) {
+            Certificate c = null;
+            try {
+                c = ks.getCertificate(alias);
+                assertNotNull(c);
+                assertTrue(ks.isCertificateEntry(alias));
+                assertTrue(ks.entryInstanceOf(alias, TrustedCertificateEntry.class));
+                assertEquals(alias, ks.getCertificateAlias(c));
+
+                assertTrue(c instanceof X509Certificate);
+                X509Certificate cert = (X509Certificate) c;
+                assertEquals(cert.getSubjectUniqueID(), cert.getIssuerUniqueID());
+                assertNotNull(cert.getPublicKey());
+
+                assertTrue(ks.containsAlias(alias));
+                assertNotNull(ks.getCreationDate(alias));
+                assertNotNull(ks.getEntry(alias, null));
+
+                assertFalse(ks.isKeyEntry(alias));
+                assertNull(ks.getKey(alias, null));
+                assertNull(ks.getCertificateChain(alias));
+
+            } catch (Throwable t) {
+                throw new Exception("alias=" + alias + " cert=" + c, t);
+            }
+        }
+    }
+
+    // http://b/857840: want JKS key store
+    public void testDefaultKeystore() {
+        String type = KeyStore.getDefaultType();
+        assertEquals(StandardNames.KEY_STORE_ALGORITHM, type);
+
+        try {
+            KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
+            assertNotNull("Keystore must not be null", store);
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+
+        try {
+            KeyStore store = KeyStore.getInstance(StandardNames.KEY_STORE_ALGORITHM);
+            assertNotNull("Keystore must not be null", store);
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+}
diff --git a/tests/tests/location/src/android/location/cts/GnssMeasurementValuesTest.java b/tests/tests/location/src/android/location/cts/GnssMeasurementValuesTest.java
index 65733ec..e8b8c74 100644
--- a/tests/tests/location/src/android/location/cts/GnssMeasurementValuesTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssMeasurementValuesTest.java
@@ -41,7 +41,7 @@
  */
 public class GnssMeasurementValuesTest extends AndroidTestCase {
 
-    private static final String TAG = "GpsMeasValuesTest";
+    private static final String TAG = "GnssMeasValuesTest";
     private static final int LOCATION_TO_COLLECT_COUNT = 5;
 
     private TestLocationManager mTestLocationManager;
diff --git a/tests/tests/location/src/android/location/cts/GnssMeasurementWhenNoLocationTest.java b/tests/tests/location/src/android/location/cts/GnssMeasurementWhenNoLocationTest.java
index b6d1e13..7a2bead 100644
--- a/tests/tests/location/src/android/location/cts/GnssMeasurementWhenNoLocationTest.java
+++ b/tests/tests/location/src/android/location/cts/GnssMeasurementWhenNoLocationTest.java
@@ -57,7 +57,7 @@
  */
 public class GnssMeasurementWhenNoLocationTest extends AndroidTestCase {
 
-    private static final String TAG = "GpsMeasWhenNoFixTest";
+    private static final String TAG = "GnssMeasWhenNoFixTest";
     private TestGnssMeasurementListener mMeasurementListener;
     private TestLocationManager mTestLocationManager;
     private TestGpsStatusListener mGpsStatusListener;
@@ -121,13 +121,18 @@
             return;
         }
         if (!mGpsStatusListener.isGpsStatusReceived()) {
-            Log.i(TAG, "No Satellites are visible. Device may be Indoor. Skip test.");
+            Log.i(TAG, "No Satellites are visible. Device may be indoors. Skip test.");
             return;
         }
 
         List<GnssMeasurementsEvent> events = mMeasurementListener.getEvents();
         Log.i(TAG, "Number of GPS measurement events received = " + events.size());
 
+        if (events.isEmpty()) {
+            Log.i(TAG, "No GPS measurement events received. Device may be indoors. Skip test.");
+            return;
+        }
+
         // If device is not indoor, verify that we receive GPS measurements before being able to
         // calculate the position solution and verify that mandatory fields of GnssMeasurement are
         // in expected ranges.
diff --git a/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java b/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
index 3d10127..f7cf144 100644
--- a/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
+++ b/tests/tests/location/src/android/location/cts/TestMeasurementUtil.java
@@ -19,6 +19,7 @@
 import android.location.GnssMeasurement;
 import android.location.GnssNavigationMessage;
 import android.location.GnssNavigationMessageEvent;
+import android.location.GnssStatus;
 import android.location.LocationManager;
 import android.os.Build;
 import android.util.Log;
@@ -27,34 +28,32 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * Helper class for Gps Measurement Tests.
+ * Helper class for GnssMeasurement Tests.
  */
 public final class TestMeasurementUtil {
 
     private static final String TAG = "TestMeasurementUtil";
     // Error message for GnssMeasurements Registration.
-    public static final String REGISTRATION_ERROR_MESSAGE =  "Registration of GnssMeasurements" +
+    public static final String REGISTRATION_ERROR_MESSAGE = "Registration of GnssMeasurements" +
             " listener has failed, this indicates a platform bug. Please report the issue with" +
             " a full bugreport.";
-    private static final double MILLISECOND_DIVISOR = 1E6;
-    private static final double NANOSECOND_DIVISOR = 1E9;
 
     /**
      * Check if test can be run on the current device.
      *
-     * @param testLocationManager TestLocationManager
-     *
-     * @return true if Build.VERSION &gt;= Build.VERSION_CODES.LOLLIPOP_MR1,
-     *         Build.VERSION &lt;= Build.VERSION_CODES.M,
-     *         and location enabled in device.
+     * @param  testLocationManager TestLocationManager
+     * @return true if Build.VERSION &gt;=  Build.VERSION_CODES.N and location enabled in device.
      */
     public static boolean canTestRunOnCurrentDevice(TestLocationManager testLocationManager) {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
-            Log.i(TAG, "This test is designed to work on Lollipop MR1 or newer. " +
+       // TODO(sumitk): Enable this check once api 24 for N is avaiable.
+       /*
+       if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+            Log.i(TAG, "This test is designed to work on N or newer. " +
                     "Test is being skipped because the platform version is being run in " +
                     Build.VERSION.SDK_INT);
             return false;
         }
+        */
 
         if (!testLocationManager.getLocationManager()
                 .isProviderEnabled(LocationManager.GPS_PROVIDER)) {
@@ -66,102 +65,56 @@
     }
 
     /**
-     * Assert all mandatory fields in GPS Measurement are in expected range.
+     * Assert all mandatory fields in Gnss Measurement are in expected range.
      * See mandatory fields in {@code gps.h}.
      *
      * @param measurement GnssMeasurement
-     * @param softAssert custom SoftAssert
-     * @param timeInNs event time in ns
+     * @param softAssert  custom SoftAssert
+     * @param timeInNs    event time in ns
      */
     public static void assertAllGnssMeasurementMandatoryFields(GnssMeasurement measurement,
         SoftAssert softAssert, long timeInNs) {
-        // TODO(sumitk): Check for provided optional values
-        // TODO(sumitk): Set a max limit for each of the values.
-        softAssert.assertTrue("prn: Pseudo-random number",
-                timeInNs,
-                "[1, 32]",
-                String.valueOf(measurement.getSvid()),
-                measurement.getSvid() > 0 && measurement.getSvid() <= 32);
+
+        verifySvid(measurement, softAssert, timeInNs);
+        verifyReceivedSatelliteVehicleTimeInNs(measurement, softAssert, timeInNs);
+        verifyAccumulatedDeltaRanges(measurement, softAssert, timeInNs);
+
         int state = measurement.getState();
         softAssert.assertTrue("state: Satellite code sync state",
                 timeInNs,
-                "X >= 0",
+                "X > 0",
                 String.valueOf(state),
-                state >= 0);
+                state > 0);
 
-        // Verify received GPS Time-of-Week ranges.
-        long received_gps_tow_ns = measurement.getReceivedSvTimeNanos();
-        double gps_tow_ms = received_gps_tow_ns / MILLISECOND_DIVISOR;
-        double gps_tow_days = TimeUnit.NANOSECONDS.toDays(received_gps_tow_ns);
-        // Check ranges for received_gps_tow_ns for given Gps State
-        if (state == 0) {
-            softAssert.assertTrue("received_gps_tow_ns:" +
-                            " Received GPS Time-of-Week in ns." +
-                            " GPS_MEASUREMENT_STATE_UNKNOWN.",
-                    timeInNs,
-                    "X == 0",
-                    String.valueOf(received_gps_tow_ns),
-                    gps_tow_ms == 0);
-        } else if (state > 0 && state <= 1) {
-            softAssert.assertTrue("received_gps_tow_ns:" +
-                            " Received GPS Time-of-Week in ns." +
-                            " GPS_MEASUREMENT_STATE_CODE_LOCK.",
-                    timeInNs,
-                    "0ms > X <= 1ms",
-                    String.valueOf(received_gps_tow_ns),
-                    gps_tow_ms > 0 && gps_tow_ms <= 1);
-        } else if (state > 1 && state <= 3) {
-            softAssert.assertTrue("received_gps_tow_ns:" +
-                            " Received GPS Time-of-Week in ns." +
-                            " GPS_MEASUREMENT_STATE_BIT_SYNC.",
-                    timeInNs,
-                    "0ms > X <= 20ms",
-                    String.valueOf(received_gps_tow_ns),
-                    gps_tow_ms > 0 && gps_tow_ms <= 20);
-        } else if (state > 3 && state <= 7) {
-            softAssert.assertTrue("received_gps_tow_ns:" +
-                            " Received GPS Time-of-Week in ns." +
-                            " GPS_MEASUREMENT_STATE_SUBFRAME_SYNC.",
-                    timeInNs,
-                    "0ms > X <= 6000ms",
-                    String.valueOf(received_gps_tow_ns),
-                    gps_tow_ms > 0 && gps_tow_ms <= 6000);
-        } else if (state > 7 && state <= 15) {
-            softAssert.assertTrue("received_gps_tow_ns:" +
-                            " Received GPS Time-of-Week in ns." +
-                            " GPS_MEASUREMENT_STATE_TOW_DECODED.",
-                    timeInNs,
-                    "0 > X <= 1 week",
-                    String.valueOf(received_gps_tow_ns),
-                    gps_tow_ms > 0 && gps_tow_days <= 7);
-        }
-        // if state != GPS_MEASUREMENT_STATE_UNKNOWN.
-        if (state != 0){
-            softAssert.assertTrueAsWarning("received_gps_tow_uncertainty_ns:" +
-                            " Uncertainty of received GPS Time-of-Week in ns",
-                    timeInNs,
-                    "X > 0",
-                    String.valueOf(measurement.getReceivedSvTimeUncertaintyNanos()),
-                    measurement.getReceivedSvTimeUncertaintyNanos() > 0L);
-        }
+        // Check received_gps_tow_uncertainty_ns
+        softAssert.assertTrueAsWarning("received_gps_tow_uncertainty_ns:" +
+                        " Uncertainty of received GPS Time-of-Week in ns",
+                timeInNs,
+                "X > 0",
+                String.valueOf(measurement.getReceivedSvTimeUncertaintyNanos()),
+                measurement.getReceivedSvTimeUncertaintyNanos() > 0L);
 
-        double timeOffsetInSec = measurement.getTimeOffsetNanos() / NANOSECOND_DIVISOR;
+        long timeOffsetInSec = TimeUnit.NANOSECONDS.toSeconds(
+                (long) measurement.getTimeOffsetNanos());
         softAssert.assertTrue("time_offset_ns: Time offset",
                 timeInNs,
-                "X < 1 sec",
+                "-100 seconds < X < +10 seconds",
                 String.valueOf(measurement.getTimeOffsetNanos()),
-                timeOffsetInSec < 1.0);
+                (-100 < timeOffsetInSec) && (timeOffsetInSec < 10));
+
         softAssert.assertTrue("c_n0_dbhz: Carrier-to-noise density",
                 timeInNs,
                 "0.0 >= X <=63",
                 String.valueOf(measurement.getCn0DbHz()),
                 measurement.getCn0DbHz() >= 0.0 &&
                         measurement.getCn0DbHz() <= 63.0);
+
         softAssert.assertTrue("pseudorange_rate_mps: Pseudorange rate in m/s",
                 timeInNs,
                 "X != 0.0",
                 String.valueOf(measurement.getPseudorangeRateMetersPerSecond()),
                 measurement.getPseudorangeRateMetersPerSecond() != 0.0);
+
         softAssert.assertTrue("pseudorange_rate_uncertainty_mps: " +
                         "Pseudorange Rate Uncertainty in m/s",
                 timeInNs,
@@ -169,13 +122,71 @@
                 String.valueOf(
                         measurement.getPseudorangeRateUncertaintyMetersPerSecond()),
                 measurement.getPseudorangeRateUncertaintyMetersPerSecond() > 0.0);
+
+        // Check carrier_frequency_hz.
+        if (measurement.hasCarrierFrequencyHz()) {
+            softAssert.assertTrue("carrier_frequency_hz: Carrier frequency in hz",
+                    timeInNs,
+                    "X > 0.0",
+                    String.valueOf(measurement.getCarrierFrequencyHz()),
+                    measurement.getCarrierFrequencyHz() > 0.0);
+        }
+
+        // Check carrier_phase.
+        if (measurement.hasCarrierPhase()) {
+            softAssert.assertTrue("carrier_phase: Carrier phase",
+                    timeInNs,
+                    "0.0 >= X <= 1.0",
+                    String.valueOf(measurement.getCarrierPhase()),
+                    measurement.getCarrierPhase() >= 0.0 && measurement.getCarrierPhase() <= 1.0);
+        }
+
+        // Check carrier_phase_uncertainty..
+        if (measurement.hasCarrierPhaseUncertainty()) {
+            softAssert.assertTrue("carrier_phase_uncertainty: 1-Sigma uncertainty of the " +
+                            "carrier-phase",
+                    timeInNs,
+                    "X > 0.0",
+                    String.valueOf(measurement.getCarrierPhaseUncertainty()),
+                    measurement.getCarrierPhaseUncertainty() > 0.0);
+        }
+
+        // Check GNSS Measurement's multipath_indicator.
+        softAssert.assertTrue("multipath_indicator: GNSS Measurement's multipath indicator",
+                timeInNs,
+                "0 >= X <= 2",
+                String.valueOf(measurement.getMultipathIndicator()),
+                measurement.getMultipathIndicator() >= 0
+                        && measurement.getMultipathIndicator() <= 2);
+
+
+        // Check Signal-to-Noise ratio (SNR).
+        if (measurement.hasSnrInDb()) {
+            softAssert.assertTrue("snr: Signal-to-Noise ratio (SNR) in dB",
+                    timeInNs,
+                    "0.0 >= X <= 63",
+                    String.valueOf(measurement.getSnrInDb()),
+                    measurement.getSnrInDb() >= 0.0 && measurement.getSnrInDb() <= 63);
+        }
+    }
+
+    /**
+     * Verify accumulated delta ranges are in expected range.
+     *
+     * @param measurement GnssMeasurement
+     * @param softAssert  custom SoftAssert
+     * @param timeInNs    event time in ns
+     */
+    private static void verifyAccumulatedDeltaRanges(GnssMeasurement measurement,
+        SoftAssert softAssert, long timeInNs) {
+
         int accumulatedDeltaRangeState = measurement.getAccumulatedDeltaRangeState();
         softAssert.assertTrue("accumulated_delta_range_state: " +
-                        "Accumulated delta range's state",
+                        "Accumulated delta range state",
                 timeInNs,
-                "X >= 0.0",
+                "0 <= X <= 7",
                 String.valueOf(accumulatedDeltaRangeState),
-                accumulatedDeltaRangeState >= 0.0);
+                accumulatedDeltaRangeState >= 0 && accumulatedDeltaRangeState <= 7);
         if (accumulatedDeltaRangeState > 0) {
             double accumulatedDeltaRangeInMeters =
                     measurement.getAccumulatedDeltaRangeMeters();
@@ -188,7 +199,7 @@
             double accumulatedDeltaRangeUncertainty =
                     measurement.getAccumulatedDeltaRangeUncertaintyMeters();
             softAssert.assertTrue("accumulated_delta_range_uncertainty_m: " +
-                            "Accumulated delta range's uncertainty in meter",
+                            "Accumulated delta range uncertainty in meter",
                     timeInNs,
                     "X > 0.0",
                     String.valueOf(accumulatedDeltaRangeUncertainty),
@@ -197,6 +208,374 @@
     }
 
     /**
+     * Verify svid's are in expected range.
+     *
+     * @param measurement GnssMeasurement
+     * @param softAssert  custom SoftAssert
+     * @param timeInNs    event time in ns
+     */
+    private static void verifySvid(GnssMeasurement measurement, SoftAssert softAssert,
+        long timeInNs) {
+
+        String svidLogMessageFormat = "svid: Space Vehicle ID. Constellation type = %s";
+        int constellationType = measurement.getConstellationType();
+        int svid = measurement.getSvid();
+        String svidValue = String.valueOf(svid);
+
+        switch (constellationType) {
+            case GnssStatus.CONSTELLATION_GPS:
+                softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " +
+                                "= CONSTELLATION_GPS",
+                        timeInNs,
+                        "[1, 32]",
+                        svidValue,
+                        svid > 0 && svid <= 32);
+                break;
+            case GnssStatus.CONSTELLATION_SBAS:
+                softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " +
+                                "= CONSTELLATION_SBAS",
+                        timeInNs,
+                        "120 <= X <= 192",
+                        svidValue,
+                        svid >= 120 && svid <= 192);
+                break;
+            case GnssStatus.CONSTELLATION_GLONASS:
+                // Check Upper 8 bit, signed
+                int freq = (svid >> 8);
+                softAssert.assertTrue("svid: upper 8 bits, frequency number. Constellation type " +
+                                "= CONSTELLATION_GLONASS",
+                        timeInNs,
+                        "freq == -127 || -7 <= freq <= 6",
+                        svidValue,
+                        (freq == -127) || (freq >= -7 && freq <= 6));
+                // Check lower 8 bits, signed
+                byte slot = (byte) svid;
+                softAssert.assertTrue("svid: lower 8 bits, slot. Constellation type " +
+                                "= CONSTELLATION_GLONASS",
+                        timeInNs,
+                        "slot == -127 || 1 <= slot <= 24",
+                        svidValue,
+                        (slot == -127) || (slot >= 1 && slot <= 24));
+                softAssert.assertTrue("svid: one of slot or freq is set (not -127). " +
+                                "ConstellationType = CONSTELLATION_GLONASS,",
+                        timeInNs,
+                        "slot != -127 || freq != -127",
+                        svidValue,
+                        (slot != -127) || (freq != -127));
+                break;
+            case GnssStatus.CONSTELLATION_QZSS:
+                softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " +
+                                "= CONSTELLATION_QZSS",
+                        timeInNs,
+                        "193 <= X <= 200",
+                        svidValue,
+                        svid >= 193 && svid <= 200);
+                break;
+            case GnssStatus.CONSTELLATION_BEIDOU:
+                softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " +
+                                "= CONSTELLATION_BEIDOU",
+                        timeInNs,
+                        "1 <= X <= 36",
+                        svidValue,
+                        svid >= 1 && svid <= 36);
+                break;
+            case GnssStatus.CONSTELLATION_GALILEO:
+                softAssert.assertTrue("svid: Space Vehicle ID. Constellation type " +
+                                "= CONSTELLATION_GALILEO",
+                        timeInNs,
+                        "1 <= X <= 37",
+                        String.valueOf(svid),
+                        svid >= 1 && svid <= 37);
+                break;
+            default:
+                // Explicit fail if did not receive valid constellation type.
+                softAssert.assertTrue("svid: Space Vehicle ID. Did not receive any valid " +
+                                "constellation type.",
+                        timeInNs,
+                        "Valid constellation type.",
+                        svidValue,
+                        false);
+                break;
+        }
+    }
+
+    /**
+     * Verify sv times are in expected range.
+     *
+     * @param measurement GnssMeasurement
+     * @param softAssert  custom SoftAssert
+     * @param timeInNs    event time in ns
+     * */
+    private static void verifyReceivedSatelliteVehicleTimeInNs(GnssMeasurement measurement,
+        SoftAssert softAssert, long timeInNs) {
+
+        int constellationType = measurement.getConstellationType();
+        int state = measurement.getState();
+        long received_sv_time_ns = measurement.getReceivedSvTimeNanos();
+        double sv_time_ms = TimeUnit.NANOSECONDS.toMillis(received_sv_time_ns);
+        double sv_time_sec = TimeUnit.NANOSECONDS.toSeconds(received_sv_time_ns);
+        double sv_time_days = TimeUnit.NANOSECONDS.toDays(received_sv_time_ns);
+
+        // Check ranges for received_sv_time_ns for given Gps State
+        if (state == 0) {
+            softAssert.assertTrue("received_sv_time_ns:" +
+                            " Received SV Time-of-Week in ns." +
+                            " GNSS_MEASUREMENT_STATE_UNKNOWN.",
+                    timeInNs,
+                    "X == 0",
+                    String.valueOf(received_sv_time_ns),
+                    sv_time_ms == 0);
+        }
+
+        switch (constellationType) {
+            case GnssStatus.CONSTELLATION_GPS:
+                verifyGpsQzssSvTimes(measurement, softAssert, timeInNs, state, "CONSTELLATION_GPS");
+                break;
+            case GnssStatus.CONSTELLATION_QZSS:
+                verifyGpsQzssSvTimes(measurement, softAssert, timeInNs, state,
+                        "CONSTELLATION_QZSS");
+                break;
+            case GnssStatus.CONSTELLATION_SBAS:
+                if ((state | GnssMeasurement.STATE_SBAS_SYNC)
+                        == GnssMeasurement.STATE_SBAS_SYNC) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_SBAS_SYNC",
+                                    "GnssStatus.CONSTELLATION_SBAS"),
+                            timeInNs,
+                            "0s >= X <= 1s",
+                            String.valueOf(sv_time_sec),
+                            sv_time_sec >= 0 && sv_time_sec <= 1);
+                } else if ((state | GnssMeasurement.STATE_SYMBOL_SYNC)
+                        == GnssMeasurement.STATE_SYMBOL_SYNC) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_SYMBOL_SYNC",
+                                    "GnssStatus.CONSTELLATION_SBAS"),
+                            timeInNs,
+                            "0ms >= X <= 2ms",
+                            String.valueOf(sv_time_ms),
+                            sv_time_ms >= 0 && sv_time_ms <= 2);
+                } else if ((state | GnssMeasurement.STATE_CODE_LOCK)
+                        == GnssMeasurement.STATE_CODE_LOCK) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_CODE_LOCK",
+                                    "GnssStatus.CONSTELLATION_SBAS"),
+                            timeInNs,
+                            "0ms >= X <= 1ms",
+                            String.valueOf(sv_time_ms),
+                            sv_time_ms >= 0 && sv_time_ms <= 1);
+                }
+                break;
+            case GnssStatus.CONSTELLATION_GLONASS:
+                if ((state | GnssMeasurement.STATE_GLO_TOD_DECODED)
+                        == GnssMeasurement.STATE_GLO_TOD_DECODED) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_GLO_TOD_DECODED",
+                                    "GnssStatus.CONSTELLATION_GLONASS"),
+                            timeInNs,
+                            "0 day >= X <= 1 day",
+                            String.valueOf(sv_time_days),
+                            sv_time_days >= 0 && sv_time_days <= 1);
+                } else if ((state | GnssMeasurement.STATE_GLO_STRING_SYNC)
+                        == GnssMeasurement.STATE_GLO_STRING_SYNC) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_GLO_STRING_SYNC",
+                                    "GnssStatus.CONSTELLATION_GLONASS"),
+                            timeInNs,
+                            "0s >= X <= 2s",
+                            String.valueOf(sv_time_sec),
+                            sv_time_sec >= 0 && sv_time_sec <= 2);
+                } else if ((state | GnssMeasurement.STATE_BIT_SYNC)
+                        == GnssMeasurement.STATE_BIT_SYNC) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_BIT_SYNC",
+                                    "GnssStatus.CONSTELLATION_GLONASS"),
+                            timeInNs,
+                            "0ms >= X <= 20ms",
+                            String.valueOf(sv_time_ms),
+                            sv_time_ms >= 0 && sv_time_ms <= 20);
+                } else if ((state | GnssMeasurement.STATE_SYMBOL_SYNC)
+                        == GnssMeasurement.STATE_SYMBOL_SYNC) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_SYMBOL_SYNC",
+                                    "GnssStatus.CONSTELLATION_GLONASS"),
+                            timeInNs,
+                            "0ms >= X <= 10ms",
+                            String.valueOf(sv_time_ms),
+                            sv_time_ms >= 0 && sv_time_ms <= 10);
+                } else if ((state | GnssMeasurement.STATE_CODE_LOCK)
+                        == GnssMeasurement.STATE_CODE_LOCK) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_CODE_LOCK",
+                                    "GnssStatus.CONSTELLATION_GLONASS"),
+                            timeInNs,
+                            "0ms >= X <= 1ms",
+                            String.valueOf(sv_time_ms),
+                            sv_time_ms >= 0 && sv_time_ms <= 1);
+                }
+                break;
+            case GnssStatus.CONSTELLATION_GALILEO:
+                if ((state | GnssMeasurement.STATE_TOW_DECODED)
+                        == GnssMeasurement.STATE_TOW_DECODED) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_TOW_DECODED",
+                                    "GnssStatus.CONSTELLATION_GALILEO"),
+                            timeInNs,
+                            "0 >= X <= 7 days",
+                            String.valueOf(sv_time_days),
+                            sv_time_days >= 0 && sv_time_days <= 7);
+                } else if ((state | GnssMeasurement.STATE_GAL_E1B_PAGE_SYNC)
+                        == GnssMeasurement.STATE_GAL_E1B_PAGE_SYNC) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_GAL_E1B_PAGE_SYNC",
+                                    "GnssStatus.CONSTELLATION_GALILEO"),
+                            timeInNs,
+                            "0s >= X <= 2s",
+                            String.valueOf(sv_time_sec),
+                            sv_time_sec >= 0 && sv_time_sec <= 2);
+                } else if ((state | GnssMeasurement.STATE_GAL_E1C_2ND_CODE_LOCK)
+                        == GnssMeasurement.STATE_GAL_E1C_2ND_CODE_LOCK) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_GAL_E1C_2ND_CODE_LOCK",
+                                    "GnssStatus.CONSTELLATION_GALILEO"),
+                            timeInNs,
+                            "0ms >= X <= 100ms",
+                            String.valueOf(sv_time_ms),
+                            sv_time_ms >= 0 && sv_time_ms <= 100);
+                } else if ((state | GnssMeasurement.STATE_GAL_E1BC_CODE_LOCK)
+                        == GnssMeasurement.STATE_GAL_E1BC_CODE_LOCK) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_GAL_E1BC_CODE_LOCK",
+                                    "GnssStatus.CONSTELLATION_GALILEO"),
+                            timeInNs,
+                            "0ms >= X <= 4ms",
+                            String.valueOf(sv_time_ms),
+                            sv_time_ms >= 0 && sv_time_ms <= 4);
+                }
+                break;
+            case GnssStatus.CONSTELLATION_BEIDOU:
+                if ((state | GnssMeasurement.STATE_TOW_DECODED)
+                        == GnssMeasurement.STATE_TOW_DECODED) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_TOW_DECODED",
+                                    "GnssStatus.CONSTELLATION_BEIDOU"),
+                            timeInNs,
+                            "0 >= X <= 7 days",
+                            String.valueOf(sv_time_days),
+                            sv_time_days >= 0 && sv_time_days <= 7);
+                } else if ((state | GnssMeasurement.STATE_SUBFRAME_SYNC)
+                        == GnssMeasurement.STATE_SUBFRAME_SYNC) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC",
+                                    "GnssStatus.CONSTELLATION_BEIDOU"),
+                            timeInNs,
+                            "0s >= X <= 6s",
+                            String.valueOf(sv_time_sec),
+                            sv_time_sec >= 0 && sv_time_sec <= 6);
+                } else if ((state | GnssMeasurement.STATE_BDS_D2_SUBFRAME_SYNC)
+                        == GnssMeasurement.STATE_BDS_D2_SUBFRAME_SYNC) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_BDS_D2_SUBFRAME_SYNC",
+                                    "GnssStatus.CONSTELLATION_BEIDOU"),
+                            timeInNs,
+                            "0ms >= X <= 600ms (0.6sec)",
+                            String.valueOf(sv_time_ms),
+                            sv_time_ms >= 0 && sv_time_ms <= 600);
+                } else if ((state | GnssMeasurement.STATE_BIT_SYNC)
+                        == GnssMeasurement.STATE_BIT_SYNC) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_BIT_SYNC",
+                                    "GnssStatus.CONSTELLATION_BEIDOU"),
+                            timeInNs,
+                            "0ms >= X <= 20ms",
+                            String.valueOf(sv_time_ms),
+                            sv_time_ms >= 0 && sv_time_ms <= 20);
+                } else if ((state | GnssMeasurement.STATE_BDS_D2_BIT_SYNC)
+                        == GnssMeasurement.STATE_BDS_D2_BIT_SYNC) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_BDS_D2_BIT_SYNC",
+                                    "GnssStatus.CONSTELLATION_BEIDOU"),
+                            timeInNs,
+                            "0ms >= X <= 2ms",
+                            String.valueOf(sv_time_ms),
+                            sv_time_ms >= 0 && sv_time_ms <= 2);
+                } else if ((state | GnssMeasurement.STATE_CODE_LOCK)
+                        == GnssMeasurement.STATE_CODE_LOCK) {
+                    softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                                    "GNSS_MEASUREMENT_STATE_CODE_LOCK",
+                                    "GnssStatus.CONSTELLATION_BEIDOU"),
+                            timeInNs,
+                            "0ms >= X <= 1ms",
+                            String.valueOf(sv_time_ms),
+                            sv_time_ms >= 0 && sv_time_ms <= 1);
+                }
+                break;
+        }
+    }
+
+    private static String getReceivedSvTimeNsLogMessage(String constellationType, String state) {
+        return "received_sv_time_ns: Received SV Time-of-Week in ns. Constellation type = "
+                + constellationType + ". State = " + state;
+    }
+
+    /**
+     * Verify sv times are in expected range for given constellation type.
+     * This is common check for CONSTELLATION_GPS & CONSTELLATION_QZSS.
+     *
+     * @param measurement GnssMeasurement
+     * @param softAssert  custom SoftAssert
+     * @param timeInNs    event time in ns
+     * @param state       GnssMeasurement State
+     * @param constellationType Gnss Constellation type
+     */
+    private static void verifyGpsQzssSvTimes(GnssMeasurement measurement,
+        SoftAssert softAssert, long timeInNs, int state, String constellationType) {
+
+        long received_sv_time_ns = measurement.getReceivedSvTimeNanos();
+        double sv_time_ms = TimeUnit.NANOSECONDS.toMillis(received_sv_time_ns);
+        double sv_time_sec = TimeUnit.NANOSECONDS.toSeconds(received_sv_time_ns);
+        double sv_time_days = TimeUnit.NANOSECONDS.toDays(received_sv_time_ns);
+
+        if ((state | GnssMeasurement.STATE_TOW_DECODED)
+                == GnssMeasurement.STATE_TOW_DECODED) {
+            softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                            "GNSS_MEASUREMENT_STATE_TOW_DECODED",
+                            constellationType),
+                    timeInNs,
+                    "0 >= X <= 7 days",
+                    String.valueOf(sv_time_days),
+                    sv_time_days >= 0 && sv_time_days <= 7);
+        } else if ((state | GnssMeasurement.STATE_SUBFRAME_SYNC)
+                == GnssMeasurement.STATE_SUBFRAME_SYNC) {
+            softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                            "GNSS_MEASUREMENT_STATE_SUBFRAME_SYNC",
+                            constellationType),
+                    timeInNs,
+                    "0s >= X <= 6s",
+                    String.valueOf(sv_time_sec),
+                    sv_time_sec >= 0 && sv_time_sec <= 6);
+        } else if ((state | GnssMeasurement.STATE_BIT_SYNC)
+                == GnssMeasurement.STATE_BIT_SYNC) {
+            softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                            "GNSS_MEASUREMENT_STATE_BIT_SYNC",
+                            constellationType),
+                    timeInNs,
+                    "0ms >= X <= 20ms",
+                    String.valueOf(sv_time_ms),
+                    sv_time_ms >= 0 && sv_time_ms <= 20);
+
+        } else if ((state | GnssMeasurement.STATE_CODE_LOCK)
+                == GnssMeasurement.STATE_CODE_LOCK) {
+            softAssert.assertTrue(getReceivedSvTimeNsLogMessage(
+                            "GNSS_MEASUREMENT_STATE_CODE_LOCK",
+                            constellationType),
+                    timeInNs,
+                    "0ms >= X <= 1ms",
+                    String.valueOf(sv_time_ms),
+                    sv_time_ms >= 0 && sv_time_ms <= 1);
+        }
+    }
+
+    /**
      * Assert all mandatory fields in Gnss Navigation Message are in expected range.
      * See mandatory fields in {@code gps.h}.
      *
@@ -208,17 +587,17 @@
         for (GnssNavigationMessageEvent event : events) {
             GnssNavigationMessage message = event.getNavigationMessage();
             int type = message.getType();
-            softAssert.assertTrue("Gps Navigation Message Type: expected = 0 or [0x0101,0x0104], actual = " +
-                            type,
-                    type == 0 || type >= 0x0101 && type <= 0x0104);
+            softAssert.assertTrue("Gnss Navigation Message Type:expected [0x0101 - 0x0104]," +
+                            " actual = " + type,
+                    type >= 0x0101 && type <= 0x0104);
 
             // if message type == TYPE_L1CA, verify PRN & Data Size.
             int messageType = message.getType();
             if (messageType == GnssNavigationMessage.TYPE_GPS_L1CA) {
-                int prn = message.getSvid();
-                softAssert.assertTrue("Pseudo-random number: expected = [1, 32], actual = " +
-                                prn,
-                        prn >= 1 && prn <= 32);
+                int svid = message.getSvid();
+                softAssert.assertTrue("Space Vehicle ID : expected = [1, 32], actual = " +
+                                svid,
+                        svid >= 1 && svid <= 32);
                 int dataSize = message.getData().length;
                 softAssert.assertTrue("Data size: expected = 40, actual = " + dataSize,
                         dataSize == 40);
diff --git a/tests/tests/media/res/raw/voice12_48k_128kbps_15s_ac3.raw b/tests/tests/media/res/raw/voice12_48k_128kbps_15s_ac3.raw
new file mode 100644
index 0000000..e8b46af
--- /dev/null
+++ b/tests/tests/media/res/raw/voice12_48k_128kbps_15s_ac3.raw
Binary files differ
diff --git a/tests/tests/media/res/raw/voice12_48k_128kbps_15s_ac3_readme.txt b/tests/tests/media/res/raw/voice12_48k_128kbps_15s_ac3_readme.txt
new file mode 100644
index 0000000..3073d48
--- /dev/null
+++ b/tests/tests/media/res/raw/voice12_48k_128kbps_15s_ac3_readme.txt
@@ -0,0 +1,7 @@
+file=voice12_48k_128kbps_15s.raw
+author=Phil Burk
+copyright=2016 Google Inc
+license=Apache Open Source V2
+channels=2
+encoding=AC3
+rate=48000
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackSurroundTest.java b/tests/tests/media/src/android/media/cts/AudioTrackSurroundTest.java
new file mode 100644
index 0000000..2ab030a
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/AudioTrackSurroundTest.java
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.cts;
+
+import android.annotation.RawRes;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.cts.util.CtsAndroidTestCase;
+import android.media.AudioAttributes;
+import android.media.AudioDeviceInfo;
+import android.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTimestamp;
+import android.media.AudioTrack;
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Random;
+
+// Test the Java AudioTrack surround sound and HDMI passthrough.
+// Most tests involve creating a track with a given format and then playing
+// a few seconds of audio. The playback is verified by measuring the output
+// sample rate based on the AudioTimestamps.
+
+public class AudioTrackSurroundTest extends CtsAndroidTestCase {
+    private static final String TAG = "AudioTrackSurroundTest";
+
+    private static final double MAX_RATE_TOLERANCE_HZ = 100.0;
+    private static final double MAX_INSTANTANEOUS_RATE_TOLERANCE_HZ = 5000.0;
+    private static final boolean LOG_TIMESTAMPS = false; // set true for debugging
+
+    // Set this true to prefer the device that supports the particular encoding.
+    // But note that as of 3/25/2016, a bug causes Direct tracks to fail.
+    // So only set true when debugging that problem.
+    private static final boolean USE_PREFERRED_DEVICE = false;
+
+    private final static long NANOS_PER_MILLISECOND = 1000000L;
+    private final static int MILLIS_PER_SECOND = 1000;
+    private final static long NANOS_PER_SECOND = NANOS_PER_MILLISECOND * MILLIS_PER_SECOND;
+
+    private final static int RES_AC3_VOICE_48000 = R.raw.voice12_48k_128kbps_15s_ac3;
+
+    // Devices that support various encodings.
+    private static boolean mDeviceScanComplete = false;
+    private static AudioDeviceInfo mInfoPCM16 = null;
+    private static AudioDeviceInfo mInfoAC3 = null;
+    private static AudioDeviceInfo mInfoE_AC3 = null;
+    private static AudioDeviceInfo mInfoDTS = null;
+    private static AudioDeviceInfo mInfoDTS_HD = null;
+    private static AudioDeviceInfo mInfoIEC61937 = null;
+
+    private static void log(String testName, String message) {
+        Log.i(TAG, "[" + testName + "] " + message);
+    }
+
+    private static void logw(String testName, String message) {
+        Log.w(TAG, "[" + testName + "] " + message);
+    }
+
+    private static void loge(String testName, String message) {
+        Log.e(TAG, "[" + testName + "] " + message);
+    }
+
+    // This is a special method that is called automatically before each test.
+    @Override
+    protected void setUp() throws Exception {
+        // Note that I tried to only scan for encodings once but the static
+        // data did not persist properly. That may be a bug.
+        // For now, just scan before every test.
+        scanDevicesForEncodings();
+    }
+
+    private void scanDevicesForEncodings() throws Exception {
+        // Scan devices to see which encodings are supported.
+        AudioManager audioManager = (AudioManager) getContext()
+                .getSystemService(Context.AUDIO_SERVICE);
+        AudioDeviceInfo[] infos = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
+        for (AudioDeviceInfo info : infos) {
+            log("scanDevicesForEncodings", "scanning devices, info = " + info
+                    + ", id = " + info.getId() + "---------------");
+            if (info.isSink()) {
+                for (int encoding : info.getEncodings()) {
+                    switch (encoding) {
+                        case AudioFormat.ENCODING_PCM_16BIT:
+                            mInfoPCM16 = info;
+                            log(TAG, "mInfoPCM16 set to " + info);
+                            break;
+                        case AudioFormat.ENCODING_AC3:
+                            mInfoAC3 = info;
+                            log(TAG, "mInfoAC3 set to " + info);
+                            break;
+                        case AudioFormat.ENCODING_E_AC3:
+                            mInfoE_AC3 = info;
+                            log(TAG, "mInfoE_AC3 set to " + info);
+                            break;
+                        case AudioFormat.ENCODING_DTS:
+                            mInfoDTS = info;
+                            log(TAG, "mInfoDTS set to " + info);
+                            break;
+                        case AudioFormat.ENCODING_DTS_HD:
+                            mInfoDTS_HD = info;
+                            log(TAG, "mInfoDTS_HD set to " + info);
+                            break;
+                        case AudioFormat.ENCODING_IEC61937:
+                            mInfoIEC61937 = info;
+                            log(TAG, "mInfoIEC61937 set to " + info);
+                            break;
+                        default:
+                            // This is OK. It is just an encoding that we don't care about.
+                            break;
+                    }
+                }
+            }
+        }
+    }
+
+    // Load a resource into a byte[]
+    private byte[] loadRawResourceBytes(@RawRes int id) throws Exception {
+        AssetFileDescriptor masterFd = getContext().getResources().openRawResourceFd(id);
+        long masterLength = masterFd.getLength();
+        byte[] masterBuffer = new byte[(int) masterLength];
+        InputStream is = masterFd.createInputStream();
+        BufferedInputStream bis = new BufferedInputStream(is);
+        int result = bis.read(masterBuffer);
+        bis.close();
+        masterFd.close();
+        return masterBuffer;
+    }
+
+    // Load a resource into a short[]
+    private short[] loadRawResourceShorts(@RawRes int id) throws Exception {
+        AssetFileDescriptor masterFd = getContext().getResources().openRawResourceFd(id);
+        long masterLength = masterFd.getLength();
+        short[] masterBuffer = new short[(int) (masterLength / 2)];
+        InputStream is = masterFd.createInputStream();
+        BufferedInputStream bis = new BufferedInputStream(is);
+        for (int i = 0; i < masterBuffer.length; i++) {
+            int lo = bis.read(); // assume Little Endian
+            int hi = bis.read();
+            masterBuffer[i] = (short) (hi * 256 + lo);
+        }
+        bis.close();
+        masterFd.close();
+        return masterBuffer;
+    }
+
+    public void testLoadSineSweep() throws Exception {
+        final String TEST_NAME = "testLoadSineSweep";
+        short[] shortData = loadRawResourceShorts(R.raw.sinesweepraw);
+        assertTrue(TEST_NAME + ": load sinesweepraw as shorts", shortData.length > 100);
+        byte[] byteData = loadRawResourceBytes(R.raw.sinesweepraw);
+        assertTrue(TEST_NAME + ": load sinesweepraw as bytes", byteData.length > shortData.length);
+    }
+
+    private static AudioTrack createAudioTrack(int sampleRate, int encoding, int channelConfig) {
+        final String TEST_NAME = "createAudioTrack";
+        int minBufferSize = AudioTrack.getMinBufferSize(
+                sampleRate, channelConfig,
+                encoding);
+        assertTrue(TEST_NAME + ": getMinBufferSize", minBufferSize > 0);
+        int bufferSize = minBufferSize * 3; // plenty big
+        AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,
+                sampleRate, channelConfig,
+                encoding, bufferSize,
+                AudioTrack.MODE_STREAM);
+        return track;
+    }
+
+    static class TimestampAnalyzer {
+        ArrayList<AudioTimestamp> mTimestamps = new ArrayList<AudioTimestamp>();
+        AudioTimestamp mPreviousTimestamp = null;
+
+        static String timestampToString(AudioTimestamp timestamp) {
+            if (timestamp == null)
+                return "null";
+            return "(pos = " + timestamp.framePosition + ", nanos = " + timestamp.nanoTime + ")";
+        }
+
+        // Add timestamp if unique and valid.
+        void addTimestamp(AudioTrack track) {
+            AudioTimestamp timestamp = new AudioTimestamp();
+            boolean gotTimestamp = track.getTimestamp(timestamp);
+            if (gotTimestamp) {
+                // Only save timestamps after the data is flowing.
+                if (mPreviousTimestamp != null) {
+                    if ((timestamp.framePosition > 0)
+                            && (timestamp.nanoTime != mPreviousTimestamp.nanoTime)) {
+                        mTimestamps.add(timestamp);
+                    }
+                }
+                mPreviousTimestamp = timestamp;
+            }
+        }
+
+        // Use collected timestamps to estimate a sample rate.
+        double estimateSampleRate() {
+            assertTrue("expect many timestamps, got " + mTimestamps.size(),
+                    mTimestamps.size() > 10);
+            // Use first and last timestamp to get the most accurate rate.
+            AudioTimestamp first = mTimestamps.get(0);
+            AudioTimestamp last = mTimestamps.get(mTimestamps.size() - 1);
+            double measuredRate = calculateSampleRate(first, last);
+
+            AudioTimestamp previous = null;
+            // Make sure the timestamps are smooth and don't go retrograde.
+            for (AudioTimestamp timestamp : mTimestamps) {
+                if (previous != null) {
+                    double instantaneousRate = calculateSampleRate(previous, timestamp);
+                    assertEquals("instantaneous sample rate should match long term rate",
+                            measuredRate, instantaneousRate, MAX_INSTANTANEOUS_RATE_TOLERANCE_HZ);
+                    assertTrue("framePosition should be monotonic",
+                            timestamp.framePosition > previous.framePosition);
+                    assertTrue("nanoTime should be monotonic",
+                            timestamp.nanoTime > previous.nanoTime);
+                }
+                previous = timestamp;
+            }
+            return measuredRate;
+        }
+
+        /**
+         * @param timestamp1
+         * @param timestamp2
+         */
+        private double calculateSampleRate(AudioTimestamp timestamp1, AudioTimestamp timestamp2) {
+            long elapsedFrames = timestamp2.framePosition - timestamp1.framePosition;
+            long elapsedNanos = timestamp2.nanoTime - timestamp1.nanoTime;
+            double measuredRate = elapsedFrames * (double) NANOS_PER_SECOND / elapsedNanos;
+            if (LOG_TIMESTAMPS) {
+                Log.i(TAG, "calculateSampleRate(), elapsedFrames =, " + elapsedFrames
+                        + ", measuredRate =, "
+                        + (int) measuredRate);
+            }
+            return measuredRate;
+        }
+    }
+
+    // Class for looping a recording for several seconds and measuring the sample rate.
+    // This is not static because it needs to call getContext().
+    abstract class SamplePlayerBase {
+        private final int mSampleRate;
+        private final int mEncoding;
+        private final int mChannelConfig;
+        private int mBlockSize = 512;
+        protected int mOffset = 0;
+        protected AudioTrack mTrack;
+        private final TimestampAnalyzer mTimestampAnalyzer = new TimestampAnalyzer();
+
+        SamplePlayerBase(int sampleRate, int encoding, int channelConfig) {
+            mSampleRate = sampleRate;
+            mEncoding = encoding;
+            mChannelConfig = channelConfig;
+        }
+
+        // Use abstract write to handle byte[] or short[] data.
+        protected abstract int writeBlock(int numSamples);
+
+        private int primeBuffer() {
+            // Will not block when track is stopped.
+            return writeBlock(Integer.MAX_VALUE);
+        }
+
+        /**
+         * Use a device that we know supports the current encoding.
+         */
+        private void usePreferredDevice() {
+            AudioDeviceInfo info = null;
+            switch (mEncoding) {
+                case AudioFormat.ENCODING_PCM_16BIT:
+                    info = mInfoPCM16;
+                    break;
+                case AudioFormat.ENCODING_AC3:
+                    info = mInfoAC3;
+                    break;
+                case AudioFormat.ENCODING_E_AC3:
+                    info = mInfoE_AC3;
+                    break;
+                case AudioFormat.ENCODING_DTS:
+                    info = mInfoDTS;
+                    break;
+                case AudioFormat.ENCODING_DTS_HD:
+                    info = mInfoDTS_HD;
+                    break;
+                case AudioFormat.ENCODING_IEC61937:
+                    info = mInfoIEC61937;
+                    break;
+                default:
+                    break;
+            }
+
+            if (info != null) {
+                log(TAG, "track.setPreferredDevice(" + info + ")");
+                mTrack.setPreferredDevice(info);
+            }
+        }
+
+        public void playAndMeasureRate() throws Exception {
+            final String TEST_NAME = "playAndMeasureRate";
+            final long TEST_DURATION_MILLIS = 5000; // just long enough to measure the rate
+            log(TEST_NAME, String.format("test using rate = %d, encoding = 0x%08x",
+                    mSampleRate, mEncoding));
+            // Create a track and prime it.
+            mTrack = createAudioTrack(mSampleRate, mEncoding, mChannelConfig);
+            try {
+                assertEquals(TEST_NAME + ": track created", AudioTrack.STATE_INITIALIZED,
+                        mTrack.getState());
+
+                if (USE_PREFERRED_DEVICE) {
+                    usePreferredDevice();
+                }
+
+                int bytesWritten = 0;
+                mOffset = primeBuffer(); // prime the buffer
+                assertTrue(TEST_NAME + ": priming offset = " + mOffset, mOffset > 0);
+                bytesWritten += mOffset;
+
+                // Play for a while.
+                mTrack.play();
+                long elapsedMillis = 0;
+                long startTime = System.currentTimeMillis();
+                while (elapsedMillis < TEST_DURATION_MILLIS) {
+                    writeBlock(mBlockSize);
+                    elapsedMillis = System.currentTimeMillis() - startTime;
+                    mTimestampAnalyzer.addTimestamp(mTrack);
+                }
+
+                // Did we underrun? Allow 0 or 1 because there is sometimes
+                // an underrun on startup.
+                int underrunCount1 = mTrack.getUnderrunCount();
+                assertTrue(TEST_NAME + ": too many underruns, got underrunCount1",
+                        underrunCount1 < 2);
+
+                // Estimate the sample rate and compare it with expected.
+                double estimatedRate = mTimestampAnalyzer.estimateSampleRate();
+                assertEquals(TEST_NAME + ": measured sample rate",
+                        mSampleRate, estimatedRate, MAX_RATE_TOLERANCE_HZ);
+            } finally {
+                mTrack.release();
+            }
+        }
+    }
+
+    // Create player for short[]
+    class SamplePlayerShorts extends SamplePlayerBase {
+        private final short[] mData;
+
+        SamplePlayerShorts(int sampleRate, int encoding, int channelConfig) {
+            super(sampleRate, encoding, channelConfig);
+            mData = new short[64 * 1024];
+            // Fill with noise. We should not hear the noise for IEC61937.
+            int amplitude = 8000;
+            Random random = new Random();
+            for (int i = 0; i < mData.length; i++) {
+                mData[i] = (short)(random.nextInt(amplitude) - (amplitude / 2));
+            }
+        }
+
+        SamplePlayerShorts(int sampleRate, int encoding, int channelConfig, @RawRes int resourceId)
+                throws Exception {
+            super(sampleRate, encoding, channelConfig);
+            mData = loadRawResourceShorts(resourceId);
+            assertTrue("SamplePlayerShorts: load resource file as shorts", mData.length > 0);
+        }
+
+        @Override
+        protected int writeBlock(int numShorts) {
+            int result = 0;
+            int shortsToWrite = numShorts;
+            int shortsLeft = mData.length - mOffset;
+            if (shortsToWrite > shortsLeft) {
+                shortsToWrite = shortsLeft;
+            }
+            if (shortsToWrite > 0) {
+                result = mTrack.write(mData, mOffset, shortsToWrite);
+                mOffset += result;
+            } else {
+                mOffset = 0; // rewind
+            }
+            return result;
+        }
+    }
+
+    // Create player for byte[]
+    class SamplePlayerBytes extends SamplePlayerBase {
+        private final byte[] mData;
+
+        SamplePlayerBytes(int sampleRate, int encoding, int channelConfig) {
+            super(sampleRate, encoding, channelConfig);
+            mData = new byte[128 * 1024];
+        }
+
+        SamplePlayerBytes(int sampleRate, int encoding, int channelConfig, @RawRes int resourceId)
+                throws Exception {
+            super(sampleRate, encoding, channelConfig);
+            mData = loadRawResourceBytes(resourceId);
+            assertTrue("SamplePlayerBytes: load resource file as bytes", mData.length > 0);
+        }
+
+        @Override
+        protected int writeBlock(int numBytes) {
+            int result = 0;
+            int bytesToWrite = numBytes;
+            int bytesLeft = mData.length - mOffset;
+            if (bytesToWrite > bytesLeft) {
+                bytesToWrite = bytesLeft;
+            }
+            if (bytesToWrite > 0) {
+                result = mTrack.write(mData, mOffset, bytesToWrite);
+                mOffset += result;
+            } else {
+                mOffset = 0; // rewind
+            }
+            return result;
+        }
+    }
+
+    public void testPlayAC3Bytes() throws Exception {
+        if (mInfoAC3 != null) {
+            SamplePlayerBytes player = new SamplePlayerBytes(
+                    48000, AudioFormat.ENCODING_AC3, AudioFormat.CHANNEL_OUT_STEREO,
+                    RES_AC3_VOICE_48000);
+            player.playAndMeasureRate();
+        }
+    }
+
+    public void testPlayAC3Shorts() throws Exception {
+        if (mInfoAC3 != null) {
+            SamplePlayerShorts player = new SamplePlayerShorts(
+                    48000, AudioFormat.ENCODING_AC3, AudioFormat.CHANNEL_OUT_STEREO,
+                    RES_AC3_VOICE_48000);
+            player.playAndMeasureRate();
+        }
+    }
+
+    // Note that for testing IEC61937, the Audio framework does not look at the
+    // wrapped data. It just passes it through over HDMI. See we can just use
+    // zeros instead of real data.
+    public void testPlayIEC61937_32000() throws Exception {
+        if (mInfoIEC61937 != null) {
+            SamplePlayerShorts player = new SamplePlayerShorts(
+                    32000, AudioFormat.ENCODING_IEC61937, AudioFormat.CHANNEL_OUT_STEREO);
+            player.playAndMeasureRate();
+        }
+    }
+
+    public void testPlayIEC61937_44100() throws Exception {
+        if (mInfoIEC61937 != null) {
+            SamplePlayerShorts player = new SamplePlayerShorts(
+                    44100, AudioFormat.ENCODING_IEC61937, AudioFormat.CHANNEL_OUT_STEREO);
+            player.playAndMeasureRate();
+        }
+    }
+
+    public void testPlayIEC61937_48000() throws Exception {
+        if (mInfoIEC61937 != null) {
+            SamplePlayerShorts player = new SamplePlayerShorts(
+                    48000, AudioFormat.ENCODING_IEC61937, AudioFormat.CHANNEL_OUT_STEREO);
+            player.playAndMeasureRate();
+        }
+    }
+
+    public void testIEC61937_Errors() throws Exception {
+        if (mInfoIEC61937 != null) {
+            final String TEST_NAME = "testIEC61937_Errors";
+            try {
+                AudioTrack track = createAudioTrack(48000, AudioFormat.ENCODING_IEC61937,
+                        AudioFormat.CHANNEL_OUT_MONO);
+                assertTrue(TEST_NAME + ": IEC61937 track creation should fail for mono", false);
+            } catch (IllegalArgumentException e) {
+                // This is expected behavior.
+            }
+
+            try {
+                AudioTrack track = createAudioTrack(48000, AudioFormat.ENCODING_IEC61937,
+                        AudioFormat.CHANNEL_OUT_5POINT1);
+                assertTrue(TEST_NAME + ": IEC61937 track creation should fail for 5.1", false);
+            } catch (IllegalArgumentException e) {
+                // This is expected behavior.
+            }
+        }
+    }
+
+    public void testPlaySineSweepShorts() throws Exception {
+        SamplePlayerShorts player = new SamplePlayerShorts(
+                44100, AudioFormat.ENCODING_PCM_16BIT, AudioFormat.CHANNEL_OUT_STEREO,
+                R.raw.sinesweepraw);
+        player.playAndMeasureRate();
+    }
+
+    public void testPlaySineSweepBytes() throws Exception {
+        SamplePlayerBytes player = new SamplePlayerBytes(
+                44100, AudioFormat.ENCODING_PCM_16BIT, AudioFormat.CHANNEL_OUT_STEREO,
+                R.raw.sinesweepraw);
+        player.playAndMeasureRate();
+    }
+
+    public void testPlaySineSweepBytes48000() throws Exception {
+        SamplePlayerBytes player = new SamplePlayerBytes(
+                48000, AudioFormat.ENCODING_PCM_16BIT, AudioFormat.CHANNEL_OUT_STEREO,
+                R.raw.sinesweepraw);
+        player.playAndMeasureRate();
+    }
+
+    public void testPlaySineSweepShortsMono() throws Exception {
+        SamplePlayerShorts player = new SamplePlayerShorts(44100, AudioFormat.ENCODING_PCM_16BIT,
+                AudioFormat.CHANNEL_OUT_MONO,
+                R.raw.sinesweepraw);
+        player.playAndMeasureRate();
+    }
+
+    public void testPlaySineSweepBytesMono()
+            throws Exception {
+        SamplePlayerBytes player = new SamplePlayerBytes(44100,
+                AudioFormat.ENCODING_PCM_16BIT, AudioFormat.CHANNEL_OUT_MONO, R.raw.sinesweepraw);
+        player.playAndMeasureRate();
+    }
+
+}
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackTest.java b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
index 169434c..d81c11c 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrackTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
@@ -1961,11 +1961,10 @@
                 .setEncoding(encoding)
                 .setSampleRate(sampleRate)
                 .build();
+        // not specifying the buffer size in the builder should get us the minimum buffer size.
         AudioTrack track = new AudioTrack.Builder()
                 .setAudioAttributes(attributes)
                 .setAudioFormat(format)
-                .setBufferSizeInBytes(AudioTrack.getMinBufferSize(
-                        sampleRate, channelMask, encoding))
                 .setTransferMode(transferMode)
                 .build();
         assertEquals(AudioTrack.STATE_INITIALIZED, track.getState());
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index d6709dd..e3c258b 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -23,6 +23,8 @@
 import android.media.MediaCodec;
 import android.media.MediaCodec.BufferInfo;
 import android.media.MediaCodec.CodecException;
+import android.media.MediaCodec.CryptoInfo;
+import android.media.MediaCodec.CryptoInfo.Pattern;
 import android.media.MediaCodecInfo;
 import android.media.MediaCodecList;
 import android.media.MediaExtractor;
@@ -1245,6 +1247,25 @@
         public int mBitRate;
     };
 
+    public void testCryptoInfoPattern() {
+        CryptoInfo info = new CryptoInfo();
+        Pattern pattern = new Pattern(1 /*blocksToEncrypt*/, 2 /*blocksToSkip*/);
+        if (pattern.getEncryptBlocks() != 1) {
+            fail("Incorrect number of encrypt blocks in pattern");
+        }
+        if (pattern.getSkipBlocks() != 2) {
+            fail("Incorrect number of skip blocks in pattern");
+        }
+        pattern.set(3 /*blocksToEncrypt*/, 4 /*blocksToSkip*/);
+        if (pattern.getEncryptBlocks() != 3) {
+            fail("Incorrect number of encrypt blocks in pattern");
+        }
+        if (pattern.getSkipBlocks() != 4) {
+            fail("Incorrect number of skip blocks in pattern");
+        }
+        info.setPattern(pattern);
+    }
+
     private static CodecInfo getAvcSupportedFormatInfo() {
         MediaCodecInfo mediaCodecInfo = selectCodec(MIME_TYPE);
         CodecCapabilities cap = mediaCodecInfo.getCapabilitiesForType(MIME_TYPE);
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 e132cce..2e2e75b 100644
--- a/tests/tests/net/src/android/net/wifi/cts/NsdManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/NsdManagerTest.java
@@ -24,6 +24,7 @@
 
 import java.io.IOException;
 import java.net.ServerSocket;
+import java.util.Arrays;
 import java.util.Random;
 import java.util.List;
 import java.util.ArrayList;
@@ -41,6 +42,7 @@
     NsdManager.RegistrationListener mRegistrationListener;
     NsdManager.DiscoveryListener mDiscoveryListener;
     NsdManager.ResolveListener mResolveListener;
+    private NsdServiceInfo mResolvedService;
 
     public NsdManagerTest() {
         initRegistrationListener();
@@ -119,6 +121,7 @@
 
             @Override
             public void onServiceResolved(NsdServiceInfo serviceInfo) {
+                mResolvedService = serviceInfo;
                 setEvent("onServiceResolved", serviceInfo);
             }
         };
@@ -254,14 +257,87 @@
         if (DBG) Log.d(TAG, "Tear down test ...");
     }
 
-    public void runTest() throws Exception {
+    public void testNDSManager() throws Exception {
+        EventData lastEvent = null;
+
+        if (DBG) Log.d(TAG, "Starting test ...");
+
         NsdServiceInfo si = new NsdServiceInfo();
         si.setServiceType(SERVICE_TYPE);
         si.setServiceName(mServiceName);
 
-        EventData lastEvent = null;
+        byte testByteArray[] = new byte[] {-128, 127, 2, 1, 0, 1, 2};
+        String String256 = "1_________2_________3_________4_________5_________6_________" +
+                 "7_________8_________9_________10________11________12________13________" +
+                 "14________15________16________17________18________19________20________" +
+                 "21________22________23________24________25________123456";
 
-        if (DBG) Log.d(TAG, "Starting test ...");
+        // Illegal attributes
+        try {
+            si.setAttribute(null, (String) null);
+            fail("Could set null key");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            si.setAttribute("", (String) null);
+            fail("Could set empty key");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            si.setAttribute(String256, (String) null);
+            fail("Could set key with 255 characters");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            si.setAttribute("key", String256.substring(3));
+            fail("Could set key+value combination with more than 255 characters");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            si.setAttribute("key", String256.substring(4));
+            fail("Could set key+value combination with 255 characters");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            si.setAttribute(new String(new byte[]{0x19}), (String) null);
+            fail("Could set key with invalid character");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            si.setAttribute("=", (String) null);
+            fail("Could set key with invalid character");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        try {
+            si.setAttribute(new String(new byte[]{0x7F}), (String) null);
+            fail("Could set key with invalid character");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+
+        // Allowed attributes
+        si.setAttribute("booleanAttr", (String) null);
+        si.setAttribute("keyValueAttr", "value");
+        si.setAttribute("keyEqualsAttr", "=");
+        si.setAttribute(" whiteSpaceKeyValueAttr ", " value ");
+        si.setAttribute("binaryDataAttr", testByteArray);
+        si.setAttribute("nullBinaryDataAttr", (byte[]) null);
+        si.setAttribute("emptyBinaryDataAttr", new byte[]{});
+        si.setAttribute("longkey", String256.substring(9));
 
         ServerSocket socket;
         int localPort;
@@ -347,6 +423,25 @@
         mNsdManager.resolveService(si, mResolveListener);
         lastEvent = waitForCallback("onServiceResolved");                   // id = 4
 
+        assertNotNull(mResolvedService);
+
+        // Check Txt attributes
+        assertEquals(8, mResolvedService.getAttributes().size());
+        assertTrue(mResolvedService.getAttributes().containsKey("booleanAttr"));
+        assertNull(mResolvedService.getAttributes().get("booleanAttr"));
+        assertEquals("value", new String(mResolvedService.getAttributes().get("keyValueAttr")));
+        assertEquals("=", new String(mResolvedService.getAttributes().get("keyEqualsAttr")));
+        assertEquals(" value ", new String(mResolvedService.getAttributes()
+                .get(" whiteSpaceKeyValueAttr ")));
+        assertEquals(String256.substring(9), new String(mResolvedService.getAttributes()
+                .get("longkey")));
+        assertTrue(Arrays.equals(testByteArray,
+                mResolvedService.getAttributes().get("binaryDataAttr")));
+        assertTrue(mResolvedService.getAttributes().containsKey("nullBinaryDataAttr"));
+        assertNull(mResolvedService.getAttributes().get("nullBinaryDataAttr"));
+        assertTrue(mResolvedService.getAttributes().containsKey("emptyBinaryDataAttr"));
+        assertNull(mResolvedService.getAttributes().get("emptyBinaryDataAttr"));
+
         assertTrue(lastEvent != null);
         assertTrue(lastEvent.mSucceeded);
 
@@ -394,7 +489,41 @@
         registeredName = lastEvent.mInfo.getServiceName();
 
         // Expect a record to be discovered
-        lastEvent = waitForCallback("onServiceFound");                      // id = 8
+        // Expect a service record to be discovered (and filter the ones
+        // that are unrelated to this test)
+        found = false;
+        for (int i = 0; i < 32; i++) {
+
+            lastEvent = waitForCallback("onServiceFound");                  // id = 8
+            if (lastEvent == null) {
+                // no more onServiceFound events are being reported!
+                break;
+            }
+
+            assertTrue(lastEvent.mSucceeded);
+
+            if (DBG) Log.d(TAG, "id = " + String.valueOf(mWaitId) + ": ServiceName = " +
+                    lastEvent.mInfo.getServiceName());
+
+            if (lastEvent.mInfo.getServiceName().equals(registeredName)) {
+                // Save it, as it will get overwritten with new serviceFound events
+                si = lastEvent.mInfo;
+                found = true;
+            }
+
+            // Remove this event from the event cache, so it won't be found by subsequent
+            // calls to waitForCallback
+            synchronized (mEventCache) {
+                mEventCache.remove(lastEvent);
+            }
+        }
+
+        assertTrue(found);
+
+        // Resolve the service
+        clearEventCache();
+        mNsdManager.resolveService(si, mResolveListener);
+        lastEvent = waitForCallback("onServiceResolved");                   // id = 9
 
         assertTrue(lastEvent != null);
         assertTrue(lastEvent.mSucceeded);
@@ -404,11 +533,16 @@
 
         assertTrue(lastEvent.mInfo.getServiceName().equals(registeredName));
 
+        assertNotNull(mResolvedService);
+
+        // Check that we don't have any TXT records
+        assertEquals(0, mResolvedService.getAttributes().size());
+
         checkForAdditionalEvents();
         clearEventCache();
 
         mNsdManager.stopServiceDiscovery(mDiscoveryListener);
-        lastEvent = waitForCallback("onDiscoveryStopped");                  // id = 9
+        lastEvent = waitForCallback("onDiscoveryStopped");                  // id = 10
         assertTrue(lastEvent != null);
         assertTrue(lastEvent.mSucceeded);
         assertTrue(checkCacheSize(1));
@@ -418,7 +552,7 @@
 
         mNsdManager.unregisterService(mRegistrationListener);
 
-        lastEvent =  waitForCallback("onServiceUnregistered");              // id = 10
+        lastEvent =  waitForCallback("onServiceUnregistered");              // id = 11
         assertTrue(lastEvent != null);
         assertTrue(lastEvent.mSucceeded);
         assertTrue(checkCacheSize(1));
diff --git a/tests/tests/os/AndroidManifest.xml b/tests/tests/os/AndroidManifest.xml
index deb7045..bdb5230 100644
--- a/tests/tests/os/AndroidManifest.xml
+++ b/tests/tests/os/AndroidManifest.xml
@@ -16,7 +16,7 @@
  -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.cts.os">
+    package="android.os.cts">
 
     <permission android:name="android.os.cts.permission.TEST_GRANTED"
         android:protectionLevel="normal"
@@ -132,7 +132,7 @@
     </application>
 
     <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
-                     android:targetPackage="com.android.cts.os"
+                     android:targetPackage="android.os.cts"
                      android:label="CTS tests of android.os">
         <meta-data android:name="listener"
             android:value="com.android.cts.runner.CtsTestRunListener" />
diff --git a/tests/tests/os/AndroidTest.xml b/tests/tests/os/AndroidTest.xml
index 1676c88..fd446c2 100644
--- a/tests/tests/os/AndroidTest.xml
+++ b/tests/tests/os/AndroidTest.xml
@@ -19,7 +19,7 @@
         <option name="test-file-name" value="CtsOsTestCases.apk" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.cts.os" />
+        <option name="package" value="android.os.cts" />
         <option name="runtime-hint" value="3m15s" />
     </test>
 </configuration>
diff --git a/tests/tests/os/res/raw/test1_new.obb b/tests/tests/os/res/raw/test1_new.obb
new file mode 100644
index 0000000..450af90
--- /dev/null
+++ b/tests/tests/os/res/raw/test1_new.obb
Binary files differ
diff --git a/tests/tests/os/res/xml/alias.xml b/tests/tests/os/res/xml/alias.xml
index 1166669..98fb5b2 100644
--- a/tests/tests/os/res/xml/alias.xml
+++ b/tests/tests/os/res/xml/alias.xml
@@ -19,7 +19,7 @@
 
 <alias xmlns:android="http://schemas.android.com/apk/res/android">
     <intent android:action="android.intent.action.MAIN"
-        android:targetPackage="com.android.cts.os"
+        android:targetPackage="android.os.cts"
         android:targetClass="android.os.cts.ChildActivity"
         android:data="http://www.google.com/">
     </intent>
diff --git a/tests/tests/os/src/android/os/cts/ParcelFileDescriptorProcessTest.java b/tests/tests/os/src/android/os/cts/ParcelFileDescriptorProcessTest.java
index 679a35c..a6a6b99 100644
--- a/tests/tests/os/src/android/os/cts/ParcelFileDescriptorProcessTest.java
+++ b/tests/tests/os/src/android/os/cts/ParcelFileDescriptorProcessTest.java
@@ -89,10 +89,10 @@
         // Bring up both remote processes and wire them to each other
         redIntent = new Intent();
         redIntent.setComponent(new ComponentName(
-                "com.android.cts.os", "android.os.cts.ParcelFileDescriptorPeer$Red"));
+                "android.os.cts", "android.os.cts.ParcelFileDescriptorPeer$Red"));
         blueIntent = new Intent();
         blueIntent.setComponent(new ComponentName(
-                "com.android.cts.os", "android.os.cts.ParcelFileDescriptorPeer$Blue"));
+                "android.os.cts", "android.os.cts.ParcelFileDescriptorPeer$Blue"));
         redConn = new PeerConnection();
         blueConn = new PeerConnection();
         context.startService(redIntent);
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 a8e8e64..355ef65 100644
--- a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
+++ b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
@@ -16,7 +16,7 @@
 
 package android.os.storage.cts;
 
-import com.android.cts.os.R;
+import android.os.cts.R;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -47,7 +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 static final String TEST1_NEW_CONTENTS = "1\n";
 
     private StorageManager mStorageManager;
 
@@ -59,16 +59,16 @@
 
     public void testMountAndUnmountObbNormal() throws IOException {
         for (File target : getTargetFiles()) {
-            target = new File(target, "test1.obb");
+            target = new File(target, "test1_new.obb");
             Log.d(TAG, "Testing path " + target);
             doMountAndUnmountObbNormal(target);
         }
     }
 
     private void doMountAndUnmountObbNormal(File outFile) throws IOException {
-        final String canonPath = mountObb(R.raw.test1, outFile, OnObbStateChangeListener.MOUNTED);
+        final String canonPath = mountObb(R.raw.test1_new, outFile, OnObbStateChangeListener.MOUNTED);
 
-        mountObb(R.raw.test1, outFile, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
+        mountObb(R.raw.test1_new, outFile, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
 
         try {
             final String mountPath = checkMountedPath(canonPath);
@@ -77,7 +77,7 @@
 
             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);
+            assertFileContains(testFile, TEST1_NEW_CONTENTS);
         } finally {
             unmountObb(outFile, OnObbStateChangeListener.UNMOUNTED);
         }
@@ -130,8 +130,8 @@
     }
 
     private void doMountAndUnmountTwoObbs(File file1, File file2) throws IOException {
-        ObbObserver oo1 = mountObbWithoutWait(R.raw.test1, file1);
-        ObbObserver oo2 = mountObbWithoutWait(R.raw.test1, file2);
+        ObbObserver oo1 = mountObbWithoutWait(R.raw.test1_new, file1);
+        ObbObserver oo2 = mountObbWithoutWait(R.raw.test1_new, file2);
 
         Log.d(TAG, "Waiting for OBB #1 to complete mount");
         waitForObbActionCompletion(file1, oo1, OnObbStateChangeListener.MOUNTED);
@@ -144,14 +144,14 @@
             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);
+            assertFileContains(testFile1, TEST1_NEW_CONTENTS);
 
             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);
+            assertFileContains(testFile2, TEST1_NEW_CONTENTS);
         } finally {
             unmountObb(file1, OnObbStateChangeListener.UNMOUNTED);
             unmountObb(file2, OnObbStateChangeListener.UNMOUNTED);
@@ -241,11 +241,22 @@
         } catch (NotFoundException e) {
             fail("Failed to load resource with id: " + rawResId);
         }
-        FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
-                | FileUtils.S_IRWXO);
         assertTrue(FileUtils.copyToFile(is, outFile));
-        FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
-                | FileUtils.S_IRWXO);
+        exposeFile(outFile);
+    }
+
+    private File exposeFile(File file) {
+        file.setReadable(true, false);
+        file.setReadable(true, true);
+
+        File dir = file.getParentFile();
+        do {
+            dir.setExecutable(true, false);
+            dir.setExecutable(true, true);
+            dir = dir.getParentFile();
+        } while (dir != null);
+
+        return file;
     }
 
     private String mountObb(final int resource, final File file, int expectedState) {
@@ -297,7 +308,7 @@
     private void unmountObb(final File file, int expectedState) {
         final ObbObserver observer = new ObbObserver();
 
-        assertTrue("unmountObb call on test1.obb should succeed",
+        assertTrue("unmountObb call on test1_new.obb should succeed",
                 mStorageManager.unmountObb(file.getPath(), false, observer));
 
         assertTrue("Unmount should have completed",
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index bc7119c..9024092 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -87,6 +87,7 @@
     <protected-broadcast android:name="android.os.action.DEVICE_IDLE_MODE_CHANGED" />
     <protected-broadcast android:name="android.os.action.POWER_SAVE_WHITELIST_CHANGED" />
     <protected-broadcast android:name="android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED" />
+    <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED_INTERNAL" />
 
     <protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" />
 
@@ -265,6 +266,7 @@
     <protected-broadcast android:name="com.android.server.WifiManager.action.START_SCAN" />
     <protected-broadcast android:name="com.android.server.WifiManager.action.START_PNO" />
     <protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
+    <protected-broadcast android:name="com.android.server.WifiManager.action.DEVICE_IDLE" />
     <protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED" />
     <protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED" />
     <protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
@@ -374,7 +376,10 @@
     <protected-broadcast android:name="android.app.action.ACTION_PASSWORD_FAILED" />
     <protected-broadcast android:name="android.app.action.ACTION_PASSWORD_SUCCEEDED" />
     <protected-broadcast android:name="com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION" />
+
     <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_ADDED" />
+    <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNLOCKED" />
+    <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_REMOVED" />
 
     <protected-broadcast android:name="android.bluetooth.adapter.action.BLE_STATE_CHANGED" />
     <protected-broadcast android:name="android.content.jobscheduler.JOB_DELAY_EXPIRED" />
@@ -412,6 +417,7 @@
     <protected-broadcast android:name="android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED" />
     <protected-broadcast android:name="android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED" />
     <protected-broadcast android:name="android.os.storage.action.VOLUME_STATE_CHANGED" />
+    <protected-broadcast android:name="android.os.storage.action.DISK_SCANNED" />
     <protected-broadcast android:name="com.android.server.action.UPDATE_TWILIGHT_STATE" />
     <protected-broadcast android:name="com.android.server.device_idle.STEP_IDLE_STATE" />
     <protected-broadcast android:name="com.android.server.device_idle.STEP_LIGHT_IDLE_STATE" />
@@ -432,7 +438,6 @@
     <protected-broadcast android:name="android.intent.action.DYNAMIC_SENSOR_CHANGED" />
 
     <protected-broadcast android:name="android.intent.action.ACTION_RADIO_OFF" />
-    <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNLOCKED" />
 
     <protected-broadcast android:name="android.accounts.LOGIN_ACCOUNTS_CHANGED" />
     <protected-broadcast android:name="com.android.sync.SYNC_CONN_STATUS_CHANGED" />
@@ -450,6 +455,13 @@
 
     <protected-broadcast android:name="android.intent.action.TWILIGHT_CHANGED" />
 
+    <protected-broadcast android:name="com.android.server.fingerprint.ACTION_LOCKOUT_RESET" />
+    <protected-broadcast android:name="android.net.wifi.PASSPOINT_ICON_RECEIVED" />
+    <protected-broadcast android:name="com.android.server.notification.CountdownConditionProvider" />
+
+    <!-- @hide UCE service Notification -->
+    <protected-broadcast android:name="com.android.ims.internal.uce.UCE_SERVICE_UP" />
+
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
     <!-- ====================================================================== -->
@@ -694,7 +706,9 @@
                       android:description="@string/permgroupdesc_phone"
                       android:priority="500" />
 
-    <!-- Allows read only access to phone state.
+    <!-- Allows read only access to phone state, including the phone number of the device,
+         current cellular network information, the status of any ongoing calls, and a list of any
+         {@link android.telecom.PhoneAccount}s registered on the device.
          <p class="note"><strong>Note:</strong> If <em>both</em> your <a
          href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
          minSdkVersion}</a> and <a
@@ -823,6 +837,26 @@
                 android:protectionLevel="dangerous"/>
 
     <!-- ====================================================================== -->
+    <!-- Permissions for accessing the UCE Service                              -->
+    <!-- ====================================================================== -->
+
+    <!-- @hide Allows an application to Access UCE-Presence.
+         <p>Protection level: dangerous
+    -->
+    <permission android:name="android.permission.ACCESS_UCE_PRESENCE_SERVICE"
+                android:permissionGroup="android.permission-group.PHONE"
+                android:protectionLevel="dangerous"/>
+
+    <!-- @hide Allows an application to Access UCE-OPTIONS.
+         <p>Protection level: dangerous
+    -->
+    <permission android:name="android.permission.ACCESS_UCE_OPTIONS_SERVICE"
+                android:permissionGroup="android.permission-group.PHONE"
+                android:protectionLevel="dangerous"/>
+
+
+
+    <!-- ====================================================================== -->
     <!-- Permissions for accessing the device camera                            -->
     <!-- ====================================================================== -->
     <eat-comment />
@@ -965,16 +999,6 @@
     <!-- INSTALL PERMISSIONS                                                    -->
     <!-- ====================================================================== -->
 
-    `   <!-- =========================================== -->
-    <!-- Permissions for accessing contact metadata -->
-    <!-- =========================================== -->
-    <eat-comment />
-
-    <!-- @SystemApi Allows an application to read/write contact metadata.
-         <p>Not for use by third-party applications. -->
-    <permission android:name="android.permission.READ_WRITE_CONTACT_METADATA"
-                android:protectionLevel="signature|system" />
-
     <!-- ================================== -->
     <!-- Permissions for accessing messages -->
     <!-- ================================== -->
@@ -986,6 +1010,11 @@
     <permission android:name="android.permission.SEND_RESPOND_VIA_MESSAGE"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows an application to send SMS to premium shortcodes without user permission.
+         <p>Not for use by third-party applications. -->
+    <permission android:name="android.permission.SEND_SMS_NO_CONFIRMATION"
+                android:protectionLevel="signature|privileged" />
+
     <!-- Allows an application to filter carrier specific sms.
          @hide -->
     <permission android:name="android.permission.CARRIER_FILTER_SMS"
@@ -1255,7 +1284,7 @@
     <!-- ================================== -->
     <eat-comment />
 
-    <!-- Allows applications to enter Wi-Fi Multicast mode.
+    <!-- Allows applications to enter Wi-Fi ffMulticast mode.
          <p>Protection level: normal
     -->
     <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
@@ -1480,11 +1509,21 @@
 
     <!-- Allows an application to manage access to documents, usually as part
          of a document picker.
+         <p>This permission should <em>only</em> be requested by the platform
+         document management app.  This permission cannot be granted to
+         third-party apps.
          <p>Protection level: signature
     -->
     <permission android:name="android.permission.MANAGE_DOCUMENTS"
                 android:protectionLevel="signature" />
 
+    <!-- @hide Allows an application to cache content.
+         <p>Not for use by third-party applications.
+         <p>Protection level: signature
+    -->
+    <permission android:name="android.permission.CACHE_CONTENT"
+                android:protectionLevel="signature" />
+
     <!-- ================================== -->
     <!-- Permissions for screenlock         -->
     <!-- ================================== -->
@@ -1608,6 +1647,11 @@
     <permission android:name="android.permission.GET_PACKAGE_IMPORTANCE"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- Allows use of PendingIntent.getIntent().
+         @hide -->
+    <permission android:name="android.permission.GET_INTENT_SENDER_INTENT"
+                android:protectionLevel="signature" />
+
     <!-- ================================== -->
     <!-- Permissions affecting the display of other applications  -->
     <!-- ================================== -->
@@ -2128,6 +2172,15 @@
     <permission android:name="android.permission.BIND_PRINT_SERVICE"
                 android:protectionLevel="signature" />
 
+    <!-- Must be required by a {@link android.printservice.recommendation.RecommendationService},
+     to ensure that only the system can bind to it.
+     @hide
+     @SystemApi
+     <p>Protection level: signature
+    -->
+    <permission android:name="android.permission.BIND_PRINT_RECOMMENDATION_SERVICE"
+                android:protectionLevel="signature" />
+
     <!-- Must be required by a {@link android.nfc.cardemulation.HostApduService}
          or {@link android.nfc.cardemulation.OffHostApduService} to ensure that only
          the system can bind to it.
@@ -2695,7 +2748,7 @@
          OTA reboot *not* occur while the lock is held.
          @hide -->
     <permission android:name="android.permission.UPDATE_LOCK"
-                android:protectionLevel="signature|privileged" />
+                android:protectionLevel="signature|fvprivileged" />
 
     <!-- @SystemApi Allows an application to read the current set of notifications, including
          any metadata and intents attached.
@@ -2766,12 +2819,11 @@
                 android:protectionLevel="signature" />
 
     <!-- Must be required by an {@link
-         android.service.notification.NotificationAssistantService},
-         to ensure that only the system can bind to it.
+         android.service.notification.NotificationRankerService         to ensure that only the system can bind to it.
          <p>Protection level: signature
          @hide This is not a third-party API (intended for system apps). -->
     -->
-    <permission android:name="android.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE"
+    <permission android:name="android.permission.BIND_NOTIFICATION_RANKER_SERVICE"
                 android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link
@@ -2926,6 +2978,12 @@
     <permission android:name="android.permission.WRITE_BLOCKED_NUMBERS"
                 android:protectionLevel="signature" />
 
+    <!-- Must be required by an {@link android.service.vr.VrListenerService}, to ensure that only
+         the system can bind to it.
+         <p>Protection level: signature -->
+    <permission android:name="android.permission.BIND_VR_LISTENER_SERVICE"
+                android:protectionLevel="signature" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
@@ -2935,9 +2993,9 @@
                  android:killAfterRestore="false"
                  android:icon="@drawable/ic_launcher_android"
                  android:supportsRtl="true"
-                 android:theme="@style/Theme.Material.DayNight.DarkActionBar"
-                 android:forceDeviceEncrypted="true"
-                 android:encryptionAware="true">
+                 android:theme="@style/Theme.Material.Light.DarkActionBar"
+                 android:defaultToDeviceProtectedStorage="true"
+                 android:directBootAware="true">
         <activity android:name="com.android.internal.app.ChooserActivity"
                   android:theme="@style/Theme.DeviceDefault.Resolver"
                   android:finishOnCloseSystemDialogs="true"
@@ -2971,7 +3029,7 @@
                         android:label="@string/managed_profile_label">
         </activity-alias>
         <activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
-                  android:theme="@style/Theme.Material.DayNight.Dialog"
+                  android:theme="@style/Theme.Material.Light.Dialog"
                   android:label="@string/heavy_weight_switcher_title"
                   android:finishOnCloseSystemDialogs="true"
                   android:excludeFromRecents="true"
@@ -3004,7 +3062,7 @@
         <activity android:name="android.accounts.ChooseAccountActivity"
                   android:excludeFromRecents="true"
                   android:exported="true"
-                  android:theme="@style/Theme.Material.DayNight.Dialog"
+                  android:theme="@style/Theme.Material.Light.Dialog"
                   android:label="@string/choose_account_label"
                   android:process=":ui">
         </activity>
@@ -3012,14 +3070,14 @@
         <activity android:name="android.accounts.ChooseTypeAndAccountActivity"
                   android:excludeFromRecents="true"
                   android:exported="true"
-                  android:theme="@style/Theme.Material.DayNight.Dialog"
+                  android:theme="@style/Theme.Material.Light.Dialog"
                   android:label="@string/choose_account_label"
                   android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.ChooseAccountTypeActivity"
                   android:excludeFromRecents="true"
-                  android:theme="@style/Theme.Material.DayNight.Dialog"
+                  android:theme="@style/Theme.Material.Light.Dialog"
                   android:label="@string/choose_account_label"
                   android:process=":ui">
         </activity>
@@ -3027,19 +3085,19 @@
         <activity android:name="android.accounts.CantAddAccountActivity"
                   android:excludeFromRecents="true"
                   android:exported="true"
-                  android:theme="@style/Theme.Material.DayNight.Dialog.NoActionBar"
+                  android:theme="@style/Theme.Material.Light.Dialog.NoActionBar"
                   android:process=":ui">
         </activity>
 
         <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
                   android:excludeFromRecents="true"
                   android:exported="true"
-                  android:theme="@style/Theme.Material.DayNight.DialogWhenLarge"
+                  android:theme="@style/Theme.Material.Light.DialogWhenLarge"
                   android:process=":ui">
         </activity>
 
         <activity android:name="android.content.SyncActivityTooManyDeletes"
-                  android:theme="@style/Theme.Material.DayNight.Dialog"
+                  android:theme="@style/Theme.Material.Light.Dialog"
                   android:label="@string/sync_too_many_deletes"
                   android:process=":ui">
         </activity>
@@ -3059,7 +3117,7 @@
         </activity>
 
         <activity android:name="com.android.internal.app.NetInitiatedActivity"
-                  android:theme="@style/Theme.Material.DayNight.Dialog.Alert"
+                  android:theme="@style/Theme.Material.Light.Dialog.Alert"
                   android:excludeFromRecents="true"
                   android:process=":ui">
         </activity>
@@ -3080,7 +3138,7 @@
         <activity android:name="com.android.internal.app.ConfirmUserCreationActivity"
                   android:excludeFromRecents="true"
                   android:process=":ui"
-                  android:theme="@style/Theme.Material.DayNight.Dialog.Alert">
+                  android:theme="@style/Theme.Material.Light.Dialog.Alert">
             <intent-filter android:priority="1000">
                 <action android:name="android.os.action.CREATE_USER" />
                 <category android:name="android.intent.category.DEFAULT" />
@@ -3088,7 +3146,7 @@
         </activity>
 
         <activity android:name="com.android.internal.app.UnlaunchableAppActivity"
-                  android:theme="@style/Theme.Material.DayNight.Dialog.Alert"
+                  android:theme="@style/Theme.Material.Light.Dialog.Alert"
                   android:excludeFromRecents="true"
                   android:process=":ui">
         </activity>
diff --git a/tests/tests/print/src/android/print/cts/BasePrintTest.java b/tests/tests/print/src/android/print/cts/BasePrintTest.java
index 038b572..7a31e5f 100644
--- a/tests/tests/print/src/android/print/cts/BasePrintTest.java
+++ b/tests/tests/print/src/android/print/cts/BasePrintTest.java
@@ -105,6 +105,7 @@
     private CallCounter mWriteCallCounter;
     private CallCounter mFinishCallCounter;
     private CallCounter mPrintJobQueuedCallCounter;
+    private CallCounter mCreateSessionCallCounter;
     private CallCounter mDestroySessionCallCounter;
 
     private String[] mEnabledImes;
@@ -189,6 +190,7 @@
         mWriteCallCounter = new CallCounter();
         mFinishCallCounter = new CallCounter();
         mPrintJobQueuedCallCounter = new CallCounter();
+        mCreateSessionCallCounter = new CallCounter();
         mDestroySessionCallCounter = new CallCounter();
 
         // Create the activity for the right locale.
@@ -261,6 +263,10 @@
         mPrintJobQueuedCallCounter.call();
     }
 
+    protected void onPrinterDiscoverySessionCreateCalled() {
+        mCreateSessionCallCounter.call();
+    }
+
     protected void onPrinterDiscoverySessionDestroyCalled() {
         mDestroySessionCallCounter.call();
     }
@@ -270,6 +276,11 @@
                 "Did not get expected call to onCancel for the current operation.");
     }
 
+    protected void waitForPrinterDiscoverySessionCreateCallbackCalled() {
+        waitForCallbackCallCount(mCreateSessionCallCounter, 1,
+                "Did not get expected call to onCreatePrinterDiscoverySession.");
+    }
+
     protected void waitForPrinterDiscoverySessionDestroyCallbackCalled() {
         waitForCallbackCallCount(mDestroySessionCallCounter, 1,
                 "Did not get expected call to onDestroyPrinterDiscoverySession.");
@@ -550,7 +561,8 @@
         }
         if (onRequestCustomPrinterIcon != null) {
             doAnswer(onRequestCustomPrinterIcon).when(callbacks).onRequestCustomPrinterIcon(
-                    any(PrinterId.class), any(CustomPrinterIconCallback.class));
+                    any(PrinterId.class), any(CancellationSignal.class),
+                    any(CustomPrinterIconCallback.class));
         }
         if (onStopPrinterStateTracking != null) {
             doAnswer(onStopPrinterStateTracking).when(callbacks).onStopPrinterStateTracking(
diff --git a/tests/tests/print/src/android/print/cts/ClassParametersTest.java b/tests/tests/print/src/android/print/cts/ClassParametersTest.java
new file mode 100644
index 0000000..bad47f8
--- /dev/null
+++ b/tests/tests/print/src/android/print/cts/ClassParametersTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.print.cts;
+
+import android.print.PrintAttributes;
+import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
+import android.print.PrintDocumentInfo;
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test that the print attributes are correctly propagated through the print framework
+ */
+@RunWith(AndroidJUnit4.class)
+public class ClassParametersTest {
+    /**
+     * Run a runnable and expect and exception of a certain type.
+     *
+     * @param r The runnable to run
+     * @param expectedClass The expected exception type
+     */
+    private void assertException(Runnable r, Class<? extends RuntimeException> expectedClass) {
+        try {
+            r.run();
+        } catch (Exception e) {
+            if (e.getClass().isAssignableFrom(expectedClass)) {
+                return;
+            } else {
+                throw new AssertionError("Expected: " + expectedClass.getName() + ", got: "
+                        + e.getClass().getName());
+            }
+        }
+
+        throw new AssertionError("No exception thrown");
+    }
+
+    /**
+     * Test that we cannot create PrintAttributes with illegal parameters.
+     *
+     * @throws Exception If anything is unexpected
+     */
+    @Test
+    public void testIllegalPrintAttributes() throws Exception {
+        assertException(() -> (new PrintAttributes.Builder()).setColorMode(-1),
+                IllegalArgumentException.class);
+        assertException(() -> (new PrintAttributes.Builder()).setColorMode(0),
+                IllegalArgumentException.class);
+        assertException(() -> (new PrintAttributes.Builder()).setColorMode(
+                PrintAttributes.COLOR_MODE_COLOR | PrintAttributes.COLOR_MODE_MONOCHROME),
+                IllegalArgumentException.class);
+
+        assertException(() -> (new PrintAttributes.Builder()).setDuplexMode(-1),
+                IllegalArgumentException.class);
+        assertException(() -> (new PrintAttributes.Builder()).setDuplexMode(0),
+                IllegalArgumentException.class);
+        assertException(() -> (new PrintAttributes.Builder()).setDuplexMode(
+                PrintAttributes.DUPLEX_MODE_LONG_EDGE | PrintAttributes.DUPLEX_MODE_NONE),
+                IllegalArgumentException.class);
+
+        assertException(() -> new Resolution(null, "label", 10, 10),
+                IllegalArgumentException.class);
+        assertException(() -> new Resolution("", "label", 10, 10),
+                IllegalArgumentException.class);
+        assertException(() -> new Resolution("id", null, 10, 10),
+                IllegalArgumentException.class);
+        assertException(() -> new Resolution("id", "", 10, 10),
+                IllegalArgumentException.class);
+        assertException(() -> new Resolution("id", "label", -10, 10),
+                IllegalArgumentException.class);
+        assertException(() -> new Resolution("id", "label", 0, 10),
+                IllegalArgumentException.class);
+        assertException(() -> new Resolution("id", "label", 10, -10),
+                IllegalArgumentException.class);
+        assertException(() -> new Resolution("id", "label", 10, 0),
+                IllegalArgumentException.class);
+
+        assertException(() -> new MediaSize(null, "label", 10, 10),
+                IllegalArgumentException.class);
+        assertException(() -> new MediaSize("", "label", 10, 10),
+                IllegalArgumentException.class);
+        assertException(() -> new MediaSize("id", null, 10, 10),
+                IllegalArgumentException.class);
+        assertException(() -> new MediaSize("id", "", 10, 10),
+                IllegalArgumentException.class);
+        assertException(() -> new MediaSize("id", "label", -10, 10),
+                IllegalArgumentException.class);
+        assertException(() -> new MediaSize("id", "label", 0, 10),
+                IllegalArgumentException.class);
+        assertException(() -> new MediaSize("id", "label", 10, -10),
+                IllegalArgumentException.class);
+        assertException(() -> new MediaSize("id", "label", 10, 0),
+                IllegalArgumentException.class);
+
+        // There is no restrictions on what parameters to set for minMargins.
+    }
+
+    /**
+     * Test that we cannot create PrintDocumentInfo with illegal parameters.
+     *
+     * @throws Exception If anything is unexpected
+     */
+    @Test
+    public void testIllegalPrintDocumentInfo() throws Exception {
+        assertException(() -> new PrintDocumentInfo.Builder(null),
+                IllegalArgumentException.class);
+        assertException(() -> new PrintDocumentInfo.Builder(""),
+                IllegalArgumentException.class);
+
+        assertException(() -> new PrintDocumentInfo.Builder("doc").setPageCount(-2),
+                IllegalArgumentException.class);
+        // -1 == UNKNOWN and 0 are allowed
+
+        // Content type is not restricted
+    }
+}
diff --git a/tests/tests/print/src/android/print/cts/PrintAttributesTest.java b/tests/tests/print/src/android/print/cts/PrintAttributesTest.java
index 855f587..1b8c318 100644
--- a/tests/tests/print/src/android/print/cts/PrintAttributesTest.java
+++ b/tests/tests/print/src/android/print/cts/PrintAttributesTest.java
@@ -637,7 +637,7 @@
      *
      * @throws Exception If anything is unexpected
      */
-    public void testIllegalSuggested() throws Exception {
+    public void testUnsupportedSuggested() throws Exception {
         //       available                               default          suggestion
         baseTest(                                        MIN_MARGINS[0],
                  Arrays.copyOfRange(MEDIA_SIZES, 0, 1),  MEDIA_SIZES[0],  MEDIA_SIZES[1],
@@ -645,4 +645,19 @@
                  Arrays.copyOfRange(DUPLEX_MODES, 0, 1), DUPLEX_MODES[0], DUPLEX_MODES[1],
                  Arrays.copyOfRange(RESOLUTIONS, 0, 1),  RESOLUTIONS[0],  RESOLUTIONS[1]);
     }
+
+    /**
+     * Test that negative Margins do not cause issues in the print print spooler. Negative margins
+     * are allowed because of historical reasons.
+     *
+     * @throws Exception If anything is unexpected
+     */
+    public void testNegativeMargins() throws Exception {
+        //       available     default                          suggestion
+        baseTest(              new Margins(-10, -10, -10, -10),
+                 MEDIA_SIZES,  MEDIA_SIZES[1],                  null,
+                 COLOR_MODES,  COLOR_MODES[1],                  0,
+                 DUPLEX_MODES, DUPLEX_MODES[1],                 0,
+                 RESOLUTIONS,  RESOLUTIONS[1],                  null);
+    }
 }
diff --git a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
index 7d0157b..b539a83 100644
--- a/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
+++ b/tests/tests/print/src/android/print/cts/PrintDocumentAdapterContractTest.java
@@ -1665,6 +1665,154 @@
         waitForPrinterDiscoverySessionDestroyCallbackCalled();
     }
 
+    /**
+     * Executes a print process with a given print document info
+     *
+     * @param info The print document info to declare on layout
+     */
+    private void printDocumentInfoBaseTest(final PrintDocumentInfo info) throws Exception {
+        if (!supportsPrinting()) {
+            return;
+        }
+        // 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];
+                        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, 1);
+                        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);
+
+        // Select the second printer.
+        selectPrinter("Second printer");
+
+        // Wait for layout.
+        waitForLayoutAdapterCallbackCount(2);
+
+        // Click the print button.
+        clickPrintButton();
+
+        // Answer the dialog for the print service cloud warning
+        answerPrintServicesWarning(true);
+
+        // Wait for the session to be destroyed to isolate tests.
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+    }
+
+    /**
+     * Test that the default values of the PrintDocumentInfo are fine.
+     *
+     * @throws Exception If anything unexpected happens
+     */
+    public void testDocumentInfoNothingSet() throws Exception {
+        printDocumentInfoBaseTest((new PrintDocumentInfo.Builder(PRINT_JOB_NAME)).build());
+    }
+
+    /**
+     * Test that a unknown page count is handled correctly.
+     *
+     * @throws Exception If anything unexpected happens
+     */
+    public void testDocumentInfoUnknownPageCount() throws Exception {
+        printDocumentInfoBaseTest((new PrintDocumentInfo.Builder(PRINT_JOB_NAME))
+                .setPageCount(PrintDocumentInfo.PAGE_COUNT_UNKNOWN).build());
+    }
+
+    /**
+     * Test that zero page count is handled correctly.
+     *
+     * @throws Exception If anything unexpected happens
+     */
+    public void testDocumentInfoZeroPageCount() throws Exception {
+        printDocumentInfoBaseTest((new PrintDocumentInfo.Builder(PRINT_JOB_NAME))
+                .setPageCount(0).build());
+    }
+
+    /**
+     * Test that page count one is handled correctly. (The document has two pages)
+     *
+     * @throws Exception If anything unexpected happens
+     */
+    public void testDocumentInfoOnePageCount() throws Exception {
+        printDocumentInfoBaseTest((new PrintDocumentInfo.Builder(PRINT_JOB_NAME))
+                .setPageCount(1).build());
+    }
+
+    /**
+     * Test that page count three is handled correctly. (The document has two pages)
+     *
+     * @throws Exception If anything unexpected happens
+     */
+    public void testDocumentInfoThreePageCount() throws Exception {
+        printDocumentInfoBaseTest((new PrintDocumentInfo.Builder(PRINT_JOB_NAME))
+                .setPageCount(3).build());
+    }
+
+    /**
+     * Test that a photo content type is handled correctly.
+     *
+     * @throws Exception If anything unexpected happens
+     */
+    public void testDocumentInfoContentTypePhoto() throws Exception {
+        printDocumentInfoBaseTest((new PrintDocumentInfo.Builder(PRINT_JOB_NAME))
+                .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO).build());
+    }
+
+    /**
+     * Test that a unknown content type is handled correctly.
+     *
+     * @throws Exception If anything unexpected happens
+     */
+    public void testDocumentInfoContentTypeUnknown() throws Exception {
+        printDocumentInfoBaseTest((new PrintDocumentInfo.Builder(PRINT_JOB_NAME))
+                .setContentType(PrintDocumentInfo.CONTENT_TYPE_UNKNOWN).build());
+    }
+
+    /**
+     * Test that a undefined content type is handled correctly.
+     *
+     * @throws Exception If anything unexpected happens
+     */
+    public void testDocumentInfoContentTypeNonDefined() throws Exception {
+        printDocumentInfoBaseTest((new PrintDocumentInfo.Builder(PRINT_JOB_NAME))
+                .setContentType(-23).build());
+    }
+
     private PrintServiceCallbacks createFirstMockPrintServiceCallbacks() {
         final PrinterDiscoverySessionCallbacks callbacks =
                 createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
diff --git a/tests/tests/print/src/android/print/cts/PrintServicesTest.java b/tests/tests/print/src/android/print/cts/PrintServicesTest.java
index 4422979..e1e17ff 100644
--- a/tests/tests/print/src/android/print/cts/PrintServicesTest.java
+++ b/tests/tests/print/src/android/print/cts/PrintServicesTest.java
@@ -200,7 +200,7 @@
             @Override
             public Void answer(InvocationOnMock invocation) throws Throwable {
                 CustomPrinterIconCallback callback = (CustomPrinterIconCallback) invocation
-                        .getArguments()[1];
+                        .getArguments()[2];
 
                 if (mIcon != null) {
                     callback.onCustomPrinterIconLoaded(mIcon);
diff --git a/tests/tests/print/src/android/print/cts/PrinterCapabilitiesTest.java b/tests/tests/print/src/android/print/cts/PrinterCapabilitiesTest.java
index 2ed21b9..1df068d 100644
--- a/tests/tests/print/src/android/print/cts/PrinterCapabilitiesTest.java
+++ b/tests/tests/print/src/android/print/cts/PrinterCapabilitiesTest.java
@@ -43,6 +43,8 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeoutException;
+import java.util.function.Consumer;
+import java.util.function.Function;
 
 /**
  * This test verifies changes to the printer capabilities are applied correctly.
@@ -51,8 +53,14 @@
     private static final String LOG_TAG = "PrinterCapabilitiesTest";
     private static final String PRINTER_NAME = "Test printer";
 
+    private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0);
+    private static final PrintAttributes.Resolution RESOLUTION_300 =
+            new PrintAttributes.Resolution("300", "300", 300, 300);
+    private static final PrintAttributes.Resolution RESOLUTION_600 =
+            new PrintAttributes.Resolution("600", "600", 600, 600);
+
     /**
-     * Generate a new list of printers containing a singler printer with the given media size and
+     * Generate a new list of printers containing a singer printer with the given media size and
      * status. The other capabilities are default values.
      *
      * @param printerId The id of the printer
@@ -70,13 +78,13 @@
         if (mediaSize != null) {
             PrinterCapabilitiesInfo.Builder builder = new PrinterCapabilitiesInfo.Builder(
                     printerId);
-            builder.setMinMargins(new Margins(0, 0, 0, 0))
+            builder.setMinMargins(DEFAULT_MARGINS)
                     .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
                             PrintAttributes.COLOR_MODE_COLOR)
                     .setDuplexModes(PrintAttributes.DUPLEX_MODE_NONE,
                             PrintAttributes.DUPLEX_MODE_NONE)
                     .addMediaSize(mediaSize, true)
-                    .addResolution(new Resolution("300x300", "300x300", 300, 300), true);
+                    .addResolution(RESOLUTION_300, true);
             cap = builder.build();
         } else {
             cap = null;
@@ -339,4 +347,409 @@
 
         waitForPrinterDiscoverySessionDestroyCallbackCalled();
     }
+
+    /**
+     * Run a runnable and expect and exception of a certain type.
+     *
+     * @param r The runnable to run
+     * @param expectedClass The expected exception type
+     */
+    private void assertException(Runnable r, Class<? extends RuntimeException> expectedClass) {
+        try {
+            r.run();
+        } catch (Exception e) {
+            if (e.getClass().isAssignableFrom(expectedClass)) {
+                return;
+            } else {
+                throw new AssertionError("Expected: " + expectedClass.getName() + ", got: "
+                        + e.getClass().getName());
+            }
+        }
+
+        throw new AssertionError("No exception thrown");
+    }
+
+    /**
+     * That that you cannot create illegal PrinterCapabilityInfos.
+     *
+     * @throws Exception If anything is unexpected
+     */
+    public void testIllegalPrinterCapabilityInfos() throws Exception {
+        if (!supportsPrinting()) {
+            return;
+        }
+
+        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
+                createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) {
+                        StubbablePrinterDiscoverySession session =
+                                ((PrinterDiscoverySessionCallbacks)
+                                        invocation.getMock()).getSession();
+
+                        PrinterId printerId = session.getService().generatePrinterId(PRINTER_NAME);
+
+                        // printerId need to be set
+                        assertException(() -> new PrinterCapabilitiesInfo.Builder(null),
+                                IllegalArgumentException.class);
+
+                        // All capability fields (beside duplex) need to be initialized:
+                        // Test no color
+                        assertException(() ->
+                                        (new PrinterCapabilitiesInfo.Builder(printerId))
+                                                .setMinMargins(DEFAULT_MARGINS)
+                                                .addMediaSize(MediaSize.ISO_A4, true)
+                                                .addResolution(RESOLUTION_300, true).build(),
+                                IllegalStateException.class);
+                        // Test bad colors
+                        assertException(() ->
+                                        (new PrinterCapabilitiesInfo.Builder(printerId))
+                                                .setColorModes(0xffff,
+                                                        PrintAttributes.COLOR_MODE_MONOCHROME),
+                                IllegalArgumentException.class);
+                        // Test bad duplex mode
+                        assertException(() ->
+                                        (new PrinterCapabilitiesInfo.Builder(printerId))
+                                                .setDuplexModes(0xffff,
+                                                        PrintAttributes.DUPLEX_MODE_NONE),
+                                IllegalArgumentException.class);
+                        // Test no mediasize
+                        assertException(() ->
+                                        (new PrinterCapabilitiesInfo.Builder(printerId))
+                                                .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+                                                        PrintAttributes.COLOR_MODE_COLOR)
+                                                .setMinMargins(DEFAULT_MARGINS)
+                                                .addResolution(RESOLUTION_300, true).build(),
+                                IllegalStateException.class);
+                        // Test no default mediasize
+                        assertException(() ->
+                                        (new PrinterCapabilitiesInfo.Builder(printerId))
+                                                .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+                                                        PrintAttributes.COLOR_MODE_COLOR)
+                                                .setMinMargins(DEFAULT_MARGINS)
+                                                .addMediaSize(MediaSize.ISO_A4, false)
+                                                .addResolution(RESOLUTION_300, true).build(),
+                                IllegalStateException.class);
+                        // Test two default mediasizes
+                        assertException(() ->
+                                        (new PrinterCapabilitiesInfo.Builder(printerId))
+                                                .addMediaSize(MediaSize.ISO_A4, true)
+                                                .addMediaSize(MediaSize.ISO_A5, true),
+                                IllegalArgumentException.class);
+                        // Test no resolution
+                        assertException(() ->
+                                        (new PrinterCapabilitiesInfo.Builder(printerId))
+                                                .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+                                                        PrintAttributes.COLOR_MODE_COLOR)
+                                                .setMinMargins(DEFAULT_MARGINS)
+                                                .addMediaSize(MediaSize.ISO_A4, true).build(),
+                                IllegalStateException.class);
+                        // Test no default resolution
+                        assertException(() ->
+                                        (new PrinterCapabilitiesInfo.Builder(printerId))
+                                                .setColorModes(PrintAttributes.COLOR_MODE_COLOR,
+                                                        PrintAttributes.COLOR_MODE_COLOR)
+                                                .setMinMargins(DEFAULT_MARGINS)
+                                                .addMediaSize(MediaSize.ISO_A4, true)
+                                                .addResolution(RESOLUTION_300, false).build(),
+                                IllegalStateException.class);
+                        // Test two default resolutions
+                        assertException(() ->
+                                        (new PrinterCapabilitiesInfo.Builder(printerId))
+                                                .addResolution(RESOLUTION_300, true)
+                                                .addResolution(RESOLUTION_600, true),
+                                IllegalArgumentException.class);
+
+                        onPrinterDiscoverySessionCreateCalled();
+                        return null;
+                    }
+                }, null, null, null, null, null, new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) {
+                        onPrinterDiscoverySessionDestroyCalled();
+                        return null;
+                    }
+                });
+
+        // Create the service callbacks for the first print service.
+        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
+                new Answer<PrinterDiscoverySessionCallbacks>() {
+                    @Override
+                    public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+                        return firstSessionCallbacks;
+                    }
+                }, null, null);
+
+        // Configure the print services.
+        FirstPrintService.setCallbacks(firstServiceCallbacks);
+        SecondPrintService.setCallbacks(createMockPrintServiceCallbacks(null, null, null));
+
+        PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(null, null, null);
+
+        // Start printing.
+        print(adapter);
+
+        waitForPrinterDiscoverySessionCreateCallbackCalled();
+
+        getUiDevice().pressBack();
+
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+    }
+
+    /**
+     * That that you can use all sane legal PrinterCapabilityInfos.
+     *
+     * @throws Exception If anything is unexpected
+     */
+    public void testSanePrinterCapabilityInfos() throws Exception {
+        if (!supportsPrinting()) {
+            return;
+        }
+
+        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
+                createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) {
+                        StubbablePrinterDiscoverySession session =
+                                ((PrinterDiscoverySessionCallbacks)
+                                        invocation.getMock()).getSession();
+
+                        MediaSize[] mediaSizes = {MediaSize.ISO_A0, MediaSize.ISO_A0,
+                                MediaSize.ISO_A1};
+                        Resolution[] resolutions = {RESOLUTION_300, RESOLUTION_300,
+                                RESOLUTION_600};
+                        int[] colorModes = {PrintAttributes.COLOR_MODE_MONOCHROME,
+                                PrintAttributes.COLOR_MODE_COLOR};
+                        int[] duplexModes = {PrintAttributes.DUPLEX_MODE_NONE,
+                                PrintAttributes.DUPLEX_MODE_LONG_EDGE,
+                                PrintAttributes.DUPLEX_MODE_SHORT_EDGE};
+
+                        ArrayList<PrinterInfo> printers = new ArrayList<>();
+                        for (int mediaSizeIndex = 1; mediaSizeIndex < mediaSizes.length;
+                             mediaSizeIndex++) {
+                            for (int resolutionIndex = 1; resolutionIndex < mediaSizes.length;
+                                 resolutionIndex++) {
+                                for (int colorIndex = 1; colorIndex < colorModes.length;
+                                     colorIndex++) {
+                                    for (int duplexIndex = 1; duplexIndex < duplexModes.length;
+                                         duplexIndex++) {
+                                        PrinterId printerId = session.getService()
+                                                .generatePrinterId(Integer.valueOf(printers.size())
+                                                        .toString());
+
+                                        PrinterCapabilitiesInfo.Builder b =
+                                                new PrinterCapabilitiesInfo.Builder(printerId);
+
+                                        for (int i = 0; i < mediaSizeIndex; i++) {
+                                            b.addMediaSize(mediaSizes[i], i == mediaSizeIndex - 1);
+                                        }
+
+                                        for (int i = 0; i < resolutionIndex; i++) {
+                                            b.addResolution(resolutions[i],
+                                                    i == resolutionIndex - 1);
+                                        }
+
+                                        int allColors = 0;
+                                        for (int i = 0; i < colorIndex; i++) {
+                                            allColors |= colorModes[i];
+                                        }
+                                        b.setColorModes(allColors, colorModes[colorIndex - 1]);
+
+                                        int allDuplexModes = 0;
+                                        for (int i = 0; i < duplexIndex; i++) {
+                                            allDuplexModes |= duplexModes[i];
+                                        }
+                                        b.setDuplexModes(allDuplexModes,
+                                                duplexModes[duplexIndex - 1]);
+
+                                        printers.add((new PrinterInfo.Builder(printerId,
+                                                Integer.valueOf(printers.size()).toString(),
+                                                PrinterInfo.STATUS_IDLE)).setCapabilities(b.build())
+                                                .build());
+                                    }
+                                }
+                            }
+                        }
+
+                        session.addPrinters(printers);
+
+                        onPrinterDiscoverySessionCreateCalled();
+                        return null;
+                    }
+                }, null, null, null, null, null, new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) {
+                        onPrinterDiscoverySessionDestroyCalled();
+                        return null;
+                    }
+                });
+
+        // Create the service callbacks for the first print service.
+        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
+                new Answer<PrinterDiscoverySessionCallbacks>() {
+                    @Override
+                    public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+                        return firstSessionCallbacks;
+                    }
+                }, null, null);
+
+        // Configure the print services.
+        FirstPrintService.setCallbacks(firstServiceCallbacks);
+        SecondPrintService.setCallbacks(createMockPrintServiceCallbacks(null, null, null));
+
+        PrintDocumentAdapter adapter = createMockPrintDocumentAdapter(null, null, null);
+
+        // Start printing.
+        print(adapter);
+
+        waitForPrinterDiscoverySessionCreateCallbackCalled();
+
+        getUiDevice().pressBack();
+
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+    }
+
+    /**
+     * Base test that performs a print operation with a give PrinterCapabilityInfo and run a test
+     * function before finishing.
+     *
+     * @throws Exception
+     */
+    private void testPrinterCapabilityInfo(final Function<PrinterId, PrinterCapabilitiesInfo>
+            capBuilder, Consumer<PrintAttributes> test) throws Exception {
+        if (!supportsPrinting()) {
+            return;
+        }
+
+        final PrinterDiscoverySessionCallbacks firstSessionCallbacks =
+                createMockPrinterDiscoverySessionCallbacks(new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) {
+                        StubbablePrinterDiscoverySession session =
+                                ((PrinterDiscoverySessionCallbacks)
+                                        invocation.getMock()).getSession();
+
+                        PrinterId printerId = session.getService()
+                                .generatePrinterId(PRINTER_NAME);
+
+                        ArrayList<PrinterInfo> printers = new ArrayList<>();
+                        printers.add((new PrinterInfo.Builder(printerId, PRINTER_NAME,
+                                PrinterInfo.STATUS_IDLE))
+                                .setCapabilities(capBuilder.apply(printerId)).build());
+
+                        session.addPrinters(printers);
+
+                        onPrinterDiscoverySessionCreateCalled();
+                        return null;
+                    }
+                }, null, null, null, null, null, new Answer<Void>() {
+                    @Override
+                    public Void answer(InvocationOnMock invocation) {
+                        onPrinterDiscoverySessionDestroyCalled();
+                        return null;
+                    }
+                });
+
+        // Create the service callbacks for the first print service.
+        PrintServiceCallbacks firstServiceCallbacks = createMockPrintServiceCallbacks(
+                new Answer<PrinterDiscoverySessionCallbacks>() {
+                    @Override
+                    public PrinterDiscoverySessionCallbacks answer(InvocationOnMock invocation) {
+                        return firstSessionCallbacks;
+                    }
+                }, null, null);
+
+        // Configure the print services.
+        FirstPrintService.setCallbacks(firstServiceCallbacks);
+        SecondPrintService.setCallbacks(createMockPrintServiceCallbacks(null, null, null));
+
+        final PrintAttributes[] layoutAttributes = new PrintAttributes[1];
+
+        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)
+                                .setPageCount(1)
+                                .build();
+                        layoutAttributes[0] = (PrintAttributes) invocation.getArguments()[1];
+
+                        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(layoutAttributes[0], fd, pages[0].getStart(),
+                                pages[0].getEnd());
+                        fd.close();
+
+                        callback.onWriteFinished(pages);
+                        return null;
+                    }
+                }, null);
+
+        // Start printing.
+        print(adapter);
+
+        // make sure that options does not crash
+        openPrintOptions();
+
+        // Select printer under test
+        selectPrinter(PRINTER_NAME);
+
+        clickPrintButton();
+
+        answerPrintServicesWarning(true);
+
+        test.accept(layoutAttributes[0]);
+
+        waitForPrinterDiscoverySessionDestroyCallbackCalled();
+    }
+
+    /**
+     * That that you use a default color that is not in the allowed colors. This is allowed because
+     * of historical reasons.
+     *
+     * @throws Exception If anything is unexpected
+     */
+    public void testInvalidDefaultColor() throws Exception {
+        testPrinterCapabilityInfo(
+                (printerId) -> (new PrinterCapabilitiesInfo.Builder(printerId))
+                        .addMediaSize(MediaSize.ISO_A4, true)
+                        .addResolution(RESOLUTION_300, true)
+                        .setColorModes(PrintAttributes.COLOR_MODE_MONOCHROME,
+                                PrintAttributes.COLOR_MODE_COLOR).build(),
+                (layoutAttributes) -> assertEquals(layoutAttributes.getColorMode(),
+                        PrintAttributes.COLOR_MODE_MONOCHROME));
+    }
+
+    /**
+     * That that you use a default duplex mode that is not in the allowed duplex modes. This is
+     * allowed because of historical reasons.
+     *
+     * @throws Exception If anything is unexpected
+     */
+    public void testInvalidDefaultDuplexMode() throws Exception {
+        testPrinterCapabilityInfo(
+                (printerId) -> (new PrinterCapabilitiesInfo.Builder(printerId))
+                        .addMediaSize(MediaSize.ISO_A4, true)
+                        .addResolution(RESOLUTION_300, true)
+                        .setColorModes(PrintAttributes.COLOR_MODE_MONOCHROME,
+                                PrintAttributes.COLOR_MODE_MONOCHROME)
+                        .setDuplexModes(PrintAttributes.DUPLEX_MODE_LONG_EDGE
+                                | PrintAttributes.DUPLEX_MODE_NONE,
+                                PrintAttributes.DUPLEX_MODE_SHORT_EDGE).build(),
+                (layoutAttributes) -> assertTrue(layoutAttributes.getDuplexMode() ==
+                        PrintAttributes.DUPLEX_MODE_LONG_EDGE || layoutAttributes.getDuplexMode() ==
+                        PrintAttributes.DUPLEX_MODE_NONE));
+    }
 }
diff --git a/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java b/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
index a198790..00efa67 100644
--- a/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
+++ b/tests/tests/print/src/android/print/cts/PrinterDiscoverySessionLifecycleTest.java
@@ -187,6 +187,7 @@
 
         // Configure the print services.
         FirstPrintService.setCallbacks(firstServiceCallbacks);
+        SecondPrintService.setCallbacks(createSecondMockPrintServiceCallbacks());
 
         // Create a print adapter that respects the print contract.
         PrintDocumentAdapter adapter = createMockPrintDocumentAdapter();
diff --git a/tests/tests/print/src/android/print/cts/PrinterInfoTest.java b/tests/tests/print/src/android/print/cts/PrinterInfoTest.java
index db19d20..db09b24 100644
--- a/tests/tests/print/src/android/print/cts/PrinterInfoTest.java
+++ b/tests/tests/print/src/android/print/cts/PrinterInfoTest.java
@@ -367,7 +367,7 @@
             @Override
             public Void answer(InvocationOnMock invocation) throws Throwable {
                 CustomPrinterIconCallback callback = (CustomPrinterIconCallback) invocation
-                        .getArguments()[1];
+                        .getArguments()[2];
 
                 if (mIcon != null) {
                     callback.onCustomPrinterIconLoaded(mIcon);
diff --git a/tests/tests/print/src/android/print/cts/services/PrinterDiscoverySessionCallbacks.java b/tests/tests/print/src/android/print/cts/services/PrinterDiscoverySessionCallbacks.java
index 2e0e729..ebddda1 100644
--- a/tests/tests/print/src/android/print/cts/services/PrinterDiscoverySessionCallbacks.java
+++ b/tests/tests/print/src/android/print/cts/services/PrinterDiscoverySessionCallbacks.java
@@ -16,6 +16,7 @@
 
 package android.print.cts.services;
 
+import android.os.CancellationSignal;
 import android.print.PrinterId;
 import android.printservice.CustomPrinterIconCallback;
 
@@ -42,7 +43,7 @@
     public abstract void onStartPrinterStateTracking(PrinterId printerId);
 
     public abstract void onRequestCustomPrinterIcon(PrinterId printerId,
-            CustomPrinterIconCallback callback);
+            CancellationSignal cancellationSignal, CustomPrinterIconCallback callback);
 
     public abstract void onStopPrinterStateTracking(PrinterId printerId);
 
diff --git a/tests/tests/print/src/android/print/cts/services/StubbablePrinterDiscoverySession.java b/tests/tests/print/src/android/print/cts/services/StubbablePrinterDiscoverySession.java
index 4c2d8b8..b7cccaa 100644
--- a/tests/tests/print/src/android/print/cts/services/StubbablePrinterDiscoverySession.java
+++ b/tests/tests/print/src/android/print/cts/services/StubbablePrinterDiscoverySession.java
@@ -16,6 +16,7 @@
 
 package android.print.cts.services;
 
+import android.os.CancellationSignal;
 import android.print.PrinterId;
 import android.printservice.CustomPrinterIconCallback;
 import android.printservice.PrintService;
@@ -70,9 +71,9 @@
 
     @Override
     public void onRequestCustomPrinterIcon(PrinterId printerId,
-            CustomPrinterIconCallback callback) {
+            CancellationSignal cancellationSignal, CustomPrinterIconCallback callback) {
         if (mCallbacks != null) {
-            mCallbacks.onRequestCustomPrinterIcon(printerId, callback);
+            mCallbacks.onRequestCustomPrinterIcon(printerId, cancellationSignal, callback);
         }
     }
 
diff --git a/tests/tests/provider/AndroidManifest.xml b/tests/tests/provider/AndroidManifest.xml
index e56ac1d..aadddb5 100644
--- a/tests/tests/provider/AndroidManifest.xml
+++ b/tests/tests/provider/AndroidManifest.xml
@@ -36,6 +36,9 @@
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
     <uses-permission android:name="android.permission.READ_CALL_LOG" />
     <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.READ_SMS" />
+    <uses-permission android:name="android.permission.WRITE_SMS" />
+
 
     <application>
         <uses-library android:name="android.test.runner"/>
diff --git a/tests/tests/provider/src/android/provider/cts/BlockedNumberBackupRestoreTest.java b/tests/tests/provider/src/android/provider/cts/BlockedNumberBackupRestoreTest.java
index fc0333c..5ea4caf 100644
--- a/tests/tests/provider/src/android/provider/cts/BlockedNumberBackupRestoreTest.java
+++ b/tests/tests/provider/src/android/provider/cts/BlockedNumberBackupRestoreTest.java
@@ -16,16 +16,14 @@
 
 package android.provider.cts;
 
+import android.app.UiAutomation;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.provider.BlockedNumberContract;
 import android.telecom.Log;
 
-import java.util.Objects;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
 /**
  * CTS tests for backup and restore of blocked numbers using local transport.
  */
@@ -39,13 +37,12 @@
             "android/com.android.internal.backup.LocalTransport";
     private static final String BLOCKED_NUMBERS_PROVIDER_PACKAGE =
             "com.android.providers.blockednumber";
-    private static final int BACKUP_TIMEOUT_MILLIS = 4000;
-    private static final Pattern BMGR_ENABLED_PATTERN = Pattern.compile(
-            "^Backup Manager currently (enabled|disabled)$");
 
     private ContentResolver mContentResolver;
     private Context mContext;
+    private UiAutomation mUiAutomation;
     private String mOldTransport;
+    private boolean mHasFeature;
 
     @Override
     protected void setUp() throws Exception {
@@ -53,30 +50,36 @@
 
         mContext = getInstrumentation().getContext();
         mContentResolver = mContext.getContentResolver();
+        mUiAutomation = getInstrumentation().getUiAutomation();
 
-        BlockedNumberTestUtils.setDefaultSmsApp(
-                true, mContext.getPackageName(), getInstrumentation().getUiAutomation());
+        mHasFeature = isFeatureSupported();
 
-        mOldTransport = setBackupTransport(LOCAL_BACKUP_COMPONENT);
-        clearBlockedNumbers();
-        wipeBackup();
+        if (mHasFeature) {
+            ProviderTestUtils.setDefaultSmsApp(true, mContext.getPackageName(), mUiAutomation);
+
+            mOldTransport = ProviderTestUtils.setBackupTransport(
+                    LOCAL_BACKUP_COMPONENT, mUiAutomation);
+            clearBlockedNumbers();
+            wipeBackup();
+        }
     }
 
     @Override
     protected void tearDown() throws Exception {
-        wipeBackup();
-        clearBlockedNumbers();
-        setBackupTransport(mOldTransport);
-
-        BlockedNumberTestUtils.setDefaultSmsApp(
-                false, mContext.getPackageName(), getInstrumentation().getUiAutomation());
+        if (mHasFeature) {
+            wipeBackup();
+            clearBlockedNumbers();
+            ProviderTestUtils.setBackupTransport(mOldTransport, mUiAutomation);
+            ProviderTestUtils.setDefaultSmsApp(false, mContext.getPackageName(), mUiAutomation);
+        }
 
         super.tearDown();
     }
 
     public void testBackupAndRestoreForSingleNumber() throws Exception {
-        if (!hasBackupTransport(LOCAL_BACKUP_COMPONENT)) {
+        if (!mHasFeature) {
             Log.i(TAG, "skipping BlockedNumberBackupRestoreTest");
+            return;
         }
 
         Log.i(TAG, "Adding blocked numbers.");
@@ -84,7 +87,6 @@
 
         Log.i(TAG, "Running backup.");
         runBackup();
-        Thread.sleep(BACKUP_TIMEOUT_MILLIS);
 
         Log.i(TAG, "Clearing blocked numbers.");
         clearBlockedNumbers();
@@ -92,13 +94,13 @@
 
         Log.i(TAG, "Restoring blocked numbers.");
         runRestore();
-        Thread.sleep(BACKUP_TIMEOUT_MILLIS);
         verifyBlockedNumbers("123456789");
     }
 
     public void testBackupAndRestoreWithDeletion() throws Exception {
-        if (!hasBackupTransport(LOCAL_BACKUP_COMPONENT)) {
+        if (!mHasFeature) {
             Log.i(TAG, "skipping BlockedNumberBackupRestoreTest");
+            return;
         }
 
         Log.i(TAG, "Adding blocked numbers.");
@@ -108,7 +110,6 @@
 
         Log.i(TAG, "Running backup.");
         runBackup();
-        Thread.sleep(BACKUP_TIMEOUT_MILLIS);
 
         Log.i(TAG, "Deleting blocked number.");
         deleteNumber("123456789");
@@ -116,7 +117,6 @@
 
         Log.i(TAG, "Running backup.");
         runBackup();
-        Thread.sleep(BACKUP_TIMEOUT_MILLIS);
 
         Log.i(TAG, "Clearing blocked numbers.");
         clearBlockedNumbers();
@@ -124,10 +124,14 @@
 
         Log.i(TAG, "Restoring blocked numbers.");
         runRestore();
-        Thread.sleep(BACKUP_TIMEOUT_MILLIS);
         verifyBlockedNumbers("223456789", "323456789");
     }
 
+    private boolean isFeatureSupported() throws Exception {
+        return ProviderTestUtils.hasBackupTransport(LOCAL_BACKUP_COMPONENT, mUiAutomation)
+                && mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+    }
+
     private void insertBlockedNumber(String number) {
         ContentValues cv = new ContentValues();
         cv.put(BlockedNumberContract.BlockedNumbers.COLUMN_ORIGINAL_NUMBER, number);
@@ -156,45 +160,16 @@
         mContentResolver.delete(BlockedNumberContract.BlockedNumbers.CONTENT_URI, null, null);
     }
 
-    private boolean hasBackupTransport(String transport) throws Exception {
-        String output = BlockedNumberTestUtils.executeShellCommand(
-                getInstrumentation().getUiAutomation(), "bmgr list transports");
-        for (String t : output.split(" ")) {
-            if ("*".equals(t)) {
-                // skip the current selection marker.
-                continue;
-            } else if (Objects.equals(transport, t)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private String setBackupTransport(String transport) throws Exception {
-        String output = exec("bmgr transport " + transport);
-        Pattern pattern = Pattern.compile("\\(formerly (.*)\\)$");
-        Matcher matcher = pattern.matcher(output);
-        if (matcher.find()) {
-            return matcher.group(1);
-        } else {
-            throw new Exception("non-parsable output setting bmgr transport: " + output);
-        }
-    }
-
     private void runBackup() throws Exception {
-        exec("bmgr backupnow " + BLOCKED_NUMBERS_PROVIDER_PACKAGE);
+        ProviderTestUtils.runBackup(BLOCKED_NUMBERS_PROVIDER_PACKAGE, mUiAutomation);
     }
 
     private void runRestore() throws Exception {
-        exec("bmgr restore " + BLOCKED_NUMBERS_PROVIDER_PACKAGE);
+        ProviderTestUtils.runRestore(BLOCKED_NUMBERS_PROVIDER_PACKAGE, mUiAutomation);
     }
 
     private void wipeBackup() throws Exception {
-        exec("bmgr wipe " + LOCAL_BACKUP_COMPONENT + " " + BLOCKED_NUMBERS_PROVIDER_PACKAGE);
-    }
-
-    private String exec(String command) throws Exception {
-        return BlockedNumberTestUtils.executeShellCommand(
-                getInstrumentation().getUiAutomation(), command);
+        ProviderTestUtils.wipeBackup(LOCAL_BACKUP_COMPONENT, BLOCKED_NUMBERS_PROVIDER_PACKAGE,
+                mUiAutomation);
     }
 }
diff --git a/tests/tests/provider/src/android/provider/cts/BlockedNumberContractTest.java b/tests/tests/provider/src/android/provider/cts/BlockedNumberContractTest.java
index fb49765..4ef28f4 100644
--- a/tests/tests/provider/src/android/provider/cts/BlockedNumberContractTest.java
+++ b/tests/tests/provider/src/android/provider/cts/BlockedNumberContractTest.java
@@ -347,7 +347,7 @@
     }
 
     private void setDefaultSmsApp(boolean setToSmsApp) throws Exception {
-        BlockedNumberTestUtils.setDefaultSmsApp(
+        ProviderTestUtils.setDefaultSmsApp(
                 setToSmsApp, mContext.getPackageName(), getInstrumentation().getUiAutomation());
     }
 }
diff --git a/tests/tests/provider/src/android/provider/cts/BlockedNumberTestUtils.java b/tests/tests/provider/src/android/provider/cts/BlockedNumberTestUtils.java
deleted file mode 100644
index b520542..0000000
--- a/tests/tests/provider/src/android/provider/cts/BlockedNumberTestUtils.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.provider.cts;
-
-import android.app.UiAutomation;
-import android.os.ParcelFileDescriptor;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-
-/**
- * Utility methods for blocked number cts tests.
- */
-public class BlockedNumberTestUtils {
-    static void setDefaultSmsApp(boolean setToSmsApp, String packageName, UiAutomation uiAutomation)
-            throws Exception {
-        String command = String.format(
-                "appops set %s WRITE_SMS %s", packageName, setToSmsApp ? "allow" : "default");
-        executeShellCommand(uiAutomation, command);
-    }
-
-    static String executeShellCommand(UiAutomation uiAutomation, String command)
-            throws IOException {
-        ParcelFileDescriptor pfd = uiAutomation.executeShellCommand(command.toString());
-        BufferedReader br = null;
-        try (InputStream in = new FileInputStream(pfd.getFileDescriptor());) {
-            br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
-            String str = null;
-            StringBuilder out = new StringBuilder();
-            while ((str = br.readLine()) != null) {
-                out.append(str);
-            }
-            return out.toString();
-        } finally {
-            if (br != null) {
-                br.close();
-            }
-        }
-    }
-}
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 3ccc61b..8fe95f5 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_FilesTest.java
@@ -278,16 +278,6 @@
         } catch (FileNotFoundException e) {
             // expected
         }
-        // now make the file world-readable
-        fos = mContext.openFileOutput("dummy.dat", Context.MODE_WORLD_READABLE);
-        fos.write(0);
-        fos.close();
-        try {
-            pfd = mResolver.openFileDescriptor(uri, "r");
-            pfd.close();
-        } catch (FileNotFoundException e) {
-            fail("failed to open file");
-        }
         path.delete();
 
         File sdfile = null;
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 8bf2516..1c00aac 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
@@ -32,6 +32,7 @@
 import android.provider.MediaStore.Images.Media;
 import android.provider.MediaStore.Images.Thumbnails;
 import android.test.InstrumentationTestCase;
+import android.util.Log;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -53,6 +54,8 @@
 
     private static final String TEST_DESCRIPTION3 = "test description3";
 
+    private static final String LOG_TAG = "MediaStore_Images_MediaTest";
+    
     private ArrayList<Uri> mRowsAdded;
 
     private Context mContext;
@@ -80,6 +83,16 @@
 
         mHelper = new FileCopyHelper(mContext);
         mRowsAdded = new ArrayList<Uri>();
+
+        File pics = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
+        if (!pics.exists()) {
+            Log.i(LOG_TAG, "Nonstandard test-environment: Pictures directory does not exist!");
+            pics.mkdirs();
+            if (!pics.exists()) {
+                Log.i(LOG_TAG, "Couldn't create Pictures directory, some tests may fail!");
+            }
+        }
+
     }
 
     public void testInsertImageWithImagePath() throws Exception {
diff --git a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
new file mode 100644
index 0000000..874a0a7
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.provider.cts;
+
+import android.app.UiAutomation;
+import android.os.ParcelFileDescriptor;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Utility methods for provider cts tests.
+ */
+public class ProviderTestUtils {
+
+    static final int BACKUP_TIMEOUT_MILLIS = 4000;
+
+    static void setDefaultSmsApp(boolean setToSmsApp, String packageName, UiAutomation uiAutomation)
+            throws Exception {
+        String command = String.format(
+                "appops set %s WRITE_SMS %s", packageName, setToSmsApp ? "allow" : "default");
+        executeShellCommand(command, uiAutomation);
+    }
+
+    static String executeShellCommand(String command, UiAutomation uiAutomation)
+            throws IOException {
+        ParcelFileDescriptor pfd = uiAutomation.executeShellCommand(command.toString());
+        BufferedReader br = null;
+        try (InputStream in = new FileInputStream(pfd.getFileDescriptor());) {
+            br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
+            String str = null;
+            StringBuilder out = new StringBuilder();
+            while ((str = br.readLine()) != null) {
+                out.append(str);
+            }
+            return out.toString();
+        } finally {
+            if (br != null) {
+                br.close();
+            }
+        }
+    }
+
+    static String setBackupTransport(String transport, UiAutomation uiAutomation) throws Exception {
+        String output = executeShellCommand("bmgr transport " + transport, uiAutomation);
+        Pattern pattern = Pattern.compile("\\(formerly (.*)\\)$");
+        Matcher matcher = pattern.matcher(output);
+        if (matcher.find()) {
+            return matcher.group(1);
+        } else {
+            throw new Exception("non-parsable output setting bmgr transport: " + output);
+        }
+    }
+
+    static boolean hasBackupTransport(String transport, UiAutomation uiAutomation)
+            throws Exception {
+        String output = executeShellCommand("bmgr list transports", uiAutomation);
+        for (String t : output.split(" ")) {
+            if ("*".equals(t)) {
+                // skip the current selection marker.
+                continue;
+            } else if (Objects.equals(transport, t)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static void runBackup(String packageName, UiAutomation uiAutomation) throws Exception {
+        executeShellCommand("bmgr backupnow " + packageName, uiAutomation);
+        Thread.sleep(BACKUP_TIMEOUT_MILLIS);
+    }
+
+    static void runRestore(String packageName, UiAutomation uiAutomation) throws Exception {
+        executeShellCommand("bmgr restore 1 " + packageName, uiAutomation);
+        Thread.sleep(BACKUP_TIMEOUT_MILLIS);
+    }
+
+    static void wipeBackup(String backupTransport, String packageName, UiAutomation uiAutomation)
+            throws Exception {
+        executeShellCommand("bmgr wipe " + backupTransport + " " + packageName, uiAutomation);
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java b/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java
new file mode 100644
index 0000000..f5e3033
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/SmsBackupRestoreTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.provider.cts;
+
+import com.google.android.mms.ContentType;
+import com.google.android.mms.pdu.CharacterSets;
+
+import android.app.UiAutomation;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.BaseColumns;
+import android.provider.Telephony;
+import android.util.Log;
+
+/**
+ * CTS tests for backup and restore of blocked numbers using local transport.
+ */
+// To run the tests in this file w/o running all the cts tests:
+// make cts
+// cts-tradefed
+// run cts -m CtsProviderTestCases --test android.provider.cts.SmsBackupRestoreTest
+public class SmsBackupRestoreTest extends TestCaseThatRunsIfTelephonyIsEnabled {
+    private static final String TAG = "SmsBackupRestoreTest";
+    private static final String LOCAL_BACKUP_COMPONENT =
+            "android/com.android.internal.backup.LocalTransport";
+    private static final String TELEPHONY_PROVIDER_PACKAGE = "com.android.providers.telephony";
+
+    private static final String[] smsAddressBody1 = new String[] {"+123" , "sms CTS text"};
+    private static final String[] smsAddressBody2 = new String[] {"+456" , "sms CTS text 2"};
+    private static final String[] mmsAddresses = new String[] {"+1223", "+43234234"};
+    private static final String mmsSubject = "MMS Subject CTS";
+    private static final String mmsBody = "MMS body CTS";
+
+    private static final String[] ID_PROJECTION = new String[] { BaseColumns._ID };
+    private static final String SMS_SELECTION = Telephony.Sms.ADDRESS + " = ? and "
+            + Telephony.Sms.BODY + " = ?";
+
+    private static final String MMS_SELECTION = Telephony.Mms.SUBJECT + " = ?";
+
+    private static final String[] MMS_PART_TEXT_PROJECTION = new String[]{Telephony.Mms.Part.TEXT};
+    private static final String MMS_PART_SELECTION = Telephony.Mms.Part.MSG_ID + " = ?";
+    private static final String MMS_PART_TEXT_SELECTION = Telephony.Mms.Part.CONTENT_TYPE + " = ?";
+    private static final String[] MMS_ADDR_PROJECTION = new String[] { Telephony.Mms.Addr.ADDRESS };
+    private static final String MMS_ADDR_SELECTION = Telephony.Mms.Addr.MSG_ID + " = ?";
+
+    private Context mContext;
+    private ContentResolver mContentResolver;
+    private UiAutomation mUiAutomation;
+    private String mOldTransport;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        // Wait for the UI Thread to become idle.
+        getInstrumentation().waitForIdleSync();
+        mContext = getInstrumentation().getContext();
+        mContentResolver = mContext.getContentResolver();
+        mUiAutomation = getInstrumentation().getUiAutomation();
+        ProviderTestUtils.setDefaultSmsApp(true, mContext.getPackageName(), mUiAutomation);
+        mOldTransport = ProviderTestUtils.setBackupTransport(LOCAL_BACKUP_COMPONENT, mUiAutomation);
+        clearMessages();
+        wipeBackup();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        wipeBackup();
+        clearMessages();
+        ProviderTestUtils.setBackupTransport(mOldTransport, mUiAutomation);
+        ProviderTestUtils.setDefaultSmsApp(false, mContext.getPackageName(), mUiAutomation);
+        super.tearDown();
+    }
+
+    private void clearMessages() {
+        mContentResolver.delete(Telephony.Sms.CONTENT_URI, SMS_SELECTION, smsAddressBody1);
+        mContentResolver.delete(Telephony.Sms.CONTENT_URI, SMS_SELECTION, smsAddressBody2);
+        try (Cursor mmsCursor =
+                     mContentResolver.query(Telephony.Mms.CONTENT_URI, ID_PROJECTION, MMS_SELECTION,
+                             new String[] {mmsSubject}, null)) {
+            if (mmsCursor != null && mmsCursor.moveToFirst()) {
+                final long mmsId = mmsCursor.getLong(0);
+                final Uri partUri = Telephony.Mms.CONTENT_URI.buildUpon()
+                        .appendPath(String.valueOf(mmsId)).appendPath("part").build();
+                mContentResolver.delete(partUri, MMS_PART_SELECTION,
+                        new String[]{String.valueOf(mmsId)});
+
+                final Uri addrUri = getMmsAddrUri(mmsId);
+                mContentResolver.delete(addrUri, MMS_ADDR_SELECTION,
+                        new String[]{String.valueOf(mmsId)});
+            }
+        }
+        mContentResolver.delete(Telephony.Mms.CONTENT_URI, MMS_SELECTION, new String[]{mmsSubject});
+    }
+
+    /**
+     * Test adds 2 SMS messages, 1 text-only MMS messages and 1 non-text-only, runs backup,
+     * deletes the messages from the provider, runs restore, check if the messages are in the
+     * provider (w/o non-text-only one).
+     * @throws Exception
+     */
+    public void testSmsBackupRestore() throws Exception {
+        if (!ProviderTestUtils.hasBackupTransport(LOCAL_BACKUP_COMPONENT, mUiAutomation)) {
+            Log.i(TAG, "skipping testSmsBackupRestore");
+        }
+
+        ContentValues smsContentValues[] = new ContentValues[] {
+                createSmsValues(smsAddressBody1),
+                createSmsValues(smsAddressBody2)};
+        Log.i(TAG, "Put 2 SMS into the provider");
+        mContentResolver.bulkInsert(Telephony.Sms.CONTENT_URI, smsContentValues);
+
+        Log.i(TAG, "Put 1 text MMS into the provider");
+        addMms(true /*isTextOnly*/, mmsBody, mmsSubject, mmsAddresses);
+        Log.i(TAG, "Put 1 non-text MMS into the provider");
+        addMms(false /*isTextOnly*/, mmsBody, mmsSubject, mmsAddresses);
+
+        Log.i(TAG, "Run backup");
+        ProviderTestUtils.runBackup(TELEPHONY_PROVIDER_PACKAGE, mUiAutomation);
+        Log.i(TAG, "Delete the messages from the provider");
+        clearMessages();
+        Log.i(TAG, "Run restore");
+        ProviderTestUtils.runRestore(TELEPHONY_PROVIDER_PACKAGE, mUiAutomation);
+
+        Log.i(TAG, "Check the providers for the messages");
+        assertEquals(1,
+                mContentResolver.delete(Telephony.Sms.CONTENT_URI, SMS_SELECTION, smsAddressBody1));
+        assertEquals(1,
+                mContentResolver.delete(Telephony.Sms.CONTENT_URI, SMS_SELECTION, smsAddressBody2));
+
+        try (Cursor mmsCursor = mContentResolver.query(Telephony.Mms.CONTENT_URI, ID_PROJECTION,
+                MMS_SELECTION, new String[] {mmsSubject}, null)) {
+            assertNotNull(mmsCursor);
+            assertEquals(1, mmsCursor.getCount());
+            mmsCursor.moveToFirst();
+            final long mmsId = mmsCursor.getLong(0);
+            final Uri partUri = Telephony.Mms.CONTENT_URI.buildUpon()
+                    .appendPath(String.valueOf(mmsId)).appendPath("part").build();
+            // Check the body.
+            try (Cursor partCursor = mContentResolver.query(partUri, MMS_PART_TEXT_PROJECTION,
+                    MMS_PART_TEXT_SELECTION, new String[]{ ContentType.TEXT_PLAIN }, null)) {
+                assertNotNull(partCursor);
+                assertEquals(1, partCursor.getCount());
+                assertTrue(partCursor.moveToFirst());
+                assertEquals(mmsBody, partCursor.getString(0));
+            }
+
+            // Check if there are 2 parts (smil and body).
+            assertEquals(2, mContentResolver.delete(partUri, MMS_PART_SELECTION,
+                    new String[]{String.valueOf(mmsId)}));
+
+            // Check addresses.
+            final Uri addrUri = getMmsAddrUri(mmsId);
+            try (Cursor addrCursor = mContentResolver.query(addrUri, MMS_ADDR_PROJECTION,
+                    MMS_ADDR_SELECTION, new String[]{String.valueOf(mmsId)}, null)) {
+                assertNotNull(addrCursor);
+                for (String addr : mmsAddresses) {
+                    addrCursor.moveToNext();
+                    assertEquals(addr, addrCursor.getString(0));
+                }
+            }
+            assertEquals(mmsAddresses.length, mContentResolver.delete(addrUri, MMS_ADDR_SELECTION,
+                    new String[]{String.valueOf(mmsId)}));
+        }
+    }
+
+    private static Uri getMmsAddrUri(long mmsId) {
+        Uri.Builder builder = Telephony.Mms.CONTENT_URI.buildUpon();
+        builder.appendPath(String.valueOf(mmsId)).appendPath("addr");
+        return builder.build();
+    }
+
+    private void addMms(boolean isTextOnly, String body, String subject, String[] addresses) {
+        // Insert mms.
+        final ContentValues mmsValues = new ContentValues(2);
+        mmsValues.put(Telephony.Mms.TEXT_ONLY, isTextOnly ? 1 : 0);
+        mmsValues.put(Telephony.Mms.MESSAGE_TYPE, 128);
+        mmsValues.put(Telephony.Mms.SUBJECT, subject);
+        final Uri mmsUri = mContentResolver.insert(Telephony.Mms.CONTENT_URI, mmsValues);
+        assertNotNull(mmsUri);
+        final long mmsId = ContentUris.parseId(mmsUri);
+
+        final String srcName = String.format("text.%06d.txt", 0);
+        // Insert body part.
+        final Uri partUri = Telephony.Mms.CONTENT_URI.buildUpon()
+                .appendPath(String.valueOf(mmsId)).appendPath("part").build();
+
+        final ContentValues values = new ContentValues(8);
+        values.put(Telephony.Mms.Part.MSG_ID, mmsId);
+        values.put(Telephony.Mms.Part.SEQ, 0);
+        values.put(Telephony.Mms.Part.CONTENT_TYPE, ContentType.TEXT_PLAIN);
+        values.put(Telephony.Mms.Part.NAME, srcName);
+        values.put(Telephony.Mms.Part.CONTENT_ID, "<"+srcName+">");
+        values.put(Telephony.Mms.Part.CONTENT_LOCATION, srcName);
+        values.put(Telephony.Mms.Part.CHARSET, CharacterSets.DEFAULT_CHARSET);
+        if (!isTextOnly) {
+            body = body + " Non text-only";
+        }
+        values.put(Telephony.Mms.Part.TEXT, body);
+        mContentResolver.insert(partUri, values);
+
+        // Insert addresses.
+        final Uri addrUri = Uri.withAppendedPath(mmsUri, "addr");
+        for (int i = 0; i < addresses.length; ++i) {
+            ContentValues addrValues = new ContentValues(3);
+            addrValues.put(Telephony.Mms.Addr.TYPE, i);
+            addrValues.put(Telephony.Mms.Addr.CHARSET, CharacterSets.DEFAULT_CHARSET);
+            addrValues.put(Telephony.Mms.Addr.ADDRESS, addresses[i]);
+            addrValues.put(Telephony.Mms.Addr.MSG_ID, mmsId);
+            mContentResolver.insert(addrUri, addrValues);
+        }
+    }
+
+    private static ContentValues createSmsValues(String[] addressBody) {
+        ContentValues smsRow = new ContentValues();
+        smsRow.put(Telephony.Sms.ADDRESS, addressBody[0]);
+        smsRow.put(Telephony.Sms.BODY, addressBody[1]);
+        return smsRow;
+    }
+
+    private void wipeBackup() throws Exception {
+        ProviderTestUtils.wipeBackup(LOCAL_BACKUP_COMPONENT, TELEPHONY_PROVIDER_PACKAGE,
+                mUiAutomation);
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java b/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
index 82bb17f..bc13144 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/CoreMathVerifier.java
@@ -221,14 +221,31 @@
     static native float  convertDoubleToFloat(double x);
     static native double convertDoubleToDouble(double x);
 
+    static private Target.Floaty pi(Target t) {
+        return t.newFloaty(Math.PI);
+    }
+
     static private Target.Floaty pi32(Target t) {
         return t.new32((float) Math.PI);
     }
 
+    static private Target.Floaty any(Target t) {
+        return t.newFloaty(Double.NEGATIVE_INFINITY, Double.NaN, Double.POSITIVE_INFINITY);
+    }
+
     static private Target.Floaty any32(Target t) {
         return t.new32(Float.NEGATIVE_INFINITY, Float.NaN, Float.POSITIVE_INFINITY);
     }
 
+    static private Target.Floaty acos(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.acos(in.mid()),
+            Math.acos(in.min()),
+            Math.acos(in.max()));
+    }
+
+    // TODO Remove this function and similar variants that take a float parameter instead of double.
     static private Target.Floaty acos(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -237,6 +254,16 @@
             acos(in.max32()));
     }
 
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    static private Target.Floaty acosh(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            acosh((float) in.mid()),
+            acosh((float) in.min()),
+            acosh((float) in.max()));
+    }
+
     static private Target.Floaty acosh(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -245,10 +272,22 @@
             acosh(in.max32()));
     }
 
+    static private Target.Floaty acospi(double d, Target t) {
+        return t.divide(acos(d, t), pi(t));
+    }
+
     static private Target.Floaty acospi(float f, Target t) {
         return t.divide(acos(f, t), pi32(t));
     }
 
+    static private Target.Floaty asin(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.asin(in.mid()),
+            Math.asin(in.min()),
+            Math.asin(in.max()));
+    }
+
     static private Target.Floaty asin(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -257,6 +296,16 @@
             asin(in.max32()));
     }
 
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    static private Target.Floaty asinh(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            asinh((float) in.mid()),
+            asinh((float) in.min()),
+            asinh((float) in.max()));
+    }
+
     static private Target.Floaty asinh(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -265,10 +314,22 @@
             asinh(in.max32()));
     }
 
+    static private Target.Floaty asinpi(double d, Target t) {
+        return t.divide(asin(d, t), pi(t));
+    }
+
     static private Target.Floaty asinpi(float f, Target t) {
         return t.divide(asin(f, t), pi32(t));
     }
 
+    static private Target.Floaty atan(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.atan(in.mid()),
+            Math.atan(in.min()),
+            Math.atan(in.max()));
+    }
+
     static private Target.Floaty atan(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -277,6 +338,16 @@
             atan(in.max32()));
     }
 
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    static private Target.Floaty atanh(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            atanh((float) in.mid()),
+            atanh((float) in.min()),
+            atanh((float) in.max()));
+    }
+
     static private Target.Floaty atanh(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -285,10 +356,25 @@
             atanh(in.max32()));
     }
 
+    static private Target.Floaty atanpi(double d, Target t) {
+        return t.divide(atan(d, t), pi(t));
+    }
+
     static private Target.Floaty atanpi(float f, Target t) {
         return t.divide(atan(f, t), pi32(t));
     }
 
+    static private Target.Floaty atan2(double y, double x, Target t) {
+        Target.Floaty numerator = t.newFloaty(y);
+        Target.Floaty denominator = t.newFloaty(x);
+        return t.newFloaty(
+            Math.atan2(numerator.mid(), denominator.mid()),
+            Math.atan2(numerator.min(), denominator.min()),
+            Math.atan2(numerator.min(), denominator.max()),
+            Math.atan2(numerator.max(), denominator.min()),
+            Math.atan2(numerator.max(), denominator.max()));
+    }
+
     static private Target.Floaty atan2(float y, float x, Target t) {
         Target.Floaty numerator = t.new32(y);
         Target.Floaty denominator = t.new32(x);
@@ -300,10 +386,22 @@
             atan2(numerator.max32(), denominator.max32()));
     }
 
+    static private Target.Floaty atan2pi(double y, double x, Target t) {
+        return t.divide(atan2(y, x, t), pi(t));
+    }
+
     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(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.cbrt(in.mid()),
+            Math.cbrt(in.min()),
+            Math.cbrt(in.max()));
+    }
+
     static private Target.Floaty cbrt(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -312,12 +410,20 @@
             cbrt(in.max32()));
     }
 
+    static private Target.Floaty clamp(double value, double minValue, double maxValue, Target t) {
+        return t.newFloaty(Math.min(maxValue, Math.max(minValue, value)));
+    }
+
+    static private Target.Floaty copysign(double magnitude, double sign, Target t) {
+        return t.newFloaty(Math.copySign(magnitude, sign));
+    }
+
     static private Target.Floaty cos(double d, Target t) {
         Target.Floaty in = t.newFloaty(d);
         return t.newFloaty(
-                   Math.cos(in.mid()),
-                   Math.cos(in.min()),
-                   Math.cos(in.max()));
+            Math.cos(in.mid()),
+            Math.cos(in.min()),
+            Math.cos(in.max()));
     }
 
     static private Target.Floaty cos(float f, Target t) {
@@ -328,6 +434,14 @@
             cos(in.max32()));
     }
 
+    static private Target.Floaty cosh(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.cosh(in.mid()),
+            Math.cosh(in.min()),
+            Math.cosh(in.max()));
+    }
+
     static private Target.Floaty cosh(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -336,6 +450,14 @@
             cosh(in.max32()));
     }
 
+    static private Target.Floaty cospi(double d, Target t) {
+        Target.Floaty in = t.multiply(t.newFloaty(d), pi(t));
+        return t.newFloaty(
+            Math.cos(in.mid()),
+            Math.cos(in.min()),
+            Math.cos(in.max()));
+    }
+
     static private Target.Floaty cospi(float f, Target t) {
         Target.Floaty in = t.multiply(t.new32(f), pi32(t));
         return t.new32(
@@ -376,6 +498,19 @@
         }
     }
 
+    static private Target.Floaty divide(double left, double right, Target t) {
+        Target.Floaty lFloaty = t.newFloaty(left);
+        Target.Floaty rFloaty = t.newFloaty(right);
+        return t.divide(lFloaty, rFloaty);
+    }
+
+    // Convert a double-precision radian value to degrees.
+    static private Target.Floaty degrees(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        Target.Floaty k = t.newFloaty(180. / Math.PI);
+        return t.multiply(in, k);
+    }
+
     // Returns the distance between two points (in double-precision) in n-dimensional space.
     static private Target.Floaty distance(double[] point1, double[] point2, Target t) {
         Target.Floaty sum = t.newFloaty(0.f);
@@ -398,6 +533,36 @@
         return d;
     }
 
+    // Computes the error function for a double-precision input.
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    static private Target.Floaty erf(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            erf((float) in.mid()),
+            erf((float) in.min()),
+            erf((float) in.max()));
+    }
+
+    // Computes the complementary error function for a double-precision input.
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    static private Target.Floaty erfc(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            erfc((float) in.mid()),
+            erfc((float) in.min()),
+            erfc((float) in.max()));
+    }
+
+    static private Target.Floaty exp(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.exp(in.mid()),
+            Math.exp(in.min()),
+            Math.exp(in.max()));
+    }
+
     static private Target.Floaty exp(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -406,6 +571,16 @@
             exp(in.max32()));
     }
 
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    static private Target.Floaty exp10(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            exp10((float) in.mid()),
+            exp10((float) in.min()),
+            exp10((float) in.max()));
+    }
+
     static private Target.Floaty exp10(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -414,6 +589,16 @@
             exp10(in.max32()));
     }
 
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    static private Target.Floaty exp2(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            exp2((float) in.mid()),
+            exp2((float) in.min()),
+            exp2((float) in.max()));
+    }
+
     static private Target.Floaty exp2(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -422,6 +607,14 @@
             exp2(in.max32()));
     }
 
+    static private Target.Floaty expm1(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.expm1(in.mid()),
+            Math.expm1(in.min()),
+            Math.expm1(in.max()));
+    }
+
     static private Target.Floaty expm1(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -430,6 +623,24 @@
             expm1(in.max32()));
     }
 
+    static private Target.Floaty fabs(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.abs(in.mid()),
+            Math.abs(in.min()),
+            Math.abs(in.max()));
+    }
+
+    static private Target.Floaty fdim(double a, double b, Target t) {
+        Target.Floaty inA = t.newFloaty(a);
+        Target.Floaty inB = t.newFloaty(b);
+        Target.Floaty r = t.subtract(inA, inB);
+        return t.newFloaty(
+            Math.max(0., r.mid()),
+            Math.max(0., r.min()),
+            Math.max(0., r.max()));
+    }
+
     static private Target.Floaty floor(double d, Target t) {
         Target.Floaty in = t.newFloaty(d);
         return t.newFloaty(
@@ -438,6 +649,52 @@
                     Math.floor(in.max()));
     }
 
+    static private Target.Floaty fma(double m1, double m2, double offset, Target t) {
+        Target.Floaty inM1 = t.newFloaty(m1);
+        Target.Floaty inM2 = t.newFloaty(m2);
+        Target.Floaty inOffset = t.newFloaty(offset);
+
+        return t.add(t.multiply(inM1, inM2), inOffset);
+    }
+
+    static private Target.Floaty fmax(double a, double b, Target t) {
+        return t.newFloaty(Math.max(a, b));
+    }
+
+    static private Target.Floaty fmin(double a, double b, Target t) {
+        return t.newFloaty(Math.min(a, b));
+    }
+
+    static private Target.Floaty fmod(double numerator, double denominator, Target t) {
+        Target.Floaty inNumerator = t.newFloaty(numerator);
+        Target.Floaty inDenominator = t.newFloaty(denominator);
+        return t.newFloaty(
+            numerator % denominator,
+            inNumerator.min() % inDenominator.min(),
+            inNumerator.min() % inDenominator.max(),
+            inNumerator.max() % inDenominator.min(),
+            inNumerator.max() % inDenominator.max());
+    }
+
+    // Compute the fractional part of a double value and returns a result that is at most
+    // 'fractUpperBound'.
+    static private Target.Floaty fract(double d, Target t, double fractUpperBound) {
+        return t.newFloaty(Math.min(
+            d - Math.floor(d),
+            fractUpperBound));
+    }
+
+    static private Target.Floaty hypot(double x, double y, Target t) {
+        Target.Floaty inX = t.newFloaty(x);
+        Target.Floaty inY = t.newFloaty(y);
+        return t.newFloaty(
+            Math.hypot(inX.mid(), inY.mid()),
+            Math.hypot(inX.min(), inY.min()),
+            Math.hypot(inX.min(), inY.max()),
+            Math.hypot(inX.max(), inY.min()),
+            Math.hypot(inX.max(), inY.max()));
+    }
+
     static private Target.Floaty hypot(float x, float y, Target t) {
         Target.Floaty inX = t.new32(x);
         Target.Floaty inY = t.new32(y);
@@ -470,6 +727,14 @@
         return l;
     }
 
+    static private Target.Floaty log(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.log(in.mid()),
+            Math.log(in.min()),
+            Math.log(in.max()));
+    }
+
     static private Target.Floaty log(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -478,6 +743,14 @@
             log(in.max32()));
     }
 
+    static private Target.Floaty log10(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.log10(in.mid()),
+            Math.log10(in.min()),
+            Math.log10(in.max()));
+    }
+
     static private Target.Floaty log10(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -486,6 +759,14 @@
             log10(in.max32()));
     }
 
+    static private Target.Floaty log1p(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.log1p(in.mid()),
+            Math.log1p(in.min()),
+            Math.log1p(in.max()));
+    }
+
     static private Target.Floaty log1p(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -494,6 +775,16 @@
             log1p(in.max32()));
     }
 
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    static private Target.Floaty log2(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            log2((float) in.mid()),
+            log2((float) in.min()),
+            log2((float) in.max()));
+    }
+
     static private Target.Floaty log2(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -502,6 +793,38 @@
             log2(in.max32()));
     }
 
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    static private Target.Floaty logb(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            logb((float) in.mid()),
+            logb((float) in.min()),
+            logb((float) in.max()));
+    }
+
+    static private Target.Floaty mad(double m1, double m2, double offset, Target t) {
+        Target.Floaty ab = t.multiply(t.newFloaty(m1), t.newFloaty(m2));
+        return t.add(ab, t.newFloaty(offset));
+    }
+
+    static private Target.Floaty max(double a, double b, Target t) {
+        return t.newFloaty(Math.max(a, b));
+    }
+
+    static private Target.Floaty min(double a, double b, Target t) {
+        return t.newFloaty(Math.min(a, b));
+    }
+
+    static private Target.Floaty mix(double start, double stop, double fraction, Target t) {
+        Target.Floaty inStart = t.newFloaty(start);
+        Target.Floaty inStop = t.newFloaty(stop);
+        Target.Floaty inFraction = t.newFloaty(fraction);
+
+        Target.Floaty diff = t.subtract(inStop, inStart);
+        return t.add(inStart, t.multiply(diff, inFraction));
+    }
+
     // Normalizes the double-precision n-dimensional vector, i.e. makes it length 1.
     static private void normalize(double[] in, Target.Floaty[] out, Target t) {
         Target.Floaty l = length(in, t);
@@ -526,6 +849,17 @@
         }
     }
 
+    static private Target.Floaty pow(double x, double y, Target t) {
+        Target.Floaty base = t.newFloaty(x);
+        Target.Floaty exponent = t.newFloaty(y);
+        return t.newFloaty(
+            Math.pow(base.mid(), exponent.mid()),
+            Math.pow(base.min(), exponent.min()),
+            Math.pow(base.min(), exponent.max()),
+            Math.pow(base.max(), exponent.min()),
+            Math.pow(base.max(), exponent.max()));
+    }
+
     static private Target.Floaty powr(float x, float y, Target t) {
         Target.Floaty base = t.new32(x);
         Target.Floaty exponent = t.new32(y);
@@ -537,11 +871,30 @@
             pow(base.max32(), exponent.max32()));
     }
 
+    static private Target.Floaty radians(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        Target.Floaty k = t.newFloaty(Math.PI / 180);
+        return t.multiply(in, k);
+    }
+
+    static private Target.Floaty recip(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.divide(t.newFloaty(1.), in);
+    }
+
     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 rint(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.rint(in.mid()),
+            Math.rint(in.min()),
+            Math.rint(in.max()));
+    }
+
     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
@@ -564,6 +917,19 @@
         }
     }
 
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    //
+    // Also, use native round() instead of Math.round() as the latter has different rounding
+    // behavior in case of ties.
+    static private Target.Floaty round(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            round((float) in.mid()),
+            round((float) in.min()),
+            round((float) in.max()));
+    }
+
     static private Target.Floaty rsqrt(double d, Target t) {
         Target.Floaty in = t.newFloaty(d);
         return t.divide(t.newFloaty(1.), t.sqrt(in));
@@ -574,6 +940,14 @@
         return t.divide(t.new32(1.f), t.sqrt(in));
     }
 
+    static private Target.Floaty sin(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.sin(in.mid()),
+            Math.sin(in.min()),
+            Math.sin(in.max()));
+    }
+
     static private Target.Floaty sin(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -582,6 +956,14 @@
             sin(in.max32()));
     }
 
+    static private Target.Floaty sinh(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.sinh(in.mid()),
+            Math.sinh(in.min()),
+            Math.sinh(in.max()));
+    }
+
     static private Target.Floaty sinh(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -590,6 +972,14 @@
             sinh(in.max32()));
     }
 
+    static private Target.Floaty sinpi(double d, Target t) {
+        Target.Floaty in = t.multiply(t.newFloaty(d), pi(t));
+        return t.newFloaty(
+            Math.sin(in.mid()),
+            Math.sin(in.min()),
+            Math.sin(in.max()));
+    }
+
     static private Target.Floaty sinpi(float f, Target t) {
         Target.Floaty in = t.multiply(t.new32(f), pi32(t));
         return t.new32(
@@ -598,25 +988,56 @@
             sin(in.max32()));
     }
 
+    static private Target.Floaty sqrt(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.sqrt(in);
+    }
+
     static private Target.Floaty sqrt(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.sqrt(in);
     }
 
+    static private Target.Floaty step(double v, double edge, Target t) {
+        return t.newFloaty(v < edge ? 0.f : 1.f);
+    }
+
+    static private Target.Floaty tan(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        double min = Math.tan(in.min());
+        double max = Math.tan(in.max());
+        /* If difference between in.max() and in.min() is larger than PI or if the tan of the min is
+         * greater than that of the max, we spanned a discontinuity.
+         */
+        if (in.max() - in.min() > Math.PI || min > max) {
+            return any(t);
+        } else {
+            return t.newFloaty(Math.tan(d), min, max);
+        }
+    }
+
     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 difference between in.max() and in.min() is larger than PI or if the tan of the min is
+         * greater than that of the max, we spanned a discontinuity.
          */
-        if (min > max) {
+        if (in.max() - in.min() > Math.PI || min > max) {
             return any32(t);
         } else {
             return t.new32(tan(f), min, max);
         }
     }
 
+    static private Target.Floaty tanh(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            Math.tanh(in.mid()),
+            Math.tanh(in.min()),
+            Math.tanh(in.max()));
+    }
+
     static private Target.Floaty tanh(float f, Target t) {
         Target.Floaty in = t.new32(f);
         return t.new32(
@@ -625,20 +1046,55 @@
             tanh(in.max32()));
     }
 
+    static private Target.Floaty tanpi(double d, Target t) {
+        Target.Floaty in = t.multiply(t.newFloaty(d), pi(t));
+        double min = Math.tan(in.min());
+        double max = Math.tan(in.max());
+
+        /* If difference between in.max() and in.min() is larger than PI or if the tan of the min is
+         * greater than that of the max, we spanned a discontinuity.
+         */
+        if (in.max() - in.min() > Math.PI || min > max) {
+            return any(t);
+        } else {
+            return t.newFloaty(Math.tan(in.mid()), min, max);
+        }
+    }
+
     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 difference between in.max() and in.min() is larger than PI or if the tan of the min is
+         * greater than that of the max, we spanned a discontinuity.
          */
-        if (min > max) {
+        if (in.max() - in.min() > Math.PI || min > max) {
             return any32(t);
         } else {
             return t.new32(tan(in.mid32()), min, max);
         }
     }
 
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    static private Target.Floaty tgamma(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            tgamma((float) in.mid()),
+            tgamma((float) in.min()),
+            tgamma((float) in.max()));
+    }
+
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    static private Target.Floaty trunc(double d, Target t) {
+        Target.Floaty in = t.newFloaty(d);
+        return t.newFloaty(
+            trunc((float) in.mid()),
+            trunc((float) in.min()),
+            trunc((float) in.max()));
+    }
+
     static public void computeAbs(TestAbs.ArgumentsCharUchar args) {
         args.out = (byte)Math.abs(args.inV);
     }
@@ -651,66 +1107,135 @@
         args.out = Math.abs(args.inV);
     }
 
+    static public void computeAcos(TestAcos.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = acos(args.inVDouble, t);
+    }
+
     static public void computeAcos(TestAcos.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(4, 128);
         args.out = acos(args.inV, t);
     }
 
+    static public void computeAcosh(TestAcosh.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = acosh(args.inVDouble, t);
+    }
+
     static public void computeAcosh(TestAcosh.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(4, 128);
         args.out = acosh(args.inV, t);
     }
 
+    static public void computeAcospi(TestAcospi.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = acospi(args.inVDouble, t);
+    }
+
     static public void computeAcospi(TestAcospi.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(5, 128);
         args.out = acospi(args.inV, t);
     }
 
+    static public void computeAsin(TestAsin.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = asin(args.inVDouble, t);
+    }
+
     static public void computeAsin(TestAsin.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(4, 128);
         args.out = asin(args.inV, t);
     }
 
+    static public void computeAsinh(TestAsinh.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = asinh(args.inVDouble, t);
+    }
+
     static public void computeAsinh(TestAsinh.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(4, 128);
         args.out = asinh(args.inV, t);
     }
 
+    static public void computeAsinpi(TestAsinpi.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = asinpi(args.inVDouble, t);
+    }
+
     static public void computeAsinpi(TestAsinpi.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(5, 128);
         args.out = asinpi(args.inV, t);
     }
 
+    static public void computeAtan(TestAtan.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = atan(args.inVDouble, t);
+    }
+
     static public void computeAtan(TestAtan.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(5, 128);
         args.out = atan(args.inV, t);
     }
 
+    static public void computeAtanh(TestAtanh.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = atanh(args.inVDouble, t);
+    }
+
     static public void computeAtanh(TestAtanh.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(5, 128);
         args.out = atanh(args.inV, t);
     }
 
+    static public void computeAtanpi(TestAtanpi.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = atanpi(args.inVDouble, t);
+    }
+
     static public void computeAtanpi(TestAtanpi.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(5, 128);
         args.out = atanpi(args.inV, t);
     }
 
+    static public void computeAtan2(TestAtan2.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(6, 6);
+        args.out = atan2(args.inNumeratorDouble, args.inDenominatorDouble, t);
+    }
+
     static public void computeAtan2(TestAtan2.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(6, 128);
         args.out = atan2(args.inNumerator, args.inDenominator, t);
     }
 
+    static public void computeAtan2pi(TestAtan2pi.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(6, 6);
+        args.out = atan2pi(args.inNumeratorDouble, args.inDenominatorDouble, t);
+    }
+
     static public void computeAtan2pi(TestAtan2pi.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(6, 128);
         args.out = atan2pi(args.inNumerator, args.inDenominator, t);
     }
 
+    static public void computeCbrt(TestCbrt.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(2, 2);
+        args.out = cbrt(args.inVDouble, t);
+    }
+
     static public void computeCbrt(TestCbrt.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(2, 128);
         args.out = cbrt(args.inV, t);
     }
 
+    static public void computeCeil(TestCeil.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        Target.Floaty in = t.newFloaty(args.inVDouble);
+        args.out = t.newFloaty(
+            Math.ceil(in.mid()),
+            Math.ceil(in.min()),
+            Math.ceil(in.max()));
+    }
+
     static public void computeCeil(TestCeil.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(0, 1);
         Target.Floaty in = t.new32(args.inV);
@@ -744,6 +1269,11 @@
         args.out = minU32(args.inMaxValue, maxU32(args.inValue, args.inMinValue));
     }
 
+    static public void computeClamp(TestClamp.ArgumentsHalfHalfHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = clamp(args.inValueDouble, args.inMinValueDouble, args.inMaxValueDouble, t);
+    }
+
     static public void computeClamp(TestClamp.ArgumentsFloatFloatFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         args.out = t.new32(Math.min(args.inMaxValue,
@@ -809,6 +1339,10 @@
     static public void computeConvert(TestConvert.ArgumentsCharUlong args) {
         args.out = convertCharToUlong(args.inV);
     }
+    static public void computeConvert(TestConvert.ArgumentsCharHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = t.newFloaty(convertCharToDouble(args.inV));
+    }
     static public void computeConvert(TestConvert.ArgumentsCharFloat args, Target t) {
         t.setPrecision(0, 0);
         args.out = t.new32(convertCharToFloat(args.inV));
@@ -842,6 +1376,10 @@
     static public void computeConvert(TestConvert.ArgumentsUcharUlong args) {
         args.out = convertUcharToUlong(args.inV);
     }
+    static public void computeConvert(TestConvert.ArgumentsUcharHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = t.newFloaty(convertUcharToDouble(args.inV));
+    }
     static public void computeConvert(TestConvert.ArgumentsUcharFloat args, Target t) {
         t.setPrecision(0, 0);
         args.out = t.new32(convertUcharToFloat(args.inV));
@@ -875,6 +1413,10 @@
     static public void computeConvert(TestConvert.ArgumentsShortUlong args) {
         args.out = convertShortToUlong(args.inV);
     }
+    static public void computeConvert(TestConvert.ArgumentsShortHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = t.newFloaty(convertShortToDouble(args.inV));
+    }
     static public void computeConvert(TestConvert.ArgumentsShortFloat args, Target t) {
         t.setPrecision(0, 0);
         args.out = t.new32(convertShortToFloat(args.inV));
@@ -908,6 +1450,10 @@
     static public void computeConvert(TestConvert.ArgumentsUshortUlong args) {
         args.out = convertUshortToUlong(args.inV);
     }
+    static public void computeConvert(TestConvert.ArgumentsUshortHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = t.newFloaty(convertUshortToDouble(args.inV));
+    }
     static public void computeConvert(TestConvert.ArgumentsUshortFloat args, Target t) {
         t.setPrecision(0, 0);
         args.out = t.new32(convertUshortToFloat(args.inV));
@@ -941,6 +1487,10 @@
     static public void computeConvert(TestConvert.ArgumentsIntUlong args) {
         args.out = convertIntToUlong(args.inV);
     }
+    static public void computeConvert(TestConvert.ArgumentsIntHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = t.newFloaty(convertIntToDouble(args.inV));
+    }
     static public void computeConvert(TestConvert.ArgumentsIntFloat args, Target t) {
         t.setPrecision(1, 1);
         args.out = t.new32(convertIntToFloat(args.inV));
@@ -974,6 +1524,10 @@
     static public void computeConvert(TestConvert.ArgumentsUintUlong args) {
         args.out = convertUintToUlong(args.inV);
     }
+    static public void computeConvert(TestConvert.ArgumentsUintHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = t.newFloaty(convertUintToDouble(args.inV));
+    }
     static public void computeConvert(TestConvert.ArgumentsUintFloat args, Target t) {
         t.setPrecision(1, 1);
         args.out = t.new32(convertUintToFloat(args.inV));
@@ -1007,6 +1561,10 @@
     static public void computeConvert(TestConvert.ArgumentsLongUlong args) {
         args.out = convertLongToUlong(args.inV);
     }
+    static public void computeConvert(TestConvert.ArgumentsLongHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = t.newFloaty(convertLongToDouble(args.inV));
+    }
     static public void computeConvert(TestConvert.ArgumentsLongFloat args, Target t) {
         t.setPrecision(1, 1);
         args.out = t.new32(convertLongToFloat(args.inV));
@@ -1040,6 +1598,10 @@
     static public void computeConvert(TestConvert.ArgumentsUlongUlong args) {
         args.out = convertUlongToUlong(args.inV);
     }
+    static public void computeConvert(TestConvert.ArgumentsUlongHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = t.newFloaty(convertUlongToDouble(args.inV));
+    }
     static public void computeConvert(TestConvert.ArgumentsUlongFloat args, Target t) {
         t.setPrecision(1, 1);
         args.out = t.new32(convertUlongToFloat(args.inV));
@@ -1049,6 +1611,43 @@
         args.out = t.new64(convertUlongToDouble(args.inV));
     }
 
+    static public void computeConvert(TestConvert.ArgumentsHalfChar args) {
+        args.out = convertDoubleToChar(args.inVDouble);
+    }
+    static public void computeConvert(TestConvert.ArgumentsHalfUchar args) {
+        args.out = convertDoubleToUchar(args.inVDouble);
+    }
+    static public void computeConvert(TestConvert.ArgumentsHalfShort args) {
+        args.out = convertDoubleToShort(args.inVDouble);
+    }
+    static public void computeConvert(TestConvert.ArgumentsHalfUshort args) {
+        args.out = convertDoubleToUshort(args.inVDouble);
+    }
+    static public void computeConvert(TestConvert.ArgumentsHalfInt args) {
+        args.out = convertDoubleToInt(args.inVDouble);
+    }
+    static public void computeConvert(TestConvert.ArgumentsHalfUint args) {
+        args.out = convertDoubleToUint(args.inVDouble);
+    }
+    static public void computeConvert(TestConvert.ArgumentsHalfLong args) {
+        args.out = convertDoubleToLong(args.inVDouble);
+    }
+    static public void computeConvert(TestConvert.ArgumentsHalfUlong args) {
+        args.out = convertDoubleToUlong(args.inVDouble);
+    }
+    static public void computeConvert(TestConvert.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = t.newFloaty(args.inVDouble);
+    }
+    static public void computeConvert(TestConvert.ArgumentsHalfFloat args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = t.newFloaty(convertDoubleToFloat(args.inVDouble));
+    }
+    static public void computeConvert(TestConvert.ArgumentsHalfDouble args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = t.newFloaty(args.inVDouble);
+    }
+
     static public void computeConvert(TestConvert.ArgumentsFloatChar args) {
         args.out = convertFloatToChar(args.inV);
     }
@@ -1073,6 +1672,10 @@
     static public void computeConvert(TestConvert.ArgumentsFloatUlong args) {
         args.out = convertFloatToUlong(args.inV);
     }
+    static public void computeConvert(TestConvert.ArgumentsFloatHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = t.newFloaty(args.inV);
+    }
     static public void computeConvert(TestConvert.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         args.out = t.new32(convertFloatToFloat(args.inV));
@@ -1106,6 +1709,10 @@
     static public void computeConvert(TestConvert.ArgumentsDoubleUlong args) {
         args.out = convertDoubleToUlong(args.inV);
     }
+    static public void computeConvert(TestConvert.ArgumentsDoubleHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = t.newFloaty(args.inV);
+    }
     static public void computeConvert(TestConvert.ArgumentsDoubleFloat args, Target t) {
         t.setPrecision(1, 1);
         args.out = t.new32(convertDoubleToFloat(args.inV));
@@ -1115,18 +1722,19 @@
         args.out = t.new64(convertDoubleToDouble(args.inV));
     }
 
+    static public void computeCopysign(TestCopysign.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = copysign(args.inMagnitudeValueDouble, args.inSignValueDouble, t);
+    }
+
     static public void computeCopysign(TestCopysign.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         args.out = t.new32(Math.copySign(args.inMagnitudeValue, args.inSignValue));
     }
 
     static public void computeCos(TestCos.ArgumentsHalfHalf args, Target t) {
-        t.setPrecision(4, 128);
-        Target.Floaty in = t.newFloaty(args.inVDouble);
-        args.out =  t.newFloaty(
-                        Math.cos(in.mid()),
-                        Math.cos(in.min()),
-                        Math.cos(in.max()));
+        t.setPrecision(4, 4);
+        args.out = cos(args.inVDouble, t);
     }
 
     static public void computeCos(TestCos.ArgumentsFloatFloat args, Target t) {
@@ -1134,11 +1742,21 @@
         args.out = cos(args.inV, t);
     }
 
+    static public void computeCosh(TestCosh.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = cosh(args.inVDouble, t);
+    }
+
     static public void computeCosh(TestCosh.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(4, 128);
         args.out = cosh(args.inV, t);
     }
 
+    static public void computeCospi(TestCospi.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = cospi(args.inVDouble, t);
+    }
+
     static public void computeCospi(TestCospi.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(4, 128);
         args.out = cospi(args.inV, t);
@@ -1154,6 +1772,11 @@
         cross(args.inLeftVector, args.inRightVector, args.out, t);
     }
 
+    static public void computeDegrees(TestDegrees.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = degrees(args.inVDouble, t);
+    }
+
     static public void computeDegrees(TestDegrees.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(3, 3);
         Target.Floaty in = t.new32(args.inV);
@@ -1217,6 +1840,11 @@
         args.out = sum;
     }
 
+    static public void computeErf(TestErf.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(16, 16);
+        args.out = erf(args.inVDouble, t);
+    }
+
     static public void computeErf(TestErf.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(16, 128);
         Target.Floaty in = t.new32(args.inV);
@@ -1226,6 +1854,11 @@
             erf(in.max32()));
     }
 
+    static public void computeErfc(TestErfc.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(16, 16);
+        args.out = erfc(args.inVDouble, t);
+    }
+
     static public void computeErfc(TestErfc.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(16, 128);
         Target.Floaty in = t.new32(args.inV);
@@ -1235,26 +1868,51 @@
             erfc(in.max32()));
     }
 
+    static public void computeExp(TestExp.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = exp(args.inVDouble, t);
+    }
+
     static public void computeExp(TestExp.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(3, 16);
         args.out = exp(args.inV, t);
     }
 
+    static public void computeExp10(TestExp10.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = exp10(args.inVDouble, t);
+    }
+
     static public void computeExp10(TestExp10.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(3, 32);
         args.out = exp10(args.inV, t);
     }
 
+    static public void computeExp2(TestExp2.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = exp2(args.inVDouble, t);
+    }
+
     static public void computeExp2(TestExp2.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(3, 16);
         args.out = exp2(args.inV, t);
     }
 
+    static public void computeExpm1(TestExpm1.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = expm1(args.inVDouble, t);
+    }
+
     static public void computeExpm1(TestExpm1.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(3, 16);
         args.out = expm1(args.inV, t);
     }
 
+    static public void computeFabs(TestFabs.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = fabs(args.inVDouble, t);
+    }
+
     static public void computeFabs(TestFabs.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         Target.Floaty in = t.new32(args.inV);
@@ -1296,6 +1954,11 @@
         normalize(args.inV, args.out, t);
     }
 
+    static public void computeFdim(TestFdim.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = fdim(args.inADouble, args.inBDouble, t);
+    }
+
     static public void computeFdim(TestFdim.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(1, 1);
         Target.Floaty inA = t.new32(args.inA);
@@ -1321,12 +1984,23 @@
             floor(in.max32()));
     }
 
+    static public void computeFma(TestFma.ArgumentsHalfHalfHalfHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = fma(args.inMultiplicand1Double, args.inMultiplicand2Double,
+            args.inOffsetDouble, t);
+    }
+
     static public void computeFma(TestFma.ArgumentsFloatFloatFloatFloat args, Target t) {
         t.setPrecision(1, 1);
         Target.Floaty ab = t.multiply(t.new32(args.inMultiplicand1), t.new32(args.inMultiplicand2));
         args.out = t.add(ab, t.new32(args.inOffset));
     }
 
+    static public void computeFmax(TestFmax.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = fmax(args.inADouble, args.inBDouble, t);
+    }
+
     static public void computeFmax(TestFmax.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         Target.Floaty a = t.new32(args.inA);
@@ -1339,6 +2013,11 @@
             Math.max(a.max32(), b.max32()));
     }
 
+    static public void computeFmin(TestFmin.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = fmin(args.inADouble, args.inBDouble, t);
+    }
+
     static public void computeFmin(TestFmin.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         Target.Floaty a = t.new32(args.inA);
@@ -1351,6 +2030,11 @@
             Math.min(a.max32(), b.max32()));
     }
 
+    static public void computeFmod(TestFmod.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = fmod(args.inNumeratorDouble, args.inDenominatorDouble, t);
+    }
+
     static public void computeFmod(TestFmod.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(1, 1);
         Target.Floaty numerator = t.new32(args.inNumerator);
@@ -1363,6 +2047,12 @@
             numerator.max32() % denominator.max32());
     }
 
+    static public void computeFract(TestFract.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = fract(args.inVDouble, t, 0.99951171875 /* max float16 smaller than 1.0 */);
+        args.outFloor = floor(args.inVDouble, t);
+    }
+
     static public void computeFract(TestFract.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(1, 1);
         float floor = floor(args.inV);
@@ -1371,6 +2061,11 @@
         args.out = t.new32(Math.min(args.inV - floor, 0x1.fffffep-1f));
     }
 
+    static public void computeFract(TestFract.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = fract(args.inVDouble, t, 0.99951171875 /* max float16 smaller than 1.0 */);
+    }
+
     static public void computeFract(TestFract.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(1, 1);
         float floor = floor(args.inV);
@@ -1400,6 +2095,11 @@
         args.out = sqrt(args.inV, t);
     }
 
+    static public void computeHypot(TestHypot.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = hypot(args.inADouble, args.inBDouble, t);
+    }
+
     static public void computeHypot(TestHypot.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(4, 4);
         args.out = hypot(args.inA, args.inB, t);
@@ -1499,6 +2199,11 @@
         return null;
     }
 
+    static public void computeLog(TestLog.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = log(args.inVDouble, t);
+    }
+
     // 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) {
@@ -1506,21 +2211,41 @@
         args.out = log(args.inV, t);
     }
 
+    static public void computeLog10(TestLog10.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = log10(args.inVDouble, t);
+    }
+
     static public void computeLog10(TestLog10.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(3, 16);
         args.out = log10(args.inV, t);
     }
 
+    static public void computeLog1p(TestLog1p.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(2, 2);
+        args.out = log1p(args.inVDouble, t);
+    }
+
     static public void computeLog1p(TestLog1p.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(2, 16);
         args.out = log1p(args.inV, t);
     }
 
+    static public void computeLog2(TestLog2.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = log2(args.inVDouble, t);
+    }
+
     static public void computeLog2(TestLog2.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(3, 128);
         args.out = log2(args.inV, t);
     }
 
+    static public void computeLogb(TestLogb.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = logb(args.inVDouble, t);
+    }
+
     static public void computeLogb(TestLogb.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         Target.Floaty in = t.new32(args.inV);
@@ -1530,6 +2255,11 @@
             logb(in.max32()));
     }
 
+    static public void computeMad(TestMad.ArgumentsHalfHalfHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = mad(args.inMultiplicand1Double, args.inMultiplicand2Double, args.inOffsetDouble, t);
+    }
+
     static public void computeMad(TestMad.ArgumentsFloatFloatFloatFloat args, Target t) {
         t.setPrecision(1, 4);
         Target.Floaty ab = t.multiply(t.new32(args.inMultiplicand1), t.new32(args.inMultiplicand2));
@@ -1568,6 +2298,11 @@
         args.out = maxU64(args.inA, args.inB);
     }
 
+    static public void computeMax(TestMax.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = max(args.inADouble, args.inBDouble, t);
+    }
+
     static public void computeMax(TestMax.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         Target.Floaty a = t.new32(args.inA);
@@ -1612,11 +2347,21 @@
         args.out = minU64(args.inA, args.inB);
     }
 
+    static public void computeMin(TestMin.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = min(args.inADouble, args.inBDouble, t);
+    }
+
     static public void computeMin(TestMin.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         args.out = t.new32(Math.min(args.inA, args.inB));
     }
 
+    static public void computeMix(TestMix.ArgumentsHalfHalfHalfHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = mix(args.inStartDouble, args.inStopDouble, args.inFractionDouble, t);
+    }
+
     static public void computeMix(TestMix.ArgumentsFloatFloatFloatFloat args, Target t) {
         t.setPrecision(1, 4);
         Target.Floaty start = t.new32(args.inStart);
@@ -1638,81 +2383,172 @@
         args.out = t.new32(Float.NaN);
     }
 
+    static public void computeNanHalf(TestNanHalf.ArgumentsHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = t.newFloaty(Double.NaN);
+    }
+
+    static public void computeNativeAcos(TestNativeAcos.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0); // extraAllowedError set in fw/rs/rs_math.spec and generated test files
+        args.out = acos(args.inVDouble, t);
+    }
+
     static public void computeNativeAcos(TestNativeAcos.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = acos(args.inV, t);
     }
 
+    static public void computeNativeAcosh(TestNativeAcosh.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = acosh(args.inVDouble, t);
+    }
+
     static public void computeNativeAcosh(TestNativeAcosh.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = acosh(args.inV, t);
     }
 
+    static public void computeNativeAcospi(TestNativeAcospi.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0); // extraAllowedError set in fw/rs/rs_math.spec and generated test files
+        args.out = acospi(args.inVDouble, t);
+    }
+
     static public void computeNativeAcospi(TestNativeAcospi.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = acospi(args.inV, t);
     }
 
+    static public void computeNativeAsin(TestNativeAsin.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0); // extraAllowedError set in fw/rs/rs_math.spec and generated test files
+        args.out = asin(args.inVDouble, t);
+    }
+
     static public void computeNativeAsin(TestNativeAsin.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = asin(args.inV, t);
     }
 
+    static public void computeNativeAsinh(TestNativeAsinh.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = asinh(args.inVDouble, t);
+    }
+
     static public void computeNativeAsinh(TestNativeAsinh.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = asinh(args.inV, t);
     }
 
+    static public void computeNativeAsinpi(TestNativeAsinpi.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0); // extraAllowedError set in fw/rs/rs_math.spec and generated test files
+        args.out = asinpi(args.inVDouble, t);
+    }
+
     static public void computeNativeAsinpi(TestNativeAsinpi.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = asinpi(args.inV, t);
     }
 
+    static public void computeNativeAtan(TestNativeAtan.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = atan(args.inVDouble, t);
+    }
+
     static public void computeNativeAtan(TestNativeAtan.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = atan(args.inV, t);
     }
 
+    static public void computeNativeAtanh(TestNativeAtanh.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = atanh(args.inVDouble, t);
+    }
+
     static public void computeNativeAtanh(TestNativeAtanh.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = atanh(args.inV, t);
     }
 
+    static public void computeNativeAtanpi(TestNativeAtanpi.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = atanpi(args.inVDouble, t);
+    }
+
     static public void computeNativeAtanpi(TestNativeAtanpi.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = atanpi(args.inV, t);
     }
 
+    static public void computeNativeAtan2(TestNativeAtan2.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = atan2(args.inNumeratorDouble, args.inDenominatorDouble, t);
+    }
+
     static public void computeNativeAtan2(TestNativeAtan2.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = atan2(args.inNumerator, args.inDenominator, t);
     }
 
+    static public void computeNativeAtan2pi(TestNativeAtan2pi.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = atan2pi(args.inNumeratorDouble, args.inDenominatorDouble, t);
+    }
+
     static public void computeNativeAtan2pi(TestNativeAtan2pi.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = atan2pi(args.inNumerator, args.inDenominator, t);
     }
 
+    static public void computeNativeCbrt(TestNativeCbrt.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(2, 2);
+        args.out = cbrt(args.inVDouble, t);
+    }
+
     static public void computeNativeCbrt(TestNativeCbrt.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = cbrt(args.inV, t);
     }
 
+    static public void computeNativeCos(TestNativeCos.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0); // extraAllowedError set in fw/rs/rs_math.spec and generated test files
+        args.out = cos(args.inVDouble, t);
+    }
+
     static public void computeNativeCos(TestNativeCos.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = cos(args.inV, t);
     }
 
+    static public void computeNativeCosh(TestNativeCosh.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = cosh(args.inVDouble, t);
+    }
+
     static public void computeNativeCosh(TestNativeCosh.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = cosh(args.inV, t);
     }
 
+    static public void computeNativeCospi(TestNativeCospi.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0); // extraAllowedError set in fw/rs/rs_math.spec and generated test files
+        args.out = cospi(args.inVDouble, t);
+    }
+
     static public void computeNativeCospi(TestNativeCospi.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = cospi(args.inV, t);
     }
 
+    static public void computeNativeDistance(TestNativeDistance.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = distance(new double[] {args.inLeftVectorDouble},
+                            new double[] {args.inRightVectorDouble}, t);
+    }
+
+    static public void computeNativeDistance(TestNativeDistance.ArgumentsHalfNHalfNHalf args, Target t) {
+        t.setPrecision(1, 1);
+        args.out = distance(args.inLeftVectorDouble, args.inRightVectorDouble, t);
+    }
+
     static public void computeNativeDistance(TestNativeDistance.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = distance(new float[]{args.inLeftVector}, new float[]{args.inRightVector}, t);
@@ -1723,32 +2559,82 @@
         args.out = distance(args.inLeftVector, args.inRightVector, t);
     }
 
+    static public void computeNativeDivide(TestNativeDivide.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = divide(args.inLeftVectorDouble, args.inRightVectorDouble, t);
+    }
+
     static public void computeNativeDivide(TestNativeDivide.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = t.divide(t.new32(args.inLeftVector), t.new32(args.inRightVector));
     }
 
+    static public void computeNativeExp(TestNativeExp.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = exp(args.inVDouble, t);
+    }
+
     static public void computeNativeExp(TestNativeExp.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = exp(args.inV, t);
     }
 
+    static public void computeNativeExp10(TestNativeExp10.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = exp10(args.inVDouble, t);
+    }
+
     static public void computeNativeExp10(TestNativeExp10.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = exp10(args.inV, t);
     }
 
+    static public void computeNativeExp2(TestNativeExp2.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = exp2(args.inVDouble, t);
+    }
+
     static public void computeNativeExp2(TestNativeExp2.ArgumentsFloatFloat args, Target t) {
         // TODO we would like to use NATIVE_PRECISION, NATIVE_PRECISION
         t.setPrecision(13000, 13000);
         args.out = exp2(args.inV, t);
     }
 
+    static public String verifyNativeExpm1(TestNativeExpm1.ArgumentsHalfHalf args, Target t) {
+        // Acceptable error for native_expm1 is:
+        //     < 2^-11 in [-Inf, 0.6]
+        //     3 ulp outside
+        double extraAllowedError = 0.;
+        int ulpFactor;
+        if (args.inVDouble < 0.6) {
+            ulpFactor = 0;
+            extraAllowedError = 0.00048828125; // 2^-11
+        } else {
+            ulpFactor = 3;
+        }
+        t.setPrecision(ulpFactor, ulpFactor);
+
+        Target.Floaty expectedOut = expm1(args.inVDouble, t);
+        if (!expectedOut.couldBe(args.outDouble, extraAllowedError)) {
+            StringBuilder message = new StringBuilder();
+            message.append("Ulp Factor: " + Integer.toString(ulpFactor) + "\n");
+            message.append("Extra allowed error: " + Double.toString(extraAllowedError) + "\n");
+            message.append("Expected output out: " + expectedOut.toString() + "\n");
+            return message.toString();
+        }
+        return null;
+    }
+
     static public void computeNativeExpm1(TestNativeExpm1.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = expm1(args.inV, t);
     }
 
+    static public void computeNativeHypot(TestNativeHypot.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = hypot(args.inADouble, args.inBDouble, t);
+    }
+
     static public void computeNativeHypot(TestNativeHypot.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = hypot(args.inA, args.inB, t);
@@ -1774,6 +2660,17 @@
         args.out = length(args.inV, t);
     }
 
+    static public void computeNativeLog(TestNativeLog.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        // http://b/27859722 Accept anything for zero.  Negative values don't get tested (see
+        // range() for this function in fw/rs/api/rs_math.spec.
+        if (Math.abs(args.inVDouble) < 1.e-20) {
+            args.out = any(t);
+        } else {
+            args.out = log(args.inVDouble, t);
+        }
+    }
+
     static public void computeNativeLog(TestNativeLog.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         // For very small values, allow anything.
@@ -1784,6 +2681,17 @@
         }
     }
 
+    static public void computeNativeLog10(TestNativeLog10.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        // http://b/27859722 Accept anything for zero.  Negative values don't get tested (see
+        // range() for this function in fw/rs/api/rs_math.spec.
+        if (Math.abs(args.inVDouble) < 1.e-20) {
+            args.out = any(t);
+        } else {
+            args.out = log10(args.inVDouble, t);
+        }
+    }
+
     static public void computeNativeLog10(TestNativeLog10.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         // For very small values, allow anything.
@@ -1794,11 +2702,27 @@
         }
     }
 
+    static public void computeNativeLog1p(TestNativeLog1p.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(2, 2);
+        args.out = log1p(args.inVDouble, t);
+    }
+
     static public void computeNativeLog1p(TestNativeLog1p.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = log1p(args.inV, t);
     }
 
+    static public void computeNativeLog2(TestNativeLog2.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        // http://b/27859722 Accept anything for zero.  Negative values don't get tested (see
+        // range() for this function in fw/rs/api/rs_math.spec.
+        if (Math.abs(args.inVDouble) < 1.e-20) {
+            args.out = any(t);
+        } else {
+            args.out = log2(args.inVDouble, t);
+        }
+    }
+
     static public void computeNativeLog2(TestNativeLog2.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         // For very small values, allow anything.
@@ -1833,6 +2757,17 @@
         normalize(args.inV, args.out, t);
     }
 
+    static public void computeNativePowr(TestNativePowr.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(16, 16);
+        // http://b/27859722 Accept anything for zero.  Negative values don't get tested (see
+        // range() for this function in fw/rs/api/rs_math.spec.
+        if (Math.abs(args.inBaseDouble) < 1.e-20) {
+            args.out = any(t);
+        } else {
+            args.out = pow(args.inBaseDouble, args.inExponentDouble, t);
+        }
+    }
+
     static public void computeNativePowr(TestNativePowr.ArgumentsFloatFloatFloat args, Target t) {
         // TODO we would like to use NATIVE_PRECISION, NATIVE_PRECISION
         t.setPrecision(32000, 32000);
@@ -1844,6 +2779,11 @@
         }
     }
 
+    static public void computeNativeRecip(TestNativeRecip.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = recip(args.inVDouble, t);
+    }
+
     static public void computeNativeRecip(TestNativeRecip.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = recip(args.inV, t);
@@ -1859,47 +2799,141 @@
         }
     }
 
+    static public void computeNativeRsqrt(TestNativeRsqrt.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(2, 2);
+        args.out = rsqrt(args.inVDouble, t);
+    }
+
     static public void computeNativeRsqrt(TestNativeRsqrt.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = rsqrt(args.inV, t);
     }
 
+    static public void computeNativeSin(TestNativeSin.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0); // extraAllowedError set in fw/rs/rs_math.spec and generated test files
+        args.out = sin(args.inVDouble, t);
+    }
+
     static public void computeNativeSin(TestNativeSin.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = sin(args.inV, t);
     }
 
+    static public void computeNativeSincos(TestNativeSincos.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(0, 0); // extraAllowedError set in fw/rs/rs_math.spec and generated test files
+        args.outCos = cos(args.inVDouble, t);
+        args.out = sin(args.inVDouble, t);
+    }
+
     static public void computeNativeSincos(TestNativeSincos.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.outCos = cos(args.inV, t);
         args.out = sin(args.inV, t);
     }
 
+    static public void computeNativeSinh(TestNativeSinh.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = sinh(args.inVDouble, t);
+    }
+
     static public void computeNativeSinh(TestNativeSinh.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = sinh(args.inV, t);
     }
 
+    static public void computeNativeSinpi(TestNativeSinpi.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0); // extraAllowedError set in fw/rs/rs_math.spec and generated test files
+        args.out = sinpi(args.inVDouble, t);
+    }
+
     static public void computeNativeSinpi(TestNativeSinpi.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = sinpi(args.inV, t);
     }
 
+    static public void computeNativeSqrt(TestNativeSqrt.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = sqrt(args.inVDouble, t);
+    }
+
     static public void computeNativeSqrt(TestNativeSqrt.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = sqrt(args.inV, t);
     }
 
+    static public String verifyNativeTan(TestNativeTan.ArgumentsHalfHalf args, Target t) {
+        // Precision for native_tan is as follows:
+        //     For integral n:
+        //         8 ulp in [(n-0.45) pi, (n+0.45) pi]
+        //         2048 ulp in [(n+0.45) pi, (n+0.55) pi]"
+
+        // Compute the fractional part of args.inVDouble / pi
+        double absoluteValueOverPi = Math.abs(args.inVDouble) / Math.PI;
+        double fract = absoluteValueOverPi - Math.floor(absoluteValueOverPi);
+
+        int ulpFactor;
+        if (0.45 <= fract && fract <= 0.55) {
+            ulpFactor = 2048;
+        } else {
+            ulpFactor = 8;
+        }
+        t.setPrecision(ulpFactor, ulpFactor);
+
+        Target.Floaty expectedOut = tan(args.inVDouble, t);
+        if (!expectedOut.couldBe(args.outDouble)) {
+            StringBuilder message = new StringBuilder();
+            message.append("Ulp Factor: " + Integer.toString(ulpFactor) + "\n");
+            message.append("Expected output out: " + expectedOut.toString() + "\n");
+            return message.toString();
+        }
+
+        return null;
+    }
+
     static public void computeNativeTan(TestNativeTan.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = tan(args.inV, t);
     }
 
+    static public void computeNativeTanh(TestNativeTanh.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = tanh(args.inVDouble, t);
+    }
+
     static public void computeNativeTanh(TestNativeTanh.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = tanh(args.inV, t);
     }
 
+    static public String verifyNativeTanpi(TestNativeTanpi.ArgumentsHalfHalf args, Target t) {
+        // Precision for native_tan is as follows:
+        //     For integral n:
+        //         8 ulp in [(n-0.45), (n+0.45)]
+        //         2048 ulp in [(n+0.45), (n+0.55)]"
+
+        // Compute the fractional part of args.inVDouble
+        double absoluteValue = Math.abs(args.inVDouble);
+        double fract = absoluteValue - Math.floor(absoluteValue);
+
+        int ulpFactor;
+        if (0.45 <= fract && fract <= 0.55) {
+            ulpFactor = 2048;
+        } else {
+            ulpFactor = 8;
+        }
+        t.setPrecision(ulpFactor, ulpFactor);
+
+        Target.Floaty expectedOut = tanpi(args.inVDouble, t);
+        if (!expectedOut.couldBe(args.outDouble)) {
+            StringBuilder message = new StringBuilder();
+            message.append("Ulp Factor: " + Integer.toString(ulpFactor) + "\n");
+            message.append("Expected output out: " + expectedOut.toString() + "\n");
+            return message.toString();
+        }
+
+        return null;
+    }
+
     static public void computeNativeTanpi(TestNativeTanpi.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(NATIVE_PRECISION, NATIVE_PRECISION);
         args.out = tanpi(args.inV, t);
@@ -1934,6 +2968,11 @@
         normalize(args.inV, args.out, t);
     }
 
+    static public void computePow(TestPow.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(16, 16);
+        args.out = pow(args.inBaseDouble, args.inExponentDouble, t);
+    }
+
     static public void computePow(TestPow.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(16, 128);
         Target.Floaty base = t.new32(args.inBase);
@@ -1946,6 +2985,11 @@
             pow(base.max32(), exponent.max32()));
     }
 
+    static public void computePown(TestPown.ArgumentsHalfIntHalf args, Target t) {
+        t.setPrecision(16, 16);
+        args.out = pow(args.inBaseDouble, (double) args.inExponent, t);
+    }
+
     static public void computePown(TestPown.ArgumentsFloatIntFloat args, Target t) {
         t.setPrecision(16, 128);
         Target.Floaty in = t.new32(args.inBase);
@@ -1959,11 +3003,21 @@
             (float) Math.pow(in.max32(), y));
     }
 
+    static public void computePowr(TestPowr.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(16, 16);
+        args.out = pow(args.inBaseDouble, args.inExponentDouble, t);
+    }
+
     static public void computePowr(TestPowr.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(16, 128);
         args.out = powr(args.inBase, args.inExponent, t);
     }
 
+    static public void computeRadians(TestRadians.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = radians(args.inVDouble, t);
+    }
+
     static public void computeRadians(TestRadians.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(3, 3);
         Target.Floaty in = t.new32(args.inV);
@@ -1971,6 +3025,15 @@
         args.out = t.multiply(in, k);
     }
 
+    // NOTE: This function delegates to the floating-point version in libm.  Need to switch to the
+    // double-precision version later.
+    static public void computeRemainder(TestRemainder.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        RemquoResult result = remquo((float) args.inNumeratorDouble,
+            (float) args.inDenominatorDouble);
+        args.out = t.newFloaty(result.remainder);
+    }
+
     static public void computeRemainder(TestRemainder.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         RemquoResult result = remquo(args.inNumerator, args.inDenominator);
@@ -2004,6 +3067,11 @@
         return null;
     }
 
+    static public void computeRint(TestRint.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = rint(args.inVDouble, t);
+    }
+
     static public void computeRint(TestRint.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         Target.Floaty in = t.new32(args.inV);
@@ -2018,6 +3086,11 @@
         args.out = rootn(args.inV, args.inN, t);
     }
 
+    static public void computeRound(TestRound.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = round(args.inVDouble, t);
+    }
+
     static public void computeRound(TestRound.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         Target.Floaty in = t.new32(args.inV);
@@ -2037,57 +3110,113 @@
         args.out = rsqrt(args.inV, t);
     }
 
+    static public void computeSign(TestSign.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = t.newFloaty(Math.signum(args.inVDouble));
+    }
+
     static public void computeSign(TestSign.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         args.out = t.new32(Math.signum(args.inV));
     }
 
+    static public void computeSin(TestSin.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = sin(args.inVDouble, t);
+    }
+
     static public void computeSin(TestSin.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(4, 128);
         args.out = sin(args.inV, t);
     }
 
+    static public void computeSincos(TestSincos.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(4, 128);
+        args.outCos = cos(args.inVDouble, t );
+        args.out = sin(args.inVDouble, t);
+    }
+
     static public void computeSincos(TestSincos.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(4, 128);
         args.outCos = cos(args.inV,t );
         args.out = sin(args.inV, t);
     }
 
+    static public void computeSinh(TestSinh.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = sinh(args.inVDouble, t);
+    }
+
     static public void computeSinh(TestSinh.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(4, 128);
         args.out = sinh(args.inV, t);
     }
 
+    static public void computeSinpi(TestSinpi.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = sinpi(args.inVDouble, t);
+    }
+
     static public void computeSinpi(TestSinpi.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(4, 128);
         args.out = sinpi(args.inV, t);
     }
 
+    static public void computeSqrt(TestSqrt.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(3, 3);
+        args.out = sqrt(args.inVDouble, t);
+    }
+
     static public void computeSqrt(TestSqrt.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(3, 3);
         args.out = sqrt(args.inV, t);
     }
 
+    static public void computeStep(TestStep.ArgumentsHalfHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = step(args.inVDouble, args.inEdgeDouble, t);
+    }
+
     static public void computeStep(TestStep.ArgumentsFloatFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         args.out = t.new32(args.inV < args.inEdge ? 0.f : 1.f);
     }
 
+    static public void computeTan(TestTan.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = tan(args.inVDouble, t);
+    }
+
     static public void computeTan(TestTan.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(5, 128);
         args.out = tan(args.inV, t);
     }
 
+    static public void computeTanh(TestTanh.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(5, 5);
+        args.out = tanh(args.inVDouble, t);
+    }
+
     static public void computeTanh(TestTanh.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(5, 128);
         args.out = tanh(args.inV, t);
     }
 
+    static public void computeTanpi(TestTanpi.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(4, 4);
+        args.out = tanpi(args.inVDouble, t);
+    }
+
     static public void computeTanpi(TestTanpi.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(4, 128);
         args.out = tanpi(args.inV, t);
     }
 
+    static public void computeTgamma(TestTgamma.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(16, 16);
+        args.out = tgamma(args.inVDouble, t);
+    }
+
     static public void computeTgamma(TestTgamma.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(16, 128);
         Target.Floaty in = t.new32(args.inV);
@@ -2097,6 +3226,11 @@
             tgamma(in.max32()));
     }
 
+    static public void computeTrunc(TestTrunc.ArgumentsHalfHalf args, Target t) {
+        t.setPrecision(0, 0);
+        args.out = trunc(args.inVDouble, t);
+    }
+
     static public void computeTrunc(TestTrunc.ArgumentsFloatFloat args, Target t) {
         t.setPrecision(0, 0);
         Target.Floaty in = t.new32(args.inV);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/FloatyUnitTest.java b/tests/tests/renderscript/src/android/renderscript/cts/FloatyUnitTest.java
index 9c79a66..5e7a916 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/FloatyUnitTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/FloatyUnitTest.java
@@ -30,6 +30,7 @@
     static double normalDouble = 1.7833920e+16;
 
     static double normalHalf = 1985; // 2048 - 63.  Magic number chosen for use in testHalf128Ulp
+    static double negativeNormalHalf = -237;
 
     // Some double values that are precisely representable in half-precision.
     static double[] preciseFloat16Values = {Double.NaN,
@@ -43,13 +44,18 @@
                                             -Float16Utils.MIN_VALUE * 100,
                                            };
 
-    // Fail if Floaty f doesn't accept value
-    private void shouldAccept(Target.Floaty f, double value) {
-        if (!f.couldBe(value)) {
+    // Fail if Floaty f with an extra error allowance of 'extraAllowedError' doesn't accept 'value'
+    private void shouldAccept(Target.Floaty f, double value, double extraAllowedError) {
+        if (!f.couldBe(value, extraAllowedError)) {
             StringBuilder message = new StringBuilder();
             message.append("Floaty: ");
             appendVariableToMessage(message, f);
             message.append("\n");
+            if (extraAllowedError > 0.) {
+                message.append("extraAllowedError: ");
+                appendVariableToMessage(message, extraAllowedError);
+                message.append("\n");
+            }
             message.append("Value: ");
             appendVariableToMessage(message, (float) value);
             message.append("\n");
@@ -57,13 +63,23 @@
         }
     }
 
-    // Fail if Floaty f accepts value
-    private void shouldNotAccept(Target.Floaty f, double value) {
+    // Fail if Floaty f doesn't accept value
+    private void shouldAccept(Target.Floaty f, double value) {
+        shouldAccept(f, value, 0.);
+    }
+
+    // Fail if Floaty f with an extra error allowance of 'extraAllowedError' accepts 'value'
+    private void shouldNotAccept(Target.Floaty f, double value, double extraAllowedError) {
         if (f.couldBe(value)) {
             StringBuilder message = new StringBuilder();
             message.append("Floaty: ");
             appendVariableToMessage(message, f);
             message.append("\n");
+            if (extraAllowedError > 0.) {
+                message.append("extraAllowedError: ");
+                appendVariableToMessage(message, extraAllowedError);
+                message.append("\n");
+            }
             message.append("Value: ");
             appendVariableToMessage(message, (float) value);
             message.append("\n");
@@ -71,6 +87,11 @@
         }
     }
 
+    // Fail if Floaty f accepts value
+    private void shouldNotAccept(Target.Floaty f, double value) {
+        shouldNotAccept(f, value, 0.);
+    }
+
     // Test Target that accepts precise 1ulp error for floating values.
     public void testFloat1Ulp() {
         Target t = new Target(Target.FunctionType.NORMAL, Target.ReturnType.FLOAT, false);
@@ -237,6 +258,78 @@
         shouldNotAccept(normalFloaty, 2500);
     }
 
+    public void testExtraAllowedError() {
+        Target t;
+        double extraError, lb, ub;
+
+        t = new Target(Target.FunctionType.NORMAL, Target.ReturnType.FLOAT, false);
+        t.setPrecision(4, 4);
+
+        // Test normal float value with extraAllowedError
+        extraError = 1e-15;
+        Target.Floaty normalFloaty = t.newFloaty(normalFloat2);
+        ub = normalFloat2 + 4 * Math.ulp(normalFloat2) + extraError;
+        lb = normalFloat2 - 4 * Math.ulp(normalFloat2) - extraError;
+        shouldAccept(normalFloaty, ub, extraError);
+        shouldAccept(normalFloaty, lb, extraError);
+        shouldNotAccept(normalFloaty, ub + Math.ulp(ub), extraError);
+        shouldNotAccept(normalFloaty, lb - Math.ulp(lb), extraError);
+
+        t = new Target(Target.FunctionType.NORMAL, Target.ReturnType.FLOAT, false);
+        t.setPrecision(2, 2);
+        extraError = Float.MIN_VALUE;
+
+        // Test subnormal float value with extraAllowedError
+        Target.Floaty subnormalFloaty = t.newFloaty(subnormalFloat);
+        ub = subnormalFloat + 2 * Math.ulp(subnormalFloat) + extraError;
+        lb = subnormalFloat - 2 * Math.ulp(subnormalFloat) - extraError;
+        shouldAccept(subnormalFloaty, ub, extraError);
+        shouldAccept(subnormalFloaty, lb, extraError);
+        shouldNotAccept(subnormalFloaty, ub + Math.ulp(ub), extraError);
+        shouldNotAccept(subnormalFloaty, lb - Math.ulp(lb), extraError);
+
+        t = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, false);
+        t.setPrecision(0, 0);
+
+        // Test Float16 with extraAllowedError in same order of magnitude
+        extraError = 2.0;
+        Target.Floaty halfFloaty = t.newFloaty(normalHalf);
+        ub = normalHalf + extraError;
+        lb = normalHalf - extraError;
+        shouldAccept(halfFloaty, ub, extraError);
+        shouldAccept(halfFloaty, lb, extraError);
+        shouldNotAccept(halfFloaty, ub + Float16Utils.float16Ulp(ub), extraError);
+        shouldNotAccept(halfFloaty, lb - Float16Utils.float16Ulp(lb), extraError);
+
+        // Test Float16 with a tiny extraAllowedError
+        extraError = Float16Utils.MIN_NORMAL;
+        ub = normalHalf;
+        lb = normalHalf;
+        shouldAccept(halfFloaty, ub, extraError);
+        shouldAccept(halfFloaty, lb, extraError);
+        shouldNotAccept(halfFloaty, ub + Float16Utils.float16Ulp(ub), extraError);
+        shouldNotAccept(halfFloaty, lb - Float16Utils.float16Ulp(lb), extraError);
+
+        // Test negative Float16 with extraAllowedError in same order of magnitude
+        extraError = 2.0;
+        Target.Floaty negativeHalfFloaty = t.newFloaty(negativeNormalHalf);
+        ub = negativeNormalHalf + extraError;
+        lb = negativeNormalHalf - extraError;
+        shouldAccept(negativeHalfFloaty, ub, extraError);
+        shouldAccept(negativeHalfFloaty, lb, extraError);
+        shouldNotAccept(negativeHalfFloaty, ub + Float16Utils.float16Ulp(ub), extraError);
+        shouldNotAccept(negativeHalfFloaty, lb - Float16Utils.float16Ulp(lb), extraError);
+
+        // Test negative Float16 with a tiny extraAllowedError
+        extraError = Float16Utils.MIN_NORMAL;
+        ub = negativeNormalHalf;
+        lb = negativeNormalHalf;
+        shouldAccept(negativeHalfFloaty, ub, extraError);
+        shouldAccept(negativeHalfFloaty, lb, extraError);
+        shouldNotAccept(negativeHalfFloaty, ub + Float16Utils.float16Ulp(ub), extraError);
+        shouldNotAccept(negativeHalfFloaty, lb - Float16Utils.float16Ulp(lb), extraError);
+    }
+
     // Test that range of allowed error is trimmed at the zero boundary.  This function tests both
     // float, double, and half Targets.
     public void testRangeDoesNotAcrossZero() {
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/GetAllocationTest.java b/tests/tests/renderscript/src/android/renderscript/cts/GetAllocationTest.java
index f938569..177a804 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/GetAllocationTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/GetAllocationTest.java
@@ -37,7 +37,6 @@
         Allocation mOut = Allocation.createTyped(mRS, mTemp.getType());
 
         ms.bind_pointer(mTemp);
-        ms.set_script(ms);
         ms.set_alloc_out(mOut);
         ms.invoke_start();
 
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java b/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java
index 8ef08f3..717c4a0 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RSBaseCompute.java
@@ -129,8 +129,8 @@
             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
         } else if (dataType == Element.DataType.FLOAT_16) {
             short[] inArray = new short[INPUTSIZE * width];
-            short min = RSUtils.FLOAT16_MIN_NORMAL;
-            short max = 19456; // 0x4c00 in hex, 16.0 in float16
+            double min = -4.0 * Math.PI;
+            double max = 4.0 * Math.PI;
             RSUtils.genRandomFloat16s(seed, min, max, inArray, includeExtremes);
             alloc.copyFrom(inArray);
         } else if (dataType == Element.DataType.SIGNED_64) {
@@ -185,6 +185,10 @@
             float[] inArray = new float[INPUTSIZE * width];
             RSUtils.genRandomFloats(seed, (float) minValue, (float) maxValue, inArray, false);
             alloc.copy1DRangeFrom(0, INPUTSIZE, inArray);
+        } else if (dataType == Element.DataType.FLOAT_16) {
+            short[] inArray = new short[INPUTSIZE * width];
+            RSUtils.genRandomFloat16s(seed, minValue, 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 " +
@@ -264,6 +268,22 @@
             }
             minAlloc.copyFrom(minArray);
             maxAlloc.copyFrom(maxArray);
+        } else if (dataType == Element.DataType.FLOAT_16) {
+            short[] minArray = new short[size];
+            short[] maxArray = new short[size];
+            minAlloc.copyTo(minArray);
+            maxAlloc.copyTo(maxArray);
+            for (int i = 0; i < size; i++) {
+                double minValue = Float16Utils.convertFloat16ToDouble(minArray[i]);
+                double maxValue = Float16Utils.convertFloat16ToDouble(maxArray[i]);
+                if (minValue > maxValue) {
+                    short 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];
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java b/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java
index a95687d..8704dff 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/RSUtils.java
@@ -165,8 +165,56 @@
         }
     }
 
-    public static void genRandomFloat16s(long seed, short min, short max, short array[],
-            boolean includeExtremes) {
+    public static void genRandomFloat16s(long seed, double minDoubleValue, double maxDoubleValue,
+            short array[], boolean includeExtremes) {
+
+        // Ensure that requests for random Float16s span a reasnoable range.
+        if (maxDoubleValue - minDoubleValue <= 1.) {
+            throw new RSRuntimeException("Unexpected: Range is too small");
+        }
+
+        boolean includeNegatives = false;
+
+        // Identify a range of 'short' values from the input range of 'double' If either
+        // minValueInHalf or maxValueInHalf is +/- infinity, use MAX_VALUE with appropriate sign
+        // instead.  The extreme values will get included if includeExtremes flag is set.
+        double minValueInHalf = Float16Utils.roundToFloat16(minDoubleValue)[1];
+        double maxValueInHalf = Float16Utils.roundToFloat16(maxDoubleValue)[0];
+
+        if (Double.isInfinite(minValueInHalf)) {
+            minValueInHalf = Math.copySign(Float16Utils.MAX_VALUE, minValueInHalf);
+        }
+        if (Double.isInfinite(maxValueInHalf)) {
+            maxValueInHalf = Math.copySign(Float16Utils.MAX_VALUE, maxValueInHalf);
+        }
+
+        short min = Float16Utils.convertDoubleToFloat16(minValueInHalf);
+        short max = Float16Utils.convertDoubleToFloat16(maxValueInHalf);
+
+        // If range spans across zero, set the range to be entirely positive and set
+        // includeNegatives to true.  In this scenario, the upper bound is set to the larger of
+        // maxValue and abs(minValue).  The lower bound is FLOAT16_MIN_NORMAL.
+        if (minDoubleValue < 0. && maxDoubleValue > 0.) {
+            includeNegatives = true;
+            min = FLOAT16_MIN_NORMAL;
+
+            // If abs(minDoubleValue) is greater than maxDoubleValue, pick abs(minValue) as the
+            // upper bound.
+            // TODO Update this function to generate random float16s exactly between minDoubleValue
+            // and maxDoubleValue.
+            if (Math.abs(minDoubleValue) > maxDoubleValue) {
+                max = (short) (0x7fff & min);
+            }
+        } else if (maxDoubleValue < 0.) {
+            throw new RSRuntimeException("Unexpected: Range is entirely negative: " +
+                Double.toString(minDoubleValue) + " to " + Double.toString(maxDoubleValue));
+        }
+
+        // If min is 0 or subnormal, set it to FLOAT16_MIN_NORMAL
+        if (Float16Utils.isFloat16Zero(min) || Float16Utils.isFloat16SubNormal(min)) {
+            min = FLOAT16_MIN_NORMAL;
+        }
+
         Random r = new Random(seed);
         short range = (short) (max - min + 1);
         for (int i = 0; i < array.length; i ++) {
@@ -176,13 +224,17 @@
         array[r.nextInt(array.length)] = max;
 
         // Negate approximately half of the elements.
-        for (int i = 0; i < array.length; i ++) {
-            if (r.nextBoolean()) {
-                array[i] = (short) (0x8000 | array[i]);
+        if (includeNegatives) {
+            for (int i = 0; i < array.length; i ++) {
+                if (r.nextBoolean()) {
+                    array[i] = (short) (0x8000 | array[i]);
+                }
             }
         }
 
         for (short s : sInterestingFloat16s) {
+            if (!includeNegatives && s < 0)
+                continue;
             array[r.nextInt(array.length)] = s;
         }
         if (includeExtremes) {
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ReduceTest.java b/tests/tests/renderscript/src/android/renderscript/cts/ReduceTest.java
index b3c495c..71d5549 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/ReduceTest.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/ReduceTest.java
@@ -54,6 +54,15 @@
             assertEquals(String.valueOf(i), javaRslt[i], rsRslt[i]);
     }
 
+    private void assertEquals(final String msg, final Float2 javaRslt, final Float2 rsRslt) {
+        assertEquals(msg + "(x)", javaRslt.x, rsRslt.x);
+        assertEquals(msg + "(y)", javaRslt.y, rsRslt.y);
+    }
+
+    private void assertEquals(final Float2 javaRslt, final Float2 rsRslt) {
+        assertEquals("", javaRslt, rsRslt);
+    }
+
     private void assertEquals(final String msg, final Int2 javaRslt, final Int2 rsRslt) {
         assertEquals(msg + "(x)", javaRslt.x, rsRslt.x);
         assertEquals(msg + "(y)", javaRslt.y, rsRslt.y);
@@ -125,7 +134,8 @@
 
     private static short[] createInputArrayHalf(int len, int seed) {
         short[] array = new short[len];
-        RSUtils.genRandomFloat16s(seed, RSUtils.FLOAT16_MIN_NORMAL, RSUtils.FLOAT16_MAX_VALUE, array, false);
+        RSUtils.genRandomFloat16s(seed, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, array,
+            false);
         return array;
     }
 
@@ -214,7 +224,13 @@
         final Int2 javaRslt = findMinAndMax(input);
         final Int2 rsRslt = mScript.reduce_findMinAndMax(input).get();
 
-        assertEquals(javaRslt, rsRslt);
+        // Note that the Java and RenderScript algorithms are not
+        // guaranteed to find the same cells -- but they should
+        // find cells of the same value.
+        final Float2 javaVal = new Float2(input[javaRslt.x], input[javaRslt.y]);
+        final Float2 rsVal = new Float2(input[rsRslt.x], input[rsRslt.y]);
+
+        assertEquals(javaVal, rsVal);
     }
 
     ///////////////////////////////////////////////////////////////////
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcos.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcos.java
index aa22c0a..a573212 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcos.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcos.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkAcosHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x4b431bc1l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testAcosHalfHalf(inV, out);
+            verifyResultsAcosHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAcosHalfHalf(inV, out);
+            verifyResultsAcosHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcosHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAcosHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAcosHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x3eea831bl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testAcosHalf2Half2(inV, out);
+            verifyResultsAcosHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAcosHalf2Half2(inV, out);
+            verifyResultsAcosHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcosHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAcosHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAcosHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x9df2480fl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testAcosHalf3Half3(inV, out);
+            verifyResultsAcosHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAcosHalf3Half3(inV, out);
+            verifyResultsAcosHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcosHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAcosHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAcosHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xfcfa0d03l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testAcosHalf4Half4(inV, out);
+            verifyResultsAcosHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAcosHalf4Half4(inV, out);
+            verifyResultsAcosHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcosHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcosHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAcosHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testAcos() {
         checkAcosFloatFloat();
         checkAcosFloat2Float2();
         checkAcosFloat3Float3();
         checkAcosFloat4Float4();
+        checkAcosHalfHalf();
+        checkAcosHalf2Half2();
+        checkAcosHalf3Half3();
+        checkAcosHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcos.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcos.rs
index e9c4742..2e652f6 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcos.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcos.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testAcosFloat4Float4(float4 inV) {
     return acos(inV);
 }
+
+half __attribute__((kernel)) testAcosHalfHalf(half inV) {
+    return acos(inV);
+}
+
+half2 __attribute__((kernel)) testAcosHalf2Half2(half2 inV) {
+    return acos(inV);
+}
+
+half3 __attribute__((kernel)) testAcosHalf3Half3(half3 inV) {
+    return acos(inV);
+}
+
+half4 __attribute__((kernel)) testAcosHalf4Half4(half4 inV) {
+    return acos(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcosh.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcosh.java
index e5e3766..277157a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcosh.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcosh.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkAcoshHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x78f34665l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testAcoshHalfHalf(inV, out);
+            verifyResultsAcoshHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAcoshHalfHalf(inV, out);
+            verifyResultsAcoshHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcoshHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAcoshHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAcoshHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x3c4e7d9fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testAcoshHalf2Half2(inV, out);
+            verifyResultsAcoshHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAcoshHalf2Half2(inV, out);
+            verifyResultsAcoshHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcoshHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAcoshHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAcoshHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x9b564293l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testAcoshHalf3Half3(inV, out);
+            verifyResultsAcoshHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAcoshHalf3Half3(inV, out);
+            verifyResultsAcoshHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcoshHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAcoshHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAcoshHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xfa5e0787l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testAcoshHalf4Half4(inV, out);
+            verifyResultsAcoshHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAcoshHalf4Half4(inV, out);
+            verifyResultsAcoshHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcoshHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcoshHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAcoshHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testAcosh() {
         checkAcoshFloatFloat();
         checkAcoshFloat2Float2();
         checkAcoshFloat3Float3();
         checkAcoshFloat4Float4();
+        checkAcoshHalfHalf();
+        checkAcoshHalf2Half2();
+        checkAcoshHalf3Half3();
+        checkAcoshHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcosh.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcosh.rs
index 0b1b532..130f131 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcosh.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcosh.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testAcoshFloat4Float4(float4 inV) {
     return acosh(inV);
 }
+
+half __attribute__((kernel)) testAcoshHalfHalf(half inV) {
+    return acosh(inV);
+}
+
+half2 __attribute__((kernel)) testAcoshHalf2Half2(half2 inV) {
+    return acosh(inV);
+}
+
+half3 __attribute__((kernel)) testAcoshHalf3Half3(half3 inV) {
+    return acosh(inV);
+}
+
+half4 __attribute__((kernel)) testAcoshHalf4Half4(half4 inV) {
+    return acosh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcospi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcospi.java
index 2287fc7..1b37a07 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcospi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcospi.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkAcospiHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x3b7a802cl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testAcospiHalfHalf(inV, out);
+            verifyResultsAcospiHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAcospiHalfHalf(inV, out);
+            verifyResultsAcospiHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcospiHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAcospiHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAcospiHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x3efecbeel, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testAcospiHalf2Half2(inV, out);
+            verifyResultsAcospiHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAcospiHalf2Half2(inV, out);
+            verifyResultsAcospiHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcospiHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAcospiHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAcospiHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x9e0690e2l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testAcospiHalf3Half3(inV, out);
+            verifyResultsAcospiHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAcospiHalf3Half3(inV, out);
+            verifyResultsAcospiHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcospiHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAcospiHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAcospiHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xfd0e55d6l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testAcospiHalf4Half4(inV, out);
+            verifyResultsAcospiHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAcospiHalf4Half4(inV, out);
+            verifyResultsAcospiHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAcospiHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAcospiHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAcospiHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testAcospi() {
         checkAcospiFloatFloat();
         checkAcospiFloat2Float2();
         checkAcospiFloat3Float3();
         checkAcospiFloat4Float4();
+        checkAcospiHalfHalf();
+        checkAcospiHalf2Half2();
+        checkAcospiHalf3Half3();
+        checkAcospiHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcospi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcospi.rs
index cdf4b2c..7654346 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcospi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAcospi.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testAcospiFloat4Float4(float4 inV) {
     return acospi(inV);
 }
+
+half __attribute__((kernel)) testAcospiHalfHalf(half inV) {
+    return acospi(inV);
+}
+
+half2 __attribute__((kernel)) testAcospiHalf2Half2(half2 inV) {
+    return acospi(inV);
+}
+
+half3 __attribute__((kernel)) testAcospiHalf3Half3(half3 inV) {
+    return acospi(inV);
+}
+
+half4 __attribute__((kernel)) testAcospiHalf4Half4(half4 inV) {
+    return acospi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsin.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsin.java
index 53ec3c5..b1b626c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsin.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsin.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkAsinHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x8f43a08cl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testAsinHalfHalf(inV, out);
+            verifyResultsAsinHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinHalfHalf(inV, out);
+            verifyResultsAsinHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAsinHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAsinHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x66a9a14el, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testAsinHalf2Half2(inV, out);
+            verifyResultsAsinHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinHalf2Half2(inV, out);
+            verifyResultsAsinHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAsinHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAsinHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xc5b16642l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testAsinHalf3Half3(inV, out);
+            verifyResultsAsinHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinHalf3Half3(inV, out);
+            verifyResultsAsinHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAsinHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAsinHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x24b92b36l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testAsinHalf4Half4(inV, out);
+            verifyResultsAsinHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinHalf4Half4(inV, out);
+            verifyResultsAsinHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAsinHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testAsin() {
         checkAsinFloatFloat();
         checkAsinFloat2Float2();
         checkAsinFloat3Float3();
         checkAsinFloat4Float4();
+        checkAsinHalfHalf();
+        checkAsinHalf2Half2();
+        checkAsinHalf3Half3();
+        checkAsinHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsin.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsin.rs
index 87ef4f8..29e5325 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsin.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsin.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testAsinFloat4Float4(float4 inV) {
     return asin(inV);
 }
+
+half __attribute__((kernel)) testAsinHalfHalf(half inV) {
+    return asin(inV);
+}
+
+half2 __attribute__((kernel)) testAsinHalf2Half2(half2 inV) {
+    return asin(inV);
+}
+
+half3 __attribute__((kernel)) testAsinHalf3Half3(half3 inV) {
+    return asin(inV);
+}
+
+half4 __attribute__((kernel)) testAsinHalf4Half4(half4 inV) {
+    return asin(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinh.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinh.java
index d14dc53..45ba8c8 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinh.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinh.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkAsinhHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe509947el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testAsinhHalfHalf(inV, out);
+            verifyResultsAsinhHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinhHalfHalf(inV, out);
+            verifyResultsAsinhHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinhHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAsinhHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAsinhHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xe9689030l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testAsinhHalf2Half2(inV, out);
+            verifyResultsAsinhHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinhHalf2Half2(inV, out);
+            verifyResultsAsinhHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinhHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAsinhHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAsinhHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x48705524l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testAsinhHalf3Half3(inV, out);
+            verifyResultsAsinhHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinhHalf3Half3(inV, out);
+            verifyResultsAsinhHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinhHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAsinhHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAsinhHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xa7781a18l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testAsinhHalf4Half4(inV, out);
+            verifyResultsAsinhHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinhHalf4Half4(inV, out);
+            verifyResultsAsinhHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinhHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinhHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAsinhHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testAsinh() {
         checkAsinhFloatFloat();
         checkAsinhFloat2Float2();
         checkAsinhFloat3Float3();
         checkAsinhFloat4Float4();
+        checkAsinhHalfHalf();
+        checkAsinhHalf2Half2();
+        checkAsinhHalf3Half3();
+        checkAsinhHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinh.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinh.rs
index 19a15e2..47d172d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinh.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinh.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testAsinhFloat4Float4(float4 inV) {
     return asinh(inV);
 }
+
+half __attribute__((kernel)) testAsinhHalfHalf(half inV) {
+    return asinh(inV);
+}
+
+half2 __attribute__((kernel)) testAsinhHalf2Half2(half2 inV) {
+    return asinh(inV);
+}
+
+half3 __attribute__((kernel)) testAsinhHalf3Half3(half3 inV) {
+    return asinh(inV);
+}
+
+half4 __attribute__((kernel)) testAsinhHalf4Half4(half4 inV) {
+    return asinh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinpi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinpi.java
index 8f4a825..3e4e481 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinpi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinpi.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkAsinpiHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x63399e5fl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testAsinpiHalfHalf(inV, out);
+            verifyResultsAsinpiHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinpiHalfHalf(inV, out);
+            verifyResultsAsinpiHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinpiHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAsinpiHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAsinpiHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x525fea49l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testAsinpiHalf2Half2(inV, out);
+            verifyResultsAsinpiHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinpiHalf2Half2(inV, out);
+            verifyResultsAsinpiHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinpiHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAsinpiHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAsinpiHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb167af3dl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testAsinpiHalf3Half3(inV, out);
+            verifyResultsAsinpiHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinpiHalf3Half3(inV, out);
+            verifyResultsAsinpiHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinpiHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAsinpiHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAsinpiHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x106f7431l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testAsinpiHalf4Half4(inV, out);
+            verifyResultsAsinpiHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAsinpiHalf4Half4(inV, out);
+            verifyResultsAsinpiHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAsinpiHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAsinpiHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAsinpiHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testAsinpi() {
         checkAsinpiFloatFloat();
         checkAsinpiFloat2Float2();
         checkAsinpiFloat3Float3();
         checkAsinpiFloat4Float4();
+        checkAsinpiHalfHalf();
+        checkAsinpiHalf2Half2();
+        checkAsinpiHalf3Half3();
+        checkAsinpiHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinpi.rs
index 1ec8232..92e347e 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinpi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAsinpi.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testAsinpiFloat4Float4(float4 inV) {
     return asinpi(inV);
 }
+
+half __attribute__((kernel)) testAsinpiHalfHalf(half inV) {
+    return asinpi(inV);
+}
+
+half2 __attribute__((kernel)) testAsinpiHalf2Half2(half2 inV) {
+    return asinpi(inV);
+}
+
+half3 __attribute__((kernel)) testAsinpiHalf3Half3(half3 inV) {
+    return asinpi(inV);
+}
+
+half4 __attribute__((kernel)) testAsinpiHalf4Half4(half4 inV) {
+    return asinpi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan.java
index 1bbc4dc..8a16081 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkAtanHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xfa1813dfl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testAtanHalfHalf(inV, out);
+            verifyResultsAtanHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanHalfHalf(inV, out);
+            verifyResultsAtanHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtanHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtanHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xff1e93c9l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testAtanHalf2Half2(inV, out);
+            verifyResultsAtanHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanHalf2Half2(inV, out);
+            verifyResultsAtanHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtanHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtanHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x5e2658bdl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testAtanHalf3Half3(inV, out);
+            verifyResultsAtanHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanHalf3Half3(inV, out);
+            verifyResultsAtanHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtanHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtanHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xbd2e1db1l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testAtanHalf4Half4(inV, out);
+            verifyResultsAtanHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanHalf4Half4(inV, out);
+            verifyResultsAtanHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtanHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testAtan() {
         checkAtanFloatFloat();
         checkAtanFloat2Float2();
         checkAtanFloat3Float3();
         checkAtanFloat4Float4();
+        checkAtanHalfHalf();
+        checkAtanHalf2Half2();
+        checkAtanHalf3Half3();
+        checkAtanHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan.rs
index da84da8..bc57dc2 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testAtanFloat4Float4(float4 inV) {
     return atan(inV);
 }
+
+half __attribute__((kernel)) testAtanHalfHalf(half inV) {
+    return atan(inV);
+}
+
+half2 __attribute__((kernel)) testAtanHalf2Half2(half2 inV) {
+    return atan(inV);
+}
+
+half3 __attribute__((kernel)) testAtanHalf3Half3(half3 inV) {
+    return atan(inV);
+}
+
+half4 __attribute__((kernel)) testAtanHalf4Half4(half4 inV) {
+    return atan(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2.java
index 6ea47d5..77f47e7 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inNumerator;
+        public double inNumeratorDouble;
+        public short inDenominator;
+        public double inDenominatorDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkAtan2HalfHalfHalf() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xa6793e31l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xc8fcd922l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testAtan2HalfHalfHalf(inNumerator, out);
+            verifyResultsAtan2HalfHalfHalf(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2HalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testAtan2HalfHalfHalf(inNumerator, out);
+            verifyResultsAtan2HalfHalfHalf(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2HalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2HalfHalfHalf(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtan2HalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtan2Half2Half2Half2() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xec117907l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x717dccc8l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testAtan2Half2Half2Half2(inNumerator, out);
+            verifyResultsAtan2Half2Half2Half2(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2Half2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testAtan2Half2Half2Half2(inNumerator, out);
+            verifyResultsAtan2Half2Half2Half2(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2Half2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2Half2Half2Half2(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 2 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 2 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtan2Half2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtan2Half3Half3Half3() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x3783a976l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x5d3d9e7fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testAtan2Half3Half3Half3(inNumerator, out);
+            verifyResultsAtan2Half3Half3Half3(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2Half3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testAtan2Half3Half3Half3(inNumerator, out);
+            verifyResultsAtan2Half3Half3Half3(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2Half3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2Half3Half3Half3(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 4 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 4 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtan2Half3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtan2Half4Half4Half4() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x82f5d9e5l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x48fd7036l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testAtan2Half4Half4Half4(inNumerator, out);
+            verifyResultsAtan2Half4Half4Half4(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2Half4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testAtan2Half4Half4Half4(inNumerator, out);
+            verifyResultsAtan2Half4Half4Half4(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2Half4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2Half4Half4Half4(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 4 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 4 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtan2Half4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testAtan2() {
         checkAtan2FloatFloatFloat();
         checkAtan2Float2Float2Float2();
         checkAtan2Float3Float3Float3();
         checkAtan2Float4Float4Float4();
+        checkAtan2HalfHalfHalf();
+        checkAtan2Half2Half2Half2();
+        checkAtan2Half3Half3Half3();
+        checkAtan2Half4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2.rs
index 0d20f3c..229320b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2.rs
@@ -40,3 +40,23 @@
     float4 inDenominator = rsGetElementAt_float4(gAllocInDenominator, x);
     return atan2(inNumerator, inDenominator);
 }
+
+half __attribute__((kernel)) testAtan2HalfHalfHalf(half inNumerator, unsigned int x) {
+    half inDenominator = rsGetElementAt_half(gAllocInDenominator, x);
+    return atan2(inNumerator, inDenominator);
+}
+
+half2 __attribute__((kernel)) testAtan2Half2Half2Half2(half2 inNumerator, unsigned int x) {
+    half2 inDenominator = rsGetElementAt_half2(gAllocInDenominator, x);
+    return atan2(inNumerator, inDenominator);
+}
+
+half3 __attribute__((kernel)) testAtan2Half3Half3Half3(half3 inNumerator, unsigned int x) {
+    half3 inDenominator = rsGetElementAt_half3(gAllocInDenominator, x);
+    return atan2(inNumerator, inDenominator);
+}
+
+half4 __attribute__((kernel)) testAtan2Half4Half4Half4(half4 inNumerator, unsigned int x) {
+    half4 inDenominator = rsGetElementAt_half4(gAllocInDenominator, x);
+    return atan2(inNumerator, inDenominator);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2pi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2pi.java
index 6068cea..2d8539c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2pi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2pi.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inNumerator;
+        public double inNumeratorDouble;
+        public short inDenominator;
+        public double inDenominatorDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkAtan2piHalfHalfHalf() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x2ee67becl, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x25ffb4c5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testAtan2piHalfHalfHalf(inNumerator, out);
+            verifyResultsAtan2piHalfHalfHalf(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testAtan2piHalfHalfHalf(inNumerator, out);
+            verifyResultsAtan2piHalfHalfHalf(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2piHalfHalfHalf(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtan2piHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtan2piHalf2Half2Half2() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x8b8c5d68l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x50194d61l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testAtan2piHalf2Half2Half2(inNumerator, out);
+            verifyResultsAtan2piHalf2Half2Half2(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testAtan2piHalf2Half2Half2(inNumerator, out);
+            verifyResultsAtan2piHalf2Half2Half2(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2piHalf2Half2Half2(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 2 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 2 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtan2piHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtan2piHalf3Half3Half3() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xd6fe8dd7l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x3bd91f18l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testAtan2piHalf3Half3Half3(inNumerator, out);
+            verifyResultsAtan2piHalf3Half3Half3(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testAtan2piHalf3Half3Half3(inNumerator, out);
+            verifyResultsAtan2piHalf3Half3Half3(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2piHalf3Half3Half3(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 4 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 4 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtan2piHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtan2piHalf4Half4Half4() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x2270be46l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x2798f0cfl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testAtan2piHalf4Half4Half4(inNumerator, out);
+            verifyResultsAtan2piHalf4Half4Half4(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testAtan2piHalf4Half4Half4(inNumerator, out);
+            verifyResultsAtan2piHalf4Half4Half4(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtan2piHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtan2piHalf4Half4Half4(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 4 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 4 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtan2piHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testAtan2pi() {
         checkAtan2piFloatFloatFloat();
         checkAtan2piFloat2Float2Float2();
         checkAtan2piFloat3Float3Float3();
         checkAtan2piFloat4Float4Float4();
+        checkAtan2piHalfHalfHalf();
+        checkAtan2piHalf2Half2Half2();
+        checkAtan2piHalf3Half3Half3();
+        checkAtan2piHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2pi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2pi.rs
index 14dcbc7..3daa107 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2pi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtan2pi.rs
@@ -40,3 +40,23 @@
     float4 inDenominator = rsGetElementAt_float4(gAllocInDenominator, x);
     return atan2pi(inNumerator, inDenominator);
 }
+
+half __attribute__((kernel)) testAtan2piHalfHalfHalf(half inNumerator, unsigned int x) {
+    half inDenominator = rsGetElementAt_half(gAllocInDenominator, x);
+    return atan2pi(inNumerator, inDenominator);
+}
+
+half2 __attribute__((kernel)) testAtan2piHalf2Half2Half2(half2 inNumerator, unsigned int x) {
+    half2 inDenominator = rsGetElementAt_half2(gAllocInDenominator, x);
+    return atan2pi(inNumerator, inDenominator);
+}
+
+half3 __attribute__((kernel)) testAtan2piHalf3Half3Half3(half3 inNumerator, unsigned int x) {
+    half3 inDenominator = rsGetElementAt_half3(gAllocInDenominator, x);
+    return atan2pi(inNumerator, inDenominator);
+}
+
+half4 __attribute__((kernel)) testAtan2piHalf4Half4Half4(half4 inNumerator, unsigned int x) {
+    half4 inDenominator = rsGetElementAt_half4(gAllocInDenominator, x);
+    return atan2pi(inNumerator, inDenominator);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanh.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanh.java
index feebf49..187d797 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanh.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanh.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkAtanhHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xd6b8f36fl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testAtanhHalfHalf(inV, out);
+            verifyResultsAtanhHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanhHalfHalf(inV, out);
+            verifyResultsAtanhHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanhHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtanhHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtanhHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x850d4ad9l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testAtanhHalf2Half2(inV, out);
+            verifyResultsAtanhHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanhHalf2Half2(inV, out);
+            verifyResultsAtanhHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanhHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtanhHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtanhHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xe4150fcdl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testAtanhHalf3Half3(inV, out);
+            verifyResultsAtanhHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanhHalf3Half3(inV, out);
+            verifyResultsAtanhHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanhHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtanhHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtanhHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x431cd4c1l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testAtanhHalf4Half4(inV, out);
+            verifyResultsAtanhHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanhHalf4Half4(inV, out);
+            verifyResultsAtanhHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanhHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanhHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtanhHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testAtanh() {
         checkAtanhFloatFloat();
         checkAtanhFloat2Float2();
         checkAtanhFloat3Float3();
         checkAtanhFloat4Float4();
+        checkAtanhHalfHalf();
+        checkAtanhHalf2Half2();
+        checkAtanhHalf3Half3();
+        checkAtanhHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanh.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanh.rs
index dee95a7..082154c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanh.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanh.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testAtanhFloat4Float4(float4 inV) {
     return atanh(inV);
 }
+
+half __attribute__((kernel)) testAtanhHalfHalf(half inV) {
+    return atanh(inV);
+}
+
+half2 __attribute__((kernel)) testAtanhHalf2Half2(half2 inV) {
+    return atanh(inV);
+}
+
+half3 __attribute__((kernel)) testAtanhHalf3Half3(half3 inV) {
+    return atanh(inV);
+}
+
+half4 __attribute__((kernel)) testAtanhHalf4Half4(half4 inV) {
+    return atanh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanpi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanpi.java
index d38e400..36d8ae8 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanpi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanpi.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkAtanpiHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xfbae90dal, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testAtanpiHalfHalf(inV, out);
+            verifyResultsAtanpiHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanpiHalfHalf(inV, out);
+            verifyResultsAtanpiHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanpiHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtanpiHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtanpiHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x770b44acl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testAtanpiHalf2Half2(inV, out);
+            verifyResultsAtanpiHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanpiHalf2Half2(inV, out);
+            verifyResultsAtanpiHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanpiHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtanpiHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtanpiHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xd61309a0l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testAtanpiHalf3Half3(inV, out);
+            verifyResultsAtanpiHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanpiHalf3Half3(inV, out);
+            verifyResultsAtanpiHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanpiHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtanpiHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkAtanpiHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x351ace94l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testAtanpiHalf4Half4(inV, out);
+            verifyResultsAtanpiHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testAtanpiHalf4Half4(inV, out);
+            verifyResultsAtanpiHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testAtanpiHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsAtanpiHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkAtanpiHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testAtanpi() {
         checkAtanpiFloatFloat();
         checkAtanpiFloat2Float2();
         checkAtanpiFloat3Float3();
         checkAtanpiFloat4Float4();
+        checkAtanpiHalfHalf();
+        checkAtanpiHalf2Half2();
+        checkAtanpiHalf3Half3();
+        checkAtanpiHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanpi.rs
index c59b350..b1185ee 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanpi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestAtanpi.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testAtanpiFloat4Float4(float4 inV) {
     return atanpi(inV);
 }
+
+half __attribute__((kernel)) testAtanpiHalfHalf(half inV) {
+    return atanpi(inV);
+}
+
+half2 __attribute__((kernel)) testAtanpiHalf2Half2(half2 inV) {
+    return atanpi(inV);
+}
+
+half3 __attribute__((kernel)) testAtanpiHalf3Half3(half3 inV) {
+    return atanpi(inV);
+}
+
+half4 __attribute__((kernel)) testAtanpiHalf4Half4(half4 inV) {
+    return atanpi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCbrt.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCbrt.java
index bfd98e6..cd2592b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCbrt.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCbrt.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkCbrtHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xc175945el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testCbrtHalfHalf(inV, out);
+            verifyResultsCbrtHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testCbrtHalfHalf(inV, out);
+            verifyResultsCbrtHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCbrtHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCbrtHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCbrtHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xf173a910l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testCbrtHalf2Half2(inV, out);
+            verifyResultsCbrtHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testCbrtHalf2Half2(inV, out);
+            verifyResultsCbrtHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCbrtHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCbrtHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCbrtHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x507b6e04l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testCbrtHalf3Half3(inV, out);
+            verifyResultsCbrtHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testCbrtHalf3Half3(inV, out);
+            verifyResultsCbrtHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCbrtHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCbrtHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCbrtHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xaf8332f8l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testCbrtHalf4Half4(inV, out);
+            verifyResultsCbrtHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testCbrtHalf4Half4(inV, out);
+            verifyResultsCbrtHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCbrtHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCbrtHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCbrtHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testCbrt() {
         checkCbrtFloatFloat();
         checkCbrtFloat2Float2();
         checkCbrtFloat3Float3();
         checkCbrtFloat4Float4();
+        checkCbrtHalfHalf();
+        checkCbrtHalf2Half2();
+        checkCbrtHalf3Half3();
+        checkCbrtHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCbrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCbrt.rs
index 491dc7a..a9c1cc7 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCbrt.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCbrt.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testCbrtFloat4Float4(float4 inV) {
     return cbrt(inV);
 }
+
+half __attribute__((kernel)) testCbrtHalfHalf(half inV) {
+    return cbrt(inV);
+}
+
+half2 __attribute__((kernel)) testCbrtHalf2Half2(half2 inV) {
+    return cbrt(inV);
+}
+
+half3 __attribute__((kernel)) testCbrtHalf3Half3(half3 inV) {
+    return cbrt(inV);
+}
+
+half4 __attribute__((kernel)) testCbrtHalf4Half4(half4 inV) {
+    return cbrt(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCeil.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCeil.java
index e5e0f6b..437479c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCeil.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCeil.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkCeilHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x6f7686bel, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testCeilHalfHalf(inV, out);
+            verifyResultsCeilHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testCeilHalfHalf(inV, out);
+            verifyResultsCeilHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCeilHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCeil(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCeilHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCeilHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xb64a4070l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testCeilHalf2Half2(inV, out);
+            verifyResultsCeilHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testCeilHalf2Half2(inV, out);
+            verifyResultsCeilHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCeilHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCeil(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCeilHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCeilHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x15520564l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testCeilHalf3Half3(inV, out);
+            verifyResultsCeilHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testCeilHalf3Half3(inV, out);
+            verifyResultsCeilHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCeilHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCeil(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCeilHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCeilHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x7459ca58l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testCeilHalf4Half4(inV, out);
+            verifyResultsCeilHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testCeilHalf4Half4(inV, out);
+            verifyResultsCeilHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCeilHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCeilHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCeil(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCeilHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testCeil() {
         checkCeilFloatFloat();
         checkCeilFloat2Float2();
         checkCeilFloat3Float3();
         checkCeilFloat4Float4();
+        checkCeilHalfHalf();
+        checkCeilHalf2Half2();
+        checkCeilHalf3Half3();
+        checkCeilHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCeil.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCeil.rs
index bc11e81..9cf05fc 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCeil.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCeil.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testCeilFloat4Float4(float4 inV) {
     return ceil(inV);
 }
+
+half __attribute__((kernel)) testCeilHalfHalf(half inV) {
+    return ceil(inV);
+}
+
+half2 __attribute__((kernel)) testCeilHalf2Half2(half2 inV) {
+    return ceil(inV);
+}
+
+half3 __attribute__((kernel)) testCeilHalf3Half3(half3 inV) {
+    return ceil(inV);
+}
+
+half4 __attribute__((kernel)) testCeilHalf4Half4(half4 inV) {
+    return ceil(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestClamp.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestClamp.java
index 8f9b5e4..7499b77 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestClamp.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestClamp.java
@@ -5714,6 +5714,688 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalfHalf {
+        public short inValue;
+        public double inValueDouble;
+        public short inMinValue;
+        public double inMinValueDouble;
+        public short inMaxValue;
+        public double inMaxValueDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkClampHalfHalfHalfHalf() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x4b82831l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xf102f883l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x825fea89l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampHalfHalfHalfHalf(inValue, out);
+            verifyResultsClampHalfHalfHalfHalf(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalfHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampHalfHalfHalfHalf(inValue, out);
+            verifyResultsClampHalfHalfHalfHalf(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalfHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampHalfHalfHalfHalf(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInValue, (short) 42);
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMinValue, (short) 42);
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMaxValue, (short) 42);
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inValue = arrayInValue[i];
+                args.inValueDouble = Float16Utils.convertFloat16ToDouble(args.inValue);
+                args.inMinValue = arrayInMinValue[i];
+                args.inMinValueDouble = Float16Utils.convertFloat16ToDouble(args.inMinValue);
+                args.inMaxValue = arrayInMaxValue[i];
+                args.inMaxValueDouble = Float16Utils.convertFloat16ToDouble(args.inMaxValue);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inValue: ");
+                        appendVariableToMessage(message, args.inValue);
+                        message.append("\n");
+                        message.append("Input inMinValue: ");
+                        appendVariableToMessage(message, args.inMinValue);
+                        message.append("\n");
+                        message.append("Input inMaxValue: ");
+                        appendVariableToMessage(message, args.inMaxValue);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkClampHalfHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkClampHalf2Half2Half2Half2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xb1049715l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x6f2ebd6fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x8baf75l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampHalf2Half2Half2Half2(inValue, out);
+            verifyResultsClampHalf2Half2Half2Half2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalf2Half2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampHalf2Half2Half2Half2(inValue, out);
+            verifyResultsClampHalf2Half2Half2Half2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalf2Half2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampHalf2Half2Half2Half2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInValue, (short) 42);
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInMinValue, (short) 42);
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInMaxValue, (short) 42);
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inValueDouble = Float16Utils.convertFloat16ToDouble(args.inValue);
+                args.inMinValue = arrayInMinValue[i * 2 + j];
+                args.inMinValueDouble = Float16Utils.convertFloat16ToDouble(args.inMinValue);
+                args.inMaxValue = arrayInMaxValue[i * 2 + j];
+                args.inMaxValueDouble = Float16Utils.convertFloat16ToDouble(args.inMaxValue);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inValue: ");
+                        appendVariableToMessage(message, args.inValue);
+                        message.append("\n");
+                        message.append("Input inMinValue: ");
+                        appendVariableToMessage(message, args.inMinValue);
+                        message.append("\n");
+                        message.append("Input inMaxValue: ");
+                        appendVariableToMessage(message, args.inMaxValue);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkClampHalf2Half2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkClampHalf3Half3Half3Half3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xa6d9935dl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x81facac7l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x1357bccdl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampHalf3Half3Half3Half3(inValue, out);
+            verifyResultsClampHalf3Half3Half3Half3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalf3Half3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampHalf3Half3Half3Half3(inValue, out);
+            verifyResultsClampHalf3Half3Half3Half3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalf3Half3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampHalf3Half3Half3Half3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInValue, (short) 42);
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMinValue, (short) 42);
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMaxValue, (short) 42);
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inValueDouble = Float16Utils.convertFloat16ToDouble(args.inValue);
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMinValueDouble = Float16Utils.convertFloat16ToDouble(args.inMinValue);
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                args.inMaxValueDouble = Float16Utils.convertFloat16ToDouble(args.inMaxValue);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inValue: ");
+                        appendVariableToMessage(message, args.inValue);
+                        message.append("\n");
+                        message.append("Input inMinValue: ");
+                        appendVariableToMessage(message, args.inMinValue);
+                        message.append("\n");
+                        message.append("Input inMaxValue: ");
+                        appendVariableToMessage(message, args.inMaxValue);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkClampHalf3Half3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkClampHalf4Half4Half4Half4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x9cae8fa5l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x94c6d81fl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x2623ca25l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampHalf4Half4Half4Half4(inValue, out);
+            verifyResultsClampHalf4Half4Half4Half4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalf4Half4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampHalf4Half4Half4Half4(inValue, out);
+            verifyResultsClampHalf4Half4Half4Half4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalf4Half4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampHalf4Half4Half4Half4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInValue, (short) 42);
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMinValue, (short) 42);
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMaxValue, (short) 42);
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inValueDouble = Float16Utils.convertFloat16ToDouble(args.inValue);
+                args.inMinValue = arrayInMinValue[i * 4 + j];
+                args.inMinValueDouble = Float16Utils.convertFloat16ToDouble(args.inMinValue);
+                args.inMaxValue = arrayInMaxValue[i * 4 + j];
+                args.inMaxValueDouble = Float16Utils.convertFloat16ToDouble(args.inMaxValue);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inValue: ");
+                        appendVariableToMessage(message, args.inValue);
+                        message.append("\n");
+                        message.append("Input inMinValue: ");
+                        appendVariableToMessage(message, args.inMinValue);
+                        message.append("\n");
+                        message.append("Input inMaxValue: ");
+                        appendVariableToMessage(message, args.inMaxValue);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkClampHalf4Half4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkClampHalf2HalfHalfHalf2() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x35f68507l, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xbc3d6b65l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x4d9a5d6bl, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampHalf2HalfHalfHalf2(inValue, out);
+            verifyResultsClampHalf2HalfHalfHalf2(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalf2HalfHalfHalf2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampHalf2HalfHalfHalf2(inValue, out);
+            verifyResultsClampHalf2HalfHalfHalf2(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalf2HalfHalfHalf2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampHalf2HalfHalfHalf2(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInValue, (short) 42);
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMinValue, (short) 42);
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMaxValue, (short) 42);
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inValue = arrayInValue[i * 2 + j];
+                args.inValueDouble = Float16Utils.convertFloat16ToDouble(args.inValue);
+                args.inMinValue = arrayInMinValue[i];
+                args.inMinValueDouble = Float16Utils.convertFloat16ToDouble(args.inMinValue);
+                args.inMaxValue = arrayInMaxValue[i];
+                args.inMaxValueDouble = Float16Utils.convertFloat16ToDouble(args.inMaxValue);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inValue: ");
+                        appendVariableToMessage(message, args.inValue);
+                        message.append("\n");
+                        message.append("Input inMinValue: ");
+                        appendVariableToMessage(message, args.inMinValue);
+                        message.append("\n");
+                        message.append("Input inMaxValue: ");
+                        appendVariableToMessage(message, args.inMaxValue);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkClampHalf2HalfHalfHalf2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkClampHalf3HalfHalfHalf3() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x1f414e1bl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x41ad19e1l, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xd30a0be7l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampHalf3HalfHalfHalf3(inValue, out);
+            verifyResultsClampHalf3HalfHalfHalf3(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalf3HalfHalfHalf3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampHalf3HalfHalfHalf3(inValue, out);
+            verifyResultsClampHalf3HalfHalfHalf3(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalf3HalfHalfHalf3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampHalf3HalfHalfHalf3(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInValue, (short) 42);
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMinValue, (short) 42);
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMaxValue, (short) 42);
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inValueDouble = Float16Utils.convertFloat16ToDouble(args.inValue);
+                args.inMinValue = arrayInMinValue[i];
+                args.inMinValueDouble = Float16Utils.convertFloat16ToDouble(args.inMinValue);
+                args.inMaxValue = arrayInMaxValue[i];
+                args.inMaxValueDouble = Float16Utils.convertFloat16ToDouble(args.inMaxValue);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inValue: ");
+                        appendVariableToMessage(message, args.inValue);
+                        message.append("\n");
+                        message.append("Input inMinValue: ");
+                        appendVariableToMessage(message, args.inMinValue);
+                        message.append("\n");
+                        message.append("Input inMaxValue: ");
+                        appendVariableToMessage(message, args.inMaxValue);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkClampHalf3HalfHalfHalf3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkClampHalf4HalfHalfHalf4() {
+        Allocation inValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x88c172fl, false);
+        Allocation inMinValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xc71cc85dl, false);
+        Allocation inMaxValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x5879ba63l, false);
+        enforceOrdering(inMinValue, inMaxValue);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInMinValue(inMinValue);
+            script.set_gAllocInMaxValue(inMaxValue);
+            script.forEach_testClampHalf4HalfHalfHalf4(inValue, out);
+            verifyResultsClampHalf4HalfHalfHalf4(inValue, inMinValue, inMaxValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalf4HalfHalfHalf4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMinValue(inMinValue);
+            scriptRelaxed.set_gAllocInMaxValue(inMaxValue);
+            scriptRelaxed.forEach_testClampHalf4HalfHalfHalf4(inValue, out);
+            verifyResultsClampHalf4HalfHalfHalf4(inValue, inMinValue, inMaxValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testClampHalf4HalfHalfHalf4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsClampHalf4HalfHalfHalf4(Allocation inValue, Allocation inMinValue, Allocation inMaxValue, Allocation out, boolean relaxed) {
+        short[] arrayInValue = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInValue, (short) 42);
+        inValue.copyTo(arrayInValue);
+        short[] arrayInMinValue = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMinValue, (short) 42);
+        inMinValue.copyTo(arrayInMinValue);
+        short[] arrayInMaxValue = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMaxValue, (short) 42);
+        inMaxValue.copyTo(arrayInMaxValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inValue = arrayInValue[i * 4 + j];
+                args.inValueDouble = Float16Utils.convertFloat16ToDouble(args.inValue);
+                args.inMinValue = arrayInMinValue[i];
+                args.inMinValueDouble = Float16Utils.convertFloat16ToDouble(args.inMinValue);
+                args.inMaxValue = arrayInMaxValue[i];
+                args.inMaxValueDouble = Float16Utils.convertFloat16ToDouble(args.inMaxValue);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeClamp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inValue: ");
+                        appendVariableToMessage(message, args.inValue);
+                        message.append("\n");
+                        message.append("Input inMinValue: ");
+                        appendVariableToMessage(message, args.inMinValue);
+                        message.append("\n");
+                        message.append("Input inMaxValue: ");
+                        appendVariableToMessage(message, args.inMaxValue);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkClampHalf4HalfHalfHalf4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testClamp() {
         checkClampFloatFloatFloatFloat();
         checkClampFloat2Float2Float2Float2();
@@ -5778,5 +6460,12 @@
         checkClampUlong2UlongUlongUlong2();
         checkClampUlong3UlongUlongUlong3();
         checkClampUlong4UlongUlongUlong4();
+        checkClampHalfHalfHalfHalf();
+        checkClampHalf2Half2Half2Half2();
+        checkClampHalf3Half3Half3Half3();
+        checkClampHalf4Half4Half4Half4();
+        checkClampHalf2HalfHalfHalf2();
+        checkClampHalf3HalfHalfHalf3();
+        checkClampHalf4HalfHalfHalf4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestClamp.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestClamp.rs
index c5a5159..808c27c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestClamp.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestClamp.rs
@@ -399,3 +399,45 @@
     ulong inMaxValue = rsGetElementAt_ulong(gAllocInMaxValue, x);
     return clamp(inValue, inMinValue, inMaxValue);
 }
+
+half __attribute__((kernel)) testClampHalfHalfHalfHalf(half inValue, unsigned int x) {
+    half inMinValue = rsGetElementAt_half(gAllocInMinValue, x);
+    half inMaxValue = rsGetElementAt_half(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+half2 __attribute__((kernel)) testClampHalf2Half2Half2Half2(half2 inValue, unsigned int x) {
+    half2 inMinValue = rsGetElementAt_half2(gAllocInMinValue, x);
+    half2 inMaxValue = rsGetElementAt_half2(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+half3 __attribute__((kernel)) testClampHalf3Half3Half3Half3(half3 inValue, unsigned int x) {
+    half3 inMinValue = rsGetElementAt_half3(gAllocInMinValue, x);
+    half3 inMaxValue = rsGetElementAt_half3(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+half4 __attribute__((kernel)) testClampHalf4Half4Half4Half4(half4 inValue, unsigned int x) {
+    half4 inMinValue = rsGetElementAt_half4(gAllocInMinValue, x);
+    half4 inMaxValue = rsGetElementAt_half4(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+half2 __attribute__((kernel)) testClampHalf2HalfHalfHalf2(half2 inValue, unsigned int x) {
+    half inMinValue = rsGetElementAt_half(gAllocInMinValue, x);
+    half inMaxValue = rsGetElementAt_half(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+half3 __attribute__((kernel)) testClampHalf3HalfHalfHalf3(half3 inValue, unsigned int x) {
+    half inMinValue = rsGetElementAt_half(gAllocInMinValue, x);
+    half inMaxValue = rsGetElementAt_half(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
+
+half4 __attribute__((kernel)) testClampHalf4HalfHalfHalf4(half4 inValue, unsigned int x) {
+    half inMinValue = rsGetElementAt_half(gAllocInMinValue, x);
+    half inMaxValue = rsGetElementAt_half(gAllocInMaxValue, x);
+    return clamp(inValue, inMinValue, inMaxValue);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestConvert.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestConvert.java
index 319b104..d7fbb9a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestConvert.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestConvert.java
@@ -20997,6 +20997,4577 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x77294e2el, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testConvertHalf2Half2Half2(inV, out);
+            verifyResultsConvertHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf2Half2Half2(inV, out);
+            verifyResultsConvertHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xd6311322l, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testConvertHalf3Half3Half3(inV, out);
+            verifyResultsConvertHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf3Half3Half3(inV, out);
+            verifyResultsConvertHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x3538d816l, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testConvertHalf4Half4Half4(inV, out);
+            verifyResultsConvertHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf4Half4Half4(inV, out);
+            verifyResultsConvertHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsHalfFloat {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertHalf2Float2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xbbc7b5dbl, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            script.forEach_testConvertFloat2Half2Float2(inV, out);
+            verifyResultsConvertHalf2Float2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Half2Float2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat2Half2Float2(inV, out);
+            verifyResultsConvertHalf2Float2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat2Half2Float2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf2Float2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (float) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfFloat args = new ArgumentsHalfFloat();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.FLOAT, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf2Float2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf3Float3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb1e2d6b9l, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            script.forEach_testConvertFloat3Half3Float3(inV, out);
+            verifyResultsConvertHalf3Float3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Half3Float3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat3Half3Float3(inV, out);
+            verifyResultsConvertHalf3Float3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat3Half3Float3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf3Float3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (float) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfFloat args = new ArgumentsHalfFloat();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.FLOAT, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf3Float3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf4Float4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xa7fdf797l, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            script.forEach_testConvertFloat4Half4Float4(inV, out);
+            verifyResultsConvertHalf4Float4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Half4Float4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertFloat4Half4Float4(inV, out);
+            verifyResultsConvertHalf4Float4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertFloat4Half4Float4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf4Float4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        float[] arrayOut = new float[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (float) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfFloat args = new ArgumentsHalfFloat();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.FLOAT, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf4Float4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsHalfDouble {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertHalf2Double2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xb2251ea8l, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            script.forEach_testConvertDouble2Half2Double2(inV, out);
+            verifyResultsConvertHalf2Double2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Half2Double2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble2Half2Double2(inV, out);
+            verifyResultsConvertHalf2Double2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble2Half2Double2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf2Double2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (double) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfDouble args = new ArgumentsHalfDouble();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.DOUBLE, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        if (!args.out.couldBe(arrayOut[i * 2 + j])) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf2Double2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf3Double3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x880afd4l, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            script.forEach_testConvertDouble3Half3Double3(inV, out);
+            verifyResultsConvertHalf3Double3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Half3Double3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble3Half3Double3(inV, out);
+            verifyResultsConvertHalf3Double3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble3Half3Double3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf3Double3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (double) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfDouble args = new ArgumentsHalfDouble();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.DOUBLE, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf3Double3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf4Double4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x5edc4100l, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            script.forEach_testConvertDouble4Half4Double4(inV, out);
+            verifyResultsConvertHalf4Double4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Half4Double4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertDouble4Half4Double4(inV, out);
+            verifyResultsConvertHalf4Double4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertDouble4Half4Double4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf4Double4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        double[] arrayOut = new double[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (double) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfDouble args = new ArgumentsHalfDouble();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.DOUBLE, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (!args.out.couldBe(arrayOut[i * 4 + j])) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf4Double4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsHalfChar {
+        public short inV;
+        public double inVDouble;
+        public byte out;
+    }
+
+    private void checkConvertHalf2Char2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xf6709821l, -1.2800000000000000000e+02, 1.2700000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertChar2Half2Char2(inV, out);
+            verifyResultsConvertHalf2Char2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Half2Char2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar2Half2Char2(inV, out);
+            verifyResultsConvertHalf2Char2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar2Half2Char2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf2Char2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (byte) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfChar args = new ArgumentsHalfChar();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        if (args.out != arrayOut[i * 2 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf2Char2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf3Char3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x55785d15l, -1.2800000000000000000e+02, 1.2700000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertChar3Half3Char3(inV, out);
+            verifyResultsConvertHalf3Char3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Half3Char3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar3Half3Char3(inV, out);
+            verifyResultsConvertHalf3Char3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar3Half3Char3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf3Char3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (byte) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfChar args = new ArgumentsHalfChar();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf3Char3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf4Char4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xb4802209l, -1.2800000000000000000e+02, 1.2700000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertChar4Half4Char4(inV, out);
+            verifyResultsConvertHalf4Char4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Half4Char4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertChar4Half4Char4(inV, out);
+            verifyResultsConvertHalf4Char4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertChar4Half4Char4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf4Char4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (byte) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfChar args = new ArgumentsHalfChar();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf4Char4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsHalfUchar {
+        public short inV;
+        public double inVDouble;
+        public byte out;
+    }
+
+    private void checkConvertHalf2Uchar2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x6869a68el, 0.0000000000000000000e+00, 2.5500000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            script.forEach_testConvertUchar2Half2Uchar2(inV, out);
+            verifyResultsConvertHalf2Uchar2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Half2Uchar2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar2Half2Uchar2(inV, out);
+            verifyResultsConvertHalf2Uchar2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar2Half2Uchar2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf2Uchar2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (byte) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfUchar args = new ArgumentsHalfUchar();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        if (args.out != arrayOut[i * 2 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf2Uchar2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf3Uchar3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x5e84c76cl, 0.0000000000000000000e+00, 2.5500000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            script.forEach_testConvertUchar3Half3Uchar3(inV, out);
+            verifyResultsConvertHalf3Uchar3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Half3Uchar3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar3Half3Uchar3(inV, out);
+            verifyResultsConvertHalf3Uchar3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar3Half3Uchar3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf3Uchar3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (byte) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfUchar args = new ArgumentsHalfUchar();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf3Uchar3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf4Uchar4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x549fe84al, 0.0000000000000000000e+00, 2.5500000000000000000e+02);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            script.forEach_testConvertUchar4Half4Uchar4(inV, out);
+            verifyResultsConvertHalf4Uchar4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Half4Uchar4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_8, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUchar4Half4Uchar4(inV, out);
+            verifyResultsConvertHalf4Uchar4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUchar4Half4Uchar4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf4Uchar4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        byte[] arrayOut = new byte[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (byte) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfUchar args = new ArgumentsHalfUchar();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf4Uchar4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsHalfShort {
+        public short inV;
+        public double inVDouble;
+        public short out;
+    }
+
+    private void checkConvertHalf2Short2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xfd7771a7l, -3.2753000000000000000e+04, 3.2752000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertShort2Half2Short2(inV, out);
+            verifyResultsConvertHalf2Short2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Half2Short2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort2Half2Short2(inV, out);
+            verifyResultsConvertHalf2Short2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort2Half2Short2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf2Short2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfShort args = new ArgumentsHalfShort();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        if (args.out != arrayOut[i * 2 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf2Short2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf3Short3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xf3929285l, -3.2753000000000000000e+04, 3.2752000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertShort3Half3Short3(inV, out);
+            verifyResultsConvertHalf3Short3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Half3Short3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort3Half3Short3(inV, out);
+            verifyResultsConvertHalf3Short3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort3Half3Short3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf3Short3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfShort args = new ArgumentsHalfShort();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf3Short3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf4Short4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xe9adb363l, -3.2753000000000000000e+04, 3.2752000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertShort4Half4Short4(inV, out);
+            verifyResultsConvertHalf4Short4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Half4Short4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertShort4Half4Short4(inV, out);
+            verifyResultsConvertHalf4Short4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertShort4Half4Short4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf4Short4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfShort args = new ArgumentsHalfShort();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf4Short4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsHalfUshort {
+        public short inV;
+        public double inVDouble;
+        public short out;
+    }
+
+    private void checkConvertHalf2Ushort2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x224cddf6l, 0.0000000000000000000e+00, 6.5504000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            script.forEach_testConvertUshort2Half2Ushort2(inV, out);
+            verifyResultsConvertHalf2Ushort2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Half2Ushort2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort2Half2Ushort2(inV, out);
+            verifyResultsConvertHalf2Ushort2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort2Half2Ushort2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf2Ushort2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfUshort args = new ArgumentsHalfUshort();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        if (args.out != arrayOut[i * 2 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf2Ushort2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf3Ushort3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x78a86f22l, 0.0000000000000000000e+00, 6.5504000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            script.forEach_testConvertUshort3Half3Ushort3(inV, out);
+            verifyResultsConvertHalf3Ushort3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Half3Ushort3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort3Half3Ushort3(inV, out);
+            verifyResultsConvertHalf3Ushort3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort3Half3Ushort3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf3Ushort3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfUshort args = new ArgumentsHalfUshort();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf3Ushort3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf4Ushort4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xcf04004el, 0.0000000000000000000e+00, 6.5504000000000000000e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            script.forEach_testConvertUshort4Half4Ushort4(inV, out);
+            verifyResultsConvertHalf4Ushort4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Half4Ushort4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUshort4Half4Ushort4(inV, out);
+            verifyResultsConvertHalf4Ushort4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUshort4Half4Ushort4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf4Ushort4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfUshort args = new ArgumentsHalfUshort();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf4Ushort4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsHalfInt {
+        public short inV;
+        public double inVDouble;
+        public int out;
+    }
+
+    private void checkConvertHalf2Int2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xdcfe841al, -2.1464350730000000000e+09, 2.1464350720000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertInt2Half2Int2(inV, out);
+            verifyResultsConvertHalf2Int2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Half2Int2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt2Half2Int2(inV, out);
+            verifyResultsConvertHalf2Int2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt2Half2Int2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf2Int2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (int) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfInt args = new ArgumentsHalfInt();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        if (args.out != arrayOut[i * 2 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf2Int2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf3Int3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x26a69450l, -2.1464350730000000000e+09, 2.1464350720000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertInt3Half3Int3(inV, out);
+            verifyResultsConvertHalf3Int3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Half3Int3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt3Half3Int3(inV, out);
+            verifyResultsConvertHalf3Int3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt3Half3Int3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf3Int3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (int) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfInt args = new ArgumentsHalfInt();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf3Int3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf4Int4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x704ea486l, -2.1464350730000000000e+09, 2.1464350720000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertInt4Half4Int4(inV, out);
+            verifyResultsConvertHalf4Int4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Half4Int4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertInt4Half4Int4(inV, out);
+            verifyResultsConvertHalf4Int4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertInt4Half4Int4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf4Int4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (int) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfInt args = new ArgumentsHalfInt();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf4Int4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsHalfUint {
+        public short inV;
+        public double inVDouble;
+        public int out;
+    }
+
+    private void checkConvertHalf2Uint2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xf45cbe1l, 0.0000000000000000000e+00, 4.2928701440000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            script.forEach_testConvertUint2Half2Uint2(inV, out);
+            verifyResultsConvertHalf2Uint2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Half2Uint2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint2Half2Uint2(inV, out);
+            verifyResultsConvertHalf2Uint2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint2Half2Uint2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf2Uint2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (int) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfUint args = new ArgumentsHalfUint();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        if (args.out != arrayOut[i * 2 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf2Uint2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf3Uint3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x6e4d90d5l, 0.0000000000000000000e+00, 4.2928701440000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            script.forEach_testConvertUint3Half3Uint3(inV, out);
+            verifyResultsConvertHalf3Uint3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Half3Uint3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint3Half3Uint3(inV, out);
+            verifyResultsConvertHalf3Uint3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint3Half3Uint3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf3Uint3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (int) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfUint args = new ArgumentsHalfUint();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf3Uint3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf4Uint4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xcd5555c9l, 0.0000000000000000000e+00, 4.2928701440000000000e+09);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            script.forEach_testConvertUint4Half4Uint4(inV, out);
+            verifyResultsConvertHalf4Uint4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Half4Uint4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_32, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUint4Half4Uint4(inV, out);
+            verifyResultsConvertHalf4Uint4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUint4Half4Uint4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf4Uint4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        int[] arrayOut = new int[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (int) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfUint args = new ArgumentsHalfUint();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf4Uint4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsHalfLong {
+        public short inV;
+        public double inVDouble;
+        public long out;
+    }
+
+    private void checkConvertHalf2Long2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x4a740c9fl, -9.2188684372274053120e+18, 9.2188684372274053120e+18);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertLong2Half2Long2(inV, out);
+            verifyResultsConvertHalf2Long2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Half2Long2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong2Half2Long2(inV, out);
+            verifyResultsConvertHalf2Long2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong2Half2Long2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf2Long2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (long) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfLong args = new ArgumentsHalfLong();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        if (args.out != arrayOut[i * 2 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf2Long2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf3Long3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xa97bd193l, -9.2188684372274053120e+18, 9.2188684372274053120e+18);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertLong3Half3Long3(inV, out);
+            verifyResultsConvertHalf3Long3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Half3Long3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong3Half3Long3(inV, out);
+            verifyResultsConvertHalf3Long3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong3Half3Long3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf3Long3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (long) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfLong args = new ArgumentsHalfLong();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf3Long3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf4Long4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x8839687l, -9.2188684372274053120e+18, 9.2188684372274053120e+18);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertLong4Half4Long4(inV, out);
+            verifyResultsConvertHalf4Long4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Half4Long4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.SIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertLong4Half4Long4(inV, out);
+            verifyResultsConvertHalf4Long4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertLong4Half4Long4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf4Long4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (long) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfLong args = new ArgumentsHalfLong();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf4Long4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsHalfUlong {
+        public short inV;
+        public double inVDouble;
+        public long out;
+    }
+
+    private void checkConvertHalf2Ulong2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xbc6d1b0cl, 0.0000000000000000000e+00, 1.8437736874454810624e+19);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            script.forEach_testConvertUlong2Half2Ulong2(inV, out);
+            verifyResultsConvertHalf2Ulong2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Half2Ulong2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong2Half2Ulong2(inV, out);
+            verifyResultsConvertHalf2Ulong2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong2Half2Ulong2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf2Ulong2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (long) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfUlong args = new ArgumentsHalfUlong();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        if (args.out != arrayOut[i * 2 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf2Ulong2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf3Ulong3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb2883beal, 0.0000000000000000000e+00, 1.8437736874454810624e+19);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            script.forEach_testConvertUlong3Half3Ulong3(inV, out);
+            verifyResultsConvertHalf3Ulong3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Half3Ulong3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong3Half3Ulong3(inV, out);
+            verifyResultsConvertHalf3Ulong3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong3Half3Ulong3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf3Ulong3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (long) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfUlong args = new ArgumentsHalfUlong();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf3Ulong3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertHalf4Ulong4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xa8a35cc8l, 0.0000000000000000000e+00, 1.8437736874454810624e+19);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            script.forEach_testConvertUlong4Half4Ulong4(inV, out);
+            verifyResultsConvertHalf4Ulong4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Half4Ulong4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.UNSIGNED_64, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertUlong4Half4Ulong4(inV, out);
+            verifyResultsConvertHalf4Ulong4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertUlong4Half4Ulong4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertHalf4Ulong4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        long[] arrayOut = new long[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (long) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfUlong args = new ArgumentsHalfUlong();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // 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) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        if (args.out != arrayOut[i * 4 + j]) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertHalf4Ulong4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsFloatHalf {
+        public float inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertFloat2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xaa314c6fl, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testConvertHalf2Float2Half2(inV, out);
+            verifyResultsConvertFloat2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Float2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf2Float2Half2(inV, out);
+            verifyResultsConvertFloat2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Float2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (float) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatHalf args = new ArgumentsFloatHalf();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertFloat2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertFloat3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 3, 0x9391163l, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testConvertHalf3Float3Half3(inV, out);
+            verifyResultsConvertFloat3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Float3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf3Float3Half3(inV, out);
+            verifyResultsConvertFloat3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Float3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (float) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatHalf args = new ArgumentsFloatHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertFloat3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertFloat4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_32, 4, 0x6840d657l, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testConvertHalf4Float4Half4(inV, out);
+            verifyResultsConvertFloat4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Float4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf4Float4Half4(inV, out);
+            verifyResultsConvertFloat4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Float4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertFloat4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        float[] arrayInV = new float[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (float) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsFloatHalf args = new ArgumentsFloatHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertFloat4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsDoubleHalf {
+        public double inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertDouble2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 2, 0x6fc20024l, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testConvertHalf2Double2Half2(inV, out);
+            verifyResultsConvertDouble2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Double2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf2Double2Half2(inV, out);
+            verifyResultsConvertDouble2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Double2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (double) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleHalf args = new ArgumentsDoubleHalf();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertDouble2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertDouble3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 3, 0xcec9c518l, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testConvertHalf3Double3Half3(inV, out);
+            verifyResultsConvertDouble3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Double3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf3Double3Half3(inV, out);
+            verifyResultsConvertDouble3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Double3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (double) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleHalf args = new ArgumentsDoubleHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertDouble3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertDouble4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_64, 4, 0x2dd18a0cl, -3.1129599999999998545e+04, 3.1129599999999998545e+04);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testConvertHalf4Double4Half4(inV, out);
+            verifyResultsConvertDouble4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Double4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf4Double4Half4(inV, out);
+            verifyResultsConvertDouble4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Double4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertDouble4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        double[] arrayInV = new double[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (double) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsDoubleHalf args = new ArgumentsDoubleHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertDouble4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsCharHalf {
+        public byte inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertChar2Half2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 2, 0x55c123afl, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testConvertHalf2Char2Half2(inV, out);
+            verifyResultsConvertChar2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Char2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf2Char2Half2(inV, out);
+            verifyResultsConvertChar2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Char2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (byte) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharHalf args = new ArgumentsCharHalf();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertChar2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertChar3Half3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 3, 0xb4c8e8a3l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testConvertHalf3Char3Half3(inV, out);
+            verifyResultsConvertChar3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Char3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf3Char3Half3(inV, out);
+            verifyResultsConvertChar3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Char3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (byte) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharHalf args = new ArgumentsCharHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertChar3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertChar4Half4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_8, 4, 0x13d0ad97l, true, 7);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testConvertHalf4Char4Half4(inV, out);
+            verifyResultsConvertChar4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Char4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf4Char4Half4(inV, out);
+            verifyResultsConvertChar4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Char4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertChar4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (byte) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsCharHalf args = new ArgumentsCharHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertChar4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsUcharHalf {
+        public byte inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertUchar2Half2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 2, 0xe8433030l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testConvertHalf2Uchar2Half2(inV, out);
+            verifyResultsConvertUchar2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Uchar2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf2Uchar2Half2(inV, out);
+            verifyResultsConvertUchar2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Uchar2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (byte) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharHalf args = new ArgumentsUcharHalf();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertUchar2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertUchar3Half3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 3, 0x474af524l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testConvertHalf3Uchar3Half3(inV, out);
+            verifyResultsConvertUchar3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Uchar3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf3Uchar3Half3(inV, out);
+            verifyResultsConvertUchar3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Uchar3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (byte) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharHalf args = new ArgumentsUcharHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertUchar3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertUchar4Half4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_8, 4, 0xa652ba18l, false, 8);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testConvertHalf4Uchar4Half4(inV, out);
+            verifyResultsConvertUchar4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Uchar4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf4Uchar4Half4(inV, out);
+            verifyResultsConvertUchar4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Uchar4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUchar4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        byte[] arrayInV = new byte[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (byte) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUcharHalf args = new ArgumentsUcharHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertUchar4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsShortHalf {
+        public short inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertShort2Half2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 2, 0x967ebe73l, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testConvertHalf2Short2Half2(inV, out);
+            verifyResultsConvertShort2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Short2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf2Short2Half2(inV, out);
+            verifyResultsConvertShort2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Short2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortHalf args = new ArgumentsShortHalf();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertShort2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertShort3Half3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 3, 0xf5868367l, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testConvertHalf3Short3Half3(inV, out);
+            verifyResultsConvertShort3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Short3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf3Short3Half3(inV, out);
+            verifyResultsConvertShort3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Short3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortHalf args = new ArgumentsShortHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertShort3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertShort4Half4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_16, 4, 0x548e485bl, true, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testConvertHalf4Short4Half4(inV, out);
+            verifyResultsConvertShort4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Short4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf4Short4Half4(inV, out);
+            verifyResultsConvertShort4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Short4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertShort4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsShortHalf args = new ArgumentsShortHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertShort4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsUshortHalf {
+        public short inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertUshort2Half2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 2, 0x3256d81el, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testConvertHalf2Ushort2Half2(inV, out);
+            verifyResultsConvertUshort2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Ushort2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf2Ushort2Half2(inV, out);
+            verifyResultsConvertUshort2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Ushort2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortHalf args = new ArgumentsUshortHalf();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertUshort2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertUshort3Half3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 3, 0x915e9d12l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testConvertHalf3Ushort3Half3(inV, out);
+            verifyResultsConvertUshort3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Ushort3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf3Ushort3Half3(inV, out);
+            verifyResultsConvertUshort3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Ushort3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortHalf args = new ArgumentsUshortHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertUshort3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertUshort4Half4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_16, 4, 0xf0666206l, false, 16);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testConvertHalf4Ushort4Half4(inV, out);
+            verifyResultsConvertUshort4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Ushort4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf4Ushort4Half4(inV, out);
+            verifyResultsConvertUshort4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Ushort4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUshort4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUshortHalf args = new ArgumentsUshortHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertUshort4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsIntHalf {
+        public int inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertInt2Half2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 2, 0xb6fb0cecl, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testConvertHalf2Int2Half2(inV, out);
+            verifyResultsConvertInt2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Int2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf2Int2Half2(inV, out);
+            verifyResultsConvertInt2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Int2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (int) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntHalf args = new ArgumentsIntHalf();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertInt2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertInt3Half3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x1602d1e0l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testConvertHalf3Int3Half3(inV, out);
+            verifyResultsConvertInt3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Int3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf3Int3Half3(inV, out);
+            verifyResultsConvertInt3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Int3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (int) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntHalf args = new ArgumentsIntHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertInt3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertInt4Half4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_32, 4, 0x750a96d4l, true, 31);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testConvertHalf4Int4Half4(inV, out);
+            verifyResultsConvertInt4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Int4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf4Int4Half4(inV, out);
+            verifyResultsConvertInt4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Int4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertInt4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (int) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsIntHalf args = new ArgumentsIntHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertInt4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsUintHalf {
+        public int inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertUint2Half2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 2, 0xb46f30efl, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testConvertHalf2Uint2Half2(inV, out);
+            verifyResultsConvertUint2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Uint2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf2Uint2Half2(inV, out);
+            verifyResultsConvertUint2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Uint2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (int) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintHalf args = new ArgumentsUintHalf();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertUint2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertUint3Half3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 3, 0x1376f5e3l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testConvertHalf3Uint3Half3(inV, out);
+            verifyResultsConvertUint3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Uint3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf3Uint3Half3(inV, out);
+            verifyResultsConvertUint3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Uint3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (int) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintHalf args = new ArgumentsUintHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertUint3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertUint4Half4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_32, 4, 0x727ebad7l, false, 32);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testConvertHalf4Uint4Half4(inV, out);
+            verifyResultsConvertUint4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Uint4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf4Uint4Half4(inV, out);
+            verifyResultsConvertUint4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Uint4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUint4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        int[] arrayInV = new int[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (int) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUintHalf args = new ArgumentsUintHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertUint4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsLongHalf {
+        public long inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertLong2Half2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 2, 0xf4d265b9l, true, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testConvertHalf2Long2Half2(inV, out);
+            verifyResultsConvertLong2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Long2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf2Long2Half2(inV, out);
+            verifyResultsConvertLong2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Long2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (long) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongHalf args = new ArgumentsLongHalf();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertLong2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertLong3Half3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 3, 0x53da2aadl, true, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testConvertHalf3Long3Half3(inV, out);
+            verifyResultsConvertLong3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Long3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf3Long3Half3(inV, out);
+            verifyResultsConvertLong3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Long3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (long) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongHalf args = new ArgumentsLongHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertLong3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertLong4Half4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.SIGNED_64, 4, 0xb2e1efa1l, true, 63);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testConvertHalf4Long4Half4(inV, out);
+            verifyResultsConvertLong4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Long4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf4Long4Half4(inV, out);
+            verifyResultsConvertLong4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Long4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertLong4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (long) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsLongHalf args = new ArgumentsLongHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertLong4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsUlongHalf {
+        public long inV;
+        public Target.Floaty out;
+    }
+
+    private void checkConvertUlong2Half2() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 2, 0x8754723al, false, 64);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testConvertHalf2Ulong2Half2(inV, out);
+            verifyResultsConvertUlong2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Ulong2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf2Ulong2Half2(inV, out);
+            verifyResultsConvertUlong2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf2Ulong2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (long) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongHalf args = new ArgumentsUlongHalf();
+                args.inV = arrayInV[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertUlong2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertUlong3Half3() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 3, 0xe65c372el, false, 64);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testConvertHalf3Ulong3Half3(inV, out);
+            verifyResultsConvertUlong3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Ulong3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf3Ulong3Half3(inV, out);
+            verifyResultsConvertUlong3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf3Ulong3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (long) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongHalf args = new ArgumentsUlongHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertUlong3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkConvertUlong4Half4() {
+        Allocation inV = createRandomIntegerAllocation(mRS, Element.DataType.UNSIGNED_64, 4, 0x4563fc22l, false, 64);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testConvertHalf4Ulong4Half4(inV, out);
+            verifyResultsConvertUlong4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Ulong4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testConvertHalf4Ulong4Half4(inV, out);
+            verifyResultsConvertUlong4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testConvertHalf4Ulong4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsConvertUlong4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        long[] arrayInV = new long[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (long) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsUlongHalf args = new ArgumentsUlongHalf();
+                args.inV = arrayInV[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeConvert(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkConvertUlong4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testConvert() {
         checkConvertFloat2Float2();
         checkConvertFloat3Float3();
@@ -21298,5 +25869,68 @@
         checkConvertUint2Ulong2();
         checkConvertUint3Ulong3();
         checkConvertUint4Ulong4();
+        checkConvertHalf2Half2();
+        checkConvertHalf3Half3();
+        checkConvertHalf4Half4();
+        checkConvertHalf2Float2();
+        checkConvertHalf3Float3();
+        checkConvertHalf4Float4();
+        checkConvertHalf2Double2();
+        checkConvertHalf3Double3();
+        checkConvertHalf4Double4();
+        checkConvertHalf2Char2();
+        checkConvertHalf3Char3();
+        checkConvertHalf4Char4();
+        checkConvertHalf2Uchar2();
+        checkConvertHalf3Uchar3();
+        checkConvertHalf4Uchar4();
+        checkConvertHalf2Short2();
+        checkConvertHalf3Short3();
+        checkConvertHalf4Short4();
+        checkConvertHalf2Ushort2();
+        checkConvertHalf3Ushort3();
+        checkConvertHalf4Ushort4();
+        checkConvertHalf2Int2();
+        checkConvertHalf3Int3();
+        checkConvertHalf4Int4();
+        checkConvertHalf2Uint2();
+        checkConvertHalf3Uint3();
+        checkConvertHalf4Uint4();
+        checkConvertHalf2Long2();
+        checkConvertHalf3Long3();
+        checkConvertHalf4Long4();
+        checkConvertHalf2Ulong2();
+        checkConvertHalf3Ulong3();
+        checkConvertHalf4Ulong4();
+        checkConvertFloat2Half2();
+        checkConvertFloat3Half3();
+        checkConvertFloat4Half4();
+        checkConvertDouble2Half2();
+        checkConvertDouble3Half3();
+        checkConvertDouble4Half4();
+        checkConvertChar2Half2();
+        checkConvertChar3Half3();
+        checkConvertChar4Half4();
+        checkConvertUchar2Half2();
+        checkConvertUchar3Half3();
+        checkConvertUchar4Half4();
+        checkConvertShort2Half2();
+        checkConvertShort3Half3();
+        checkConvertShort4Half4();
+        checkConvertUshort2Half2();
+        checkConvertUshort3Half3();
+        checkConvertUshort4Half4();
+        checkConvertInt2Half2();
+        checkConvertInt3Half3();
+        checkConvertInt4Half4();
+        checkConvertUint2Half2();
+        checkConvertUint3Half3();
+        checkConvertUint4Half4();
+        checkConvertLong2Half2();
+        checkConvertLong3Half3();
+        checkConvertLong4Half4();
+        checkConvertUlong2Half2();
+        checkConvertUlong3Half3();
+        checkConvertUlong4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestConvert.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestConvert.rs
index 6517db9..96fdd99 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestConvert.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestConvert.rs
@@ -1219,3 +1219,255 @@
 ulong4 __attribute__((kernel)) testConvertUlong4Uint4Ulong4(uint4 inV) {
     return convert_ulong4(inV);
 }
+
+half2 __attribute__((kernel)) testConvertHalf2Half2Half2(half2 inV) {
+    return convert_half2(inV);
+}
+
+half3 __attribute__((kernel)) testConvertHalf3Half3Half3(half3 inV) {
+    return convert_half3(inV);
+}
+
+half4 __attribute__((kernel)) testConvertHalf4Half4Half4(half4 inV) {
+    return convert_half4(inV);
+}
+
+float2 __attribute__((kernel)) testConvertFloat2Half2Float2(half2 inV) {
+    return convert_float2(inV);
+}
+
+float3 __attribute__((kernel)) testConvertFloat3Half3Float3(half3 inV) {
+    return convert_float3(inV);
+}
+
+float4 __attribute__((kernel)) testConvertFloat4Half4Float4(half4 inV) {
+    return convert_float4(inV);
+}
+
+double2 __attribute__((kernel)) testConvertDouble2Half2Double2(half2 inV) {
+    return convert_double2(inV);
+}
+
+double3 __attribute__((kernel)) testConvertDouble3Half3Double3(half3 inV) {
+    return convert_double3(inV);
+}
+
+double4 __attribute__((kernel)) testConvertDouble4Half4Double4(half4 inV) {
+    return convert_double4(inV);
+}
+
+char2 __attribute__((kernel)) testConvertChar2Half2Char2(half2 inV) {
+    return convert_char2(inV);
+}
+
+char3 __attribute__((kernel)) testConvertChar3Half3Char3(half3 inV) {
+    return convert_char3(inV);
+}
+
+char4 __attribute__((kernel)) testConvertChar4Half4Char4(half4 inV) {
+    return convert_char4(inV);
+}
+
+uchar2 __attribute__((kernel)) testConvertUchar2Half2Uchar2(half2 inV) {
+    return convert_uchar2(inV);
+}
+
+uchar3 __attribute__((kernel)) testConvertUchar3Half3Uchar3(half3 inV) {
+    return convert_uchar3(inV);
+}
+
+uchar4 __attribute__((kernel)) testConvertUchar4Half4Uchar4(half4 inV) {
+    return convert_uchar4(inV);
+}
+
+short2 __attribute__((kernel)) testConvertShort2Half2Short2(half2 inV) {
+    return convert_short2(inV);
+}
+
+short3 __attribute__((kernel)) testConvertShort3Half3Short3(half3 inV) {
+    return convert_short3(inV);
+}
+
+short4 __attribute__((kernel)) testConvertShort4Half4Short4(half4 inV) {
+    return convert_short4(inV);
+}
+
+ushort2 __attribute__((kernel)) testConvertUshort2Half2Ushort2(half2 inV) {
+    return convert_ushort2(inV);
+}
+
+ushort3 __attribute__((kernel)) testConvertUshort3Half3Ushort3(half3 inV) {
+    return convert_ushort3(inV);
+}
+
+ushort4 __attribute__((kernel)) testConvertUshort4Half4Ushort4(half4 inV) {
+    return convert_ushort4(inV);
+}
+
+int2 __attribute__((kernel)) testConvertInt2Half2Int2(half2 inV) {
+    return convert_int2(inV);
+}
+
+int3 __attribute__((kernel)) testConvertInt3Half3Int3(half3 inV) {
+    return convert_int3(inV);
+}
+
+int4 __attribute__((kernel)) testConvertInt4Half4Int4(half4 inV) {
+    return convert_int4(inV);
+}
+
+uint2 __attribute__((kernel)) testConvertUint2Half2Uint2(half2 inV) {
+    return convert_uint2(inV);
+}
+
+uint3 __attribute__((kernel)) testConvertUint3Half3Uint3(half3 inV) {
+    return convert_uint3(inV);
+}
+
+uint4 __attribute__((kernel)) testConvertUint4Half4Uint4(half4 inV) {
+    return convert_uint4(inV);
+}
+
+long2 __attribute__((kernel)) testConvertLong2Half2Long2(half2 inV) {
+    return convert_long2(inV);
+}
+
+long3 __attribute__((kernel)) testConvertLong3Half3Long3(half3 inV) {
+    return convert_long3(inV);
+}
+
+long4 __attribute__((kernel)) testConvertLong4Half4Long4(half4 inV) {
+    return convert_long4(inV);
+}
+
+ulong2 __attribute__((kernel)) testConvertUlong2Half2Ulong2(half2 inV) {
+    return convert_ulong2(inV);
+}
+
+ulong3 __attribute__((kernel)) testConvertUlong3Half3Ulong3(half3 inV) {
+    return convert_ulong3(inV);
+}
+
+ulong4 __attribute__((kernel)) testConvertUlong4Half4Ulong4(half4 inV) {
+    return convert_ulong4(inV);
+}
+
+half2 __attribute__((kernel)) testConvertHalf2Float2Half2(float2 inV) {
+    return convert_half2(inV);
+}
+
+half3 __attribute__((kernel)) testConvertHalf3Float3Half3(float3 inV) {
+    return convert_half3(inV);
+}
+
+half4 __attribute__((kernel)) testConvertHalf4Float4Half4(float4 inV) {
+    return convert_half4(inV);
+}
+
+half2 __attribute__((kernel)) testConvertHalf2Double2Half2(double2 inV) {
+    return convert_half2(inV);
+}
+
+half3 __attribute__((kernel)) testConvertHalf3Double3Half3(double3 inV) {
+    return convert_half3(inV);
+}
+
+half4 __attribute__((kernel)) testConvertHalf4Double4Half4(double4 inV) {
+    return convert_half4(inV);
+}
+
+half2 __attribute__((kernel)) testConvertHalf2Char2Half2(char2 inV) {
+    return convert_half2(inV);
+}
+
+half3 __attribute__((kernel)) testConvertHalf3Char3Half3(char3 inV) {
+    return convert_half3(inV);
+}
+
+half4 __attribute__((kernel)) testConvertHalf4Char4Half4(char4 inV) {
+    return convert_half4(inV);
+}
+
+half2 __attribute__((kernel)) testConvertHalf2Uchar2Half2(uchar2 inV) {
+    return convert_half2(inV);
+}
+
+half3 __attribute__((kernel)) testConvertHalf3Uchar3Half3(uchar3 inV) {
+    return convert_half3(inV);
+}
+
+half4 __attribute__((kernel)) testConvertHalf4Uchar4Half4(uchar4 inV) {
+    return convert_half4(inV);
+}
+
+half2 __attribute__((kernel)) testConvertHalf2Short2Half2(short2 inV) {
+    return convert_half2(inV);
+}
+
+half3 __attribute__((kernel)) testConvertHalf3Short3Half3(short3 inV) {
+    return convert_half3(inV);
+}
+
+half4 __attribute__((kernel)) testConvertHalf4Short4Half4(short4 inV) {
+    return convert_half4(inV);
+}
+
+half2 __attribute__((kernel)) testConvertHalf2Ushort2Half2(ushort2 inV) {
+    return convert_half2(inV);
+}
+
+half3 __attribute__((kernel)) testConvertHalf3Ushort3Half3(ushort3 inV) {
+    return convert_half3(inV);
+}
+
+half4 __attribute__((kernel)) testConvertHalf4Ushort4Half4(ushort4 inV) {
+    return convert_half4(inV);
+}
+
+half2 __attribute__((kernel)) testConvertHalf2Int2Half2(int2 inV) {
+    return convert_half2(inV);
+}
+
+half3 __attribute__((kernel)) testConvertHalf3Int3Half3(int3 inV) {
+    return convert_half3(inV);
+}
+
+half4 __attribute__((kernel)) testConvertHalf4Int4Half4(int4 inV) {
+    return convert_half4(inV);
+}
+
+half2 __attribute__((kernel)) testConvertHalf2Uint2Half2(uint2 inV) {
+    return convert_half2(inV);
+}
+
+half3 __attribute__((kernel)) testConvertHalf3Uint3Half3(uint3 inV) {
+    return convert_half3(inV);
+}
+
+half4 __attribute__((kernel)) testConvertHalf4Uint4Half4(uint4 inV) {
+    return convert_half4(inV);
+}
+
+half2 __attribute__((kernel)) testConvertHalf2Long2Half2(long2 inV) {
+    return convert_half2(inV);
+}
+
+half3 __attribute__((kernel)) testConvertHalf3Long3Half3(long3 inV) {
+    return convert_half3(inV);
+}
+
+half4 __attribute__((kernel)) testConvertHalf4Long4Half4(long4 inV) {
+    return convert_half4(inV);
+}
+
+half2 __attribute__((kernel)) testConvertHalf2Ulong2Half2(ulong2 inV) {
+    return convert_half2(inV);
+}
+
+half3 __attribute__((kernel)) testConvertHalf3Ulong3Half3(ulong3 inV) {
+    return convert_half3(inV);
+}
+
+half4 __attribute__((kernel)) testConvertHalf4Ulong4Half4(ulong4 inV) {
+    return convert_half4(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCopysign.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCopysign.java
index be650c5..e1194fd 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCopysign.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCopysign.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inMagnitudeValue;
+        public double inMagnitudeValueDouble;
+        public short inSignValue;
+        public double inSignValueDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkCopysignHalfHalfHalf() {
+        Allocation inMagnitudeValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x9e87c031l, false);
+        Allocation inSignValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x523236fcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInSignValue(inSignValue);
+            script.forEach_testCopysignHalfHalfHalf(inMagnitudeValue, out);
+            verifyResultsCopysignHalfHalfHalf(inMagnitudeValue, inSignValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInSignValue(inSignValue);
+            scriptRelaxed.forEach_testCopysignHalfHalfHalf(inMagnitudeValue, out);
+            verifyResultsCopysignHalfHalfHalf(inMagnitudeValue, inSignValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCopysignHalfHalfHalf(Allocation inMagnitudeValue, Allocation inSignValue, Allocation out, boolean relaxed) {
+        short[] arrayInMagnitudeValue = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMagnitudeValue, (short) 42);
+        inMagnitudeValue.copyTo(arrayInMagnitudeValue);
+        short[] arrayInSignValue = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInSignValue, (short) 42);
+        inSignValue.copyTo(arrayInSignValue);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inMagnitudeValue = arrayInMagnitudeValue[i];
+                args.inMagnitudeValueDouble = Float16Utils.convertFloat16ToDouble(args.inMagnitudeValue);
+                args.inSignValue = arrayInSignValue[i];
+                args.inSignValueDouble = Float16Utils.convertFloat16ToDouble(args.inSignValue);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCopysign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inMagnitudeValue: ");
+                        appendVariableToMessage(message, args.inMagnitudeValue);
+                        message.append("\n");
+                        message.append("Input inSignValue: ");
+                        appendVariableToMessage(message, args.inSignValue);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCopysignHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCopysignHalf2Half2Half2() {
+        Allocation inMagnitudeValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x5c704fabl, false);
+        Allocation inSignValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xa73ce4cal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInSignValue(inSignValue);
+            script.forEach_testCopysignHalf2Half2Half2(inMagnitudeValue, out);
+            verifyResultsCopysignHalf2Half2Half2(inMagnitudeValue, inSignValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInSignValue(inSignValue);
+            scriptRelaxed.forEach_testCopysignHalf2Half2Half2(inMagnitudeValue, out);
+            verifyResultsCopysignHalf2Half2Half2(inMagnitudeValue, inSignValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCopysignHalf2Half2Half2(Allocation inMagnitudeValue, Allocation inSignValue, Allocation out, boolean relaxed) {
+        short[] arrayInMagnitudeValue = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInMagnitudeValue, (short) 42);
+        inMagnitudeValue.copyTo(arrayInMagnitudeValue);
+        short[] arrayInSignValue = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInSignValue, (short) 42);
+        inSignValue.copyTo(arrayInSignValue);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inMagnitudeValue = arrayInMagnitudeValue[i * 2 + j];
+                args.inMagnitudeValueDouble = Float16Utils.convertFloat16ToDouble(args.inMagnitudeValue);
+                args.inSignValue = arrayInSignValue[i * 2 + j];
+                args.inSignValueDouble = Float16Utils.convertFloat16ToDouble(args.inSignValue);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCopysign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inMagnitudeValue: ");
+                        appendVariableToMessage(message, args.inMagnitudeValue);
+                        message.append("\n");
+                        message.append("Input inSignValue: ");
+                        appendVariableToMessage(message, args.inSignValue);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCopysignHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCopysignHalf3Half3Half3() {
+        Allocation inMagnitudeValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x38955c0l, false);
+        Allocation inSignValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xf2af1539l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInSignValue(inSignValue);
+            script.forEach_testCopysignHalf3Half3Half3(inMagnitudeValue, out);
+            verifyResultsCopysignHalf3Half3Half3(inMagnitudeValue, inSignValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInSignValue(inSignValue);
+            scriptRelaxed.forEach_testCopysignHalf3Half3Half3(inMagnitudeValue, out);
+            verifyResultsCopysignHalf3Half3Half3(inMagnitudeValue, inSignValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCopysignHalf3Half3Half3(Allocation inMagnitudeValue, Allocation inSignValue, Allocation out, boolean relaxed) {
+        short[] arrayInMagnitudeValue = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMagnitudeValue, (short) 42);
+        inMagnitudeValue.copyTo(arrayInMagnitudeValue);
+        short[] arrayInSignValue = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInSignValue, (short) 42);
+        inSignValue.copyTo(arrayInSignValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inMagnitudeValue = arrayInMagnitudeValue[i * 4 + j];
+                args.inMagnitudeValueDouble = Float16Utils.convertFloat16ToDouble(args.inMagnitudeValue);
+                args.inSignValue = arrayInSignValue[i * 4 + j];
+                args.inSignValueDouble = Float16Utils.convertFloat16ToDouble(args.inSignValue);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCopysign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inMagnitudeValue: ");
+                        appendVariableToMessage(message, args.inMagnitudeValue);
+                        message.append("\n");
+                        message.append("Input inSignValue: ");
+                        appendVariableToMessage(message, args.inSignValue);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCopysignHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCopysignHalf4Half4Half4() {
+        Allocation inMagnitudeValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xaaa25bd5l, false);
+        Allocation inSignValue = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x3e2145a8l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInSignValue(inSignValue);
+            script.forEach_testCopysignHalf4Half4Half4(inMagnitudeValue, out);
+            verifyResultsCopysignHalf4Half4Half4(inMagnitudeValue, inSignValue, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInSignValue(inSignValue);
+            scriptRelaxed.forEach_testCopysignHalf4Half4Half4(inMagnitudeValue, out);
+            verifyResultsCopysignHalf4Half4Half4(inMagnitudeValue, inSignValue, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCopysignHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCopysignHalf4Half4Half4(Allocation inMagnitudeValue, Allocation inSignValue, Allocation out, boolean relaxed) {
+        short[] arrayInMagnitudeValue = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMagnitudeValue, (short) 42);
+        inMagnitudeValue.copyTo(arrayInMagnitudeValue);
+        short[] arrayInSignValue = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInSignValue, (short) 42);
+        inSignValue.copyTo(arrayInSignValue);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inMagnitudeValue = arrayInMagnitudeValue[i * 4 + j];
+                args.inMagnitudeValueDouble = Float16Utils.convertFloat16ToDouble(args.inMagnitudeValue);
+                args.inSignValue = arrayInSignValue[i * 4 + j];
+                args.inSignValueDouble = Float16Utils.convertFloat16ToDouble(args.inSignValue);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCopysign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inMagnitudeValue: ");
+                        appendVariableToMessage(message, args.inMagnitudeValue);
+                        message.append("\n");
+                        message.append("Input inSignValue: ");
+                        appendVariableToMessage(message, args.inSignValue);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCopysignHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testCopysign() {
         checkCopysignFloatFloatFloat();
         checkCopysignFloat2Float2Float2();
         checkCopysignFloat3Float3Float3();
         checkCopysignFloat4Float4Float4();
+        checkCopysignHalfHalfHalf();
+        checkCopysignHalf2Half2Half2();
+        checkCopysignHalf3Half3Half3();
+        checkCopysignHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCopysign.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCopysign.rs
index 009ec6b..f5e57f8 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCopysign.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCopysign.rs
@@ -40,3 +40,23 @@
     float4 inSignValue = rsGetElementAt_float4(gAllocInSignValue, x);
     return copysign(inMagnitudeValue, inSignValue);
 }
+
+half __attribute__((kernel)) testCopysignHalfHalfHalf(half inMagnitudeValue, unsigned int x) {
+    half inSignValue = rsGetElementAt_half(gAllocInSignValue, x);
+    return copysign(inMagnitudeValue, inSignValue);
+}
+
+half2 __attribute__((kernel)) testCopysignHalf2Half2Half2(half2 inMagnitudeValue, unsigned int x) {
+    half2 inSignValue = rsGetElementAt_half2(gAllocInSignValue, x);
+    return copysign(inMagnitudeValue, inSignValue);
+}
+
+half3 __attribute__((kernel)) testCopysignHalf3Half3Half3(half3 inMagnitudeValue, unsigned int x) {
+    half3 inSignValue = rsGetElementAt_half3(gAllocInSignValue, x);
+    return copysign(inMagnitudeValue, inSignValue);
+}
+
+half4 __attribute__((kernel)) testCopysignHalf4Half4Half4(half4 inMagnitudeValue, unsigned int x) {
+    half4 inSignValue = rsGetElementAt_half4(gAllocInSignValue, x);
+    return copysign(inMagnitudeValue, inSignValue);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCosh.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCosh.java
index 0740285..8b0755f 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCosh.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCosh.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkCoshHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x609e2d2al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testCoshHalfHalf(inV, out);
+            verifyResultsCoshHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testCoshHalfHalf(inV, out);
+            verifyResultsCoshHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCoshHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCoshHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCoshHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x7dab427cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testCoshHalf2Half2(inV, out);
+            verifyResultsCoshHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testCoshHalf2Half2(inV, out);
+            verifyResultsCoshHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCoshHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCoshHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCoshHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xdcb30770l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testCoshHalf3Half3(inV, out);
+            verifyResultsCoshHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testCoshHalf3Half3(inV, out);
+            verifyResultsCoshHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCoshHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCoshHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCoshHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x3bbacc64l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testCoshHalf4Half4(inV, out);
+            verifyResultsCoshHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testCoshHalf4Half4(inV, out);
+            verifyResultsCoshHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCoshHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCoshHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCoshHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testCosh() {
         checkCoshFloatFloat();
         checkCoshFloat2Float2();
         checkCoshFloat3Float3();
         checkCoshFloat4Float4();
+        checkCoshHalfHalf();
+        checkCoshHalf2Half2();
+        checkCoshHalf3Half3();
+        checkCoshHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCosh.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCosh.rs
index 242f119..01543f3 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCosh.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCosh.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testCoshFloat4Float4(float4 inV) {
     return cosh(inV);
 }
+
+half __attribute__((kernel)) testCoshHalfHalf(half inV) {
+    return cosh(inV);
+}
+
+half2 __attribute__((kernel)) testCoshHalf2Half2(half2 inV) {
+    return cosh(inV);
+}
+
+half3 __attribute__((kernel)) testCoshHalf3Half3(half3 inV) {
+    return cosh(inV);
+}
+
+half4 __attribute__((kernel)) testCoshHalf4Half4(half4 inV) {
+    return cosh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCospi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCospi.java
index dab5d2f..4776433 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCospi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCospi.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkCospiHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x252f4343l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testCospiHalfHalf(inV, out);
+            verifyResultsCospiHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testCospiHalfHalf(inV, out);
+            verifyResultsCospiHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCospiHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCospiHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCospiHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x3993dd0dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testCospiHalf2Half2(inV, out);
+            verifyResultsCospiHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testCospiHalf2Half2(inV, out);
+            verifyResultsCospiHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCospiHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCospiHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCospiHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x989ba201l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testCospiHalf3Half3(inV, out);
+            verifyResultsCospiHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testCospiHalf3Half3(inV, out);
+            verifyResultsCospiHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCospiHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCospiHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkCospiHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xf7a366f5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testCospiHalf4Half4(inV, out);
+            verifyResultsCospiHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testCospiHalf4Half4(inV, out);
+            verifyResultsCospiHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testCospiHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsCospiHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkCospiHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testCospi() {
         checkCospiFloatFloat();
         checkCospiFloat2Float2();
         checkCospiFloat3Float3();
         checkCospiFloat4Float4();
+        checkCospiHalfHalf();
+        checkCospiHalf2Half2();
+        checkCospiHalf3Half3();
+        checkCospiHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCospi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCospi.rs
index f46ead0..1ebba63 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCospi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestCospi.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testCospiFloat4Float4(float4 inV) {
     return cospi(inV);
 }
+
+half __attribute__((kernel)) testCospiHalfHalf(half inV) {
+    return cospi(inV);
+}
+
+half2 __attribute__((kernel)) testCospiHalf2Half2(half2 inV) {
+    return cospi(inV);
+}
+
+half3 __attribute__((kernel)) testCospiHalf3Half3(half3 inV) {
+    return cospi(inV);
+}
+
+half4 __attribute__((kernel)) testCospiHalf4Half4(half4 inV) {
+    return cospi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestDegrees.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestDegrees.java
index c5928b7..2020e2b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestDegrees.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestDegrees.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkDegreesHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x17e3b944l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testDegreesHalfHalf(inV, out);
+            verifyResultsDegreesHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testDegreesHalfHalf(inV, out);
+            verifyResultsDegreesHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDegreesHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeDegrees(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkDegreesHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkDegreesHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x32fc2a46l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testDegreesHalf2Half2(inV, out);
+            verifyResultsDegreesHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testDegreesHalf2Half2(inV, out);
+            verifyResultsDegreesHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDegreesHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeDegrees(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkDegreesHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkDegreesHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x9203ef3al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testDegreesHalf3Half3(inV, out);
+            verifyResultsDegreesHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testDegreesHalf3Half3(inV, out);
+            verifyResultsDegreesHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDegreesHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeDegrees(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkDegreesHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkDegreesHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xf10bb42el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testDegreesHalf4Half4(inV, out);
+            verifyResultsDegreesHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testDegreesHalf4Half4(inV, out);
+            verifyResultsDegreesHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testDegreesHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsDegreesHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeDegrees(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkDegreesHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testDegrees() {
         checkDegreesFloatFloat();
         checkDegreesFloat2Float2();
         checkDegreesFloat3Float3();
         checkDegreesFloat4Float4();
+        checkDegreesHalfHalf();
+        checkDegreesHalf2Half2();
+        checkDegreesHalf3Half3();
+        checkDegreesHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestDegrees.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestDegrees.rs
index f40b5a4..fb54ef1 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestDegrees.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestDegrees.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testDegreesFloat4Float4(float4 inV) {
     return degrees(inV);
 }
+
+half __attribute__((kernel)) testDegreesHalfHalf(half inV) {
+    return degrees(inV);
+}
+
+half2 __attribute__((kernel)) testDegreesHalf2Half2(half2 inV) {
+    return degrees(inV);
+}
+
+half3 __attribute__((kernel)) testDegreesHalf3Half3(half3 inV) {
+    return degrees(inV);
+}
+
+half4 __attribute__((kernel)) testDegreesHalf4Half4(half4 inV) {
+    return degrees(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErf.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErf.java
index b36c5e5..fee259a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErf.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErf.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkErfHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x9cc93d62l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testErfHalfHalf(inV, out);
+            verifyResultsErfHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testErfHalfHalf(inV, out);
+            verifyResultsErfHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeErf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkErfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkErfHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x10b366f4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testErfHalf2Half2(inV, out);
+            verifyResultsErfHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testErfHalf2Half2(inV, out);
+            verifyResultsErfHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeErf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkErfHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkErfHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x6fbb2be8l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testErfHalf3Half3(inV, out);
+            verifyResultsErfHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testErfHalf3Half3(inV, out);
+            verifyResultsErfHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeErf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkErfHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkErfHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xcec2f0dcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testErfHalf4Half4(inV, out);
+            verifyResultsErfHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testErfHalf4Half4(inV, out);
+            verifyResultsErfHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeErf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkErfHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testErf() {
         checkErfFloatFloat();
         checkErfFloat2Float2();
         checkErfFloat3Float3();
         checkErfFloat4Float4();
+        checkErfHalfHalf();
+        checkErfHalf2Half2();
+        checkErfHalf3Half3();
+        checkErfHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErf.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErf.rs
index c7ff5b2..8a07a07 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErf.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErf.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testErfFloat4Float4(float4 inV) {
     return erf(inV);
 }
+
+half __attribute__((kernel)) testErfHalfHalf(half inV) {
+    return erf(inV);
+}
+
+half2 __attribute__((kernel)) testErfHalf2Half2(half2 inV) {
+    return erf(inV);
+}
+
+half3 __attribute__((kernel)) testErfHalf3Half3(half3 inV) {
+    return erf(inV);
+}
+
+half4 __attribute__((kernel)) testErfHalf4Half4(half4 inV) {
+    return erf(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErfc.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErfc.java
index 8b73a82..be9d6e7 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErfc.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErfc.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkErfcHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xa498d5f1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testErfcHalfHalf(inV, out);
+            verifyResultsErfcHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testErfcHalfHalf(inV, out);
+            verifyResultsErfcHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfcHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeErfc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkErfcHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkErfcHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x7b1847cbl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testErfcHalf2Half2(inV, out);
+            verifyResultsErfcHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testErfcHalf2Half2(inV, out);
+            verifyResultsErfcHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfcHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeErfc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkErfcHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkErfcHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xda200cbfl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testErfcHalf3Half3(inV, out);
+            verifyResultsErfcHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testErfcHalf3Half3(inV, out);
+            verifyResultsErfcHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfcHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeErfc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkErfcHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkErfcHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x3927d1b3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testErfcHalf4Half4(inV, out);
+            verifyResultsErfcHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testErfcHalf4Half4(inV, out);
+            verifyResultsErfcHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testErfcHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsErfcHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeErfc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkErfcHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testErfc() {
         checkErfcFloatFloat();
         checkErfcFloat2Float2();
         checkErfcFloat3Float3();
         checkErfcFloat4Float4();
+        checkErfcHalfHalf();
+        checkErfcHalf2Half2();
+        checkErfcHalf3Half3();
+        checkErfcHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErfc.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErfc.rs
index 6bf5d39..037df91 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErfc.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestErfc.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testErfcFloat4Float4(float4 inV) {
     return erfc(inV);
 }
+
+half __attribute__((kernel)) testErfcHalfHalf(half inV) {
+    return erfc(inV);
+}
+
+half2 __attribute__((kernel)) testErfcHalf2Half2(half2 inV) {
+    return erfc(inV);
+}
+
+half3 __attribute__((kernel)) testErfcHalf3Half3(half3 inV) {
+    return erfc(inV);
+}
+
+half4 __attribute__((kernel)) testErfcHalf4Half4(half4 inV) {
+    return erfc(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp.java
index 556331d..53e468c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkExpHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xd81f8cc6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testExpHalfHalf(inV, out);
+            verifyResultsExpHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testExpHalfHalf(inV, out);
+            verifyResultsExpHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExpHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkExpHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xa316d038l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testExpHalf2Half2(inV, out);
+            verifyResultsExpHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testExpHalf2Half2(inV, out);
+            verifyResultsExpHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExpHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkExpHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x21e952cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testExpHalf3Half3(inV, out);
+            verifyResultsExpHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testExpHalf3Half3(inV, out);
+            verifyResultsExpHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExpHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkExpHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x61265a20l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testExpHalf4Half4(inV, out);
+            verifyResultsExpHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testExpHalf4Half4(inV, out);
+            verifyResultsExpHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExpHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testExp() {
         checkExpFloatFloat();
         checkExpFloat2Float2();
         checkExpFloat3Float3();
         checkExpFloat4Float4();
+        checkExpHalfHalf();
+        checkExpHalf2Half2();
+        checkExpHalf3Half3();
+        checkExpHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp.rs
index 8c15bcc..2a9d5e9 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testExpFloat4Float4(float4 inV) {
     return exp(inV);
 }
+
+half __attribute__((kernel)) testExpHalfHalf(half inV) {
+    return exp(inV);
+}
+
+half2 __attribute__((kernel)) testExpHalf2Half2(half2 inV) {
+    return exp(inV);
+}
+
+half3 __attribute__((kernel)) testExpHalf3Half3(half3 inV) {
+    return exp(inV);
+}
+
+half4 __attribute__((kernel)) testExpHalf4Half4(half4 inV) {
+    return exp(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp10.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp10.java
index 12a1f8a..aa22da8 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp10.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp10.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkExp10HalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe916fd3fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testExp10HalfHalf(inV, out);
+            verifyResultsExp10HalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10HalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testExp10HalfHalf(inV, out);
+            verifyResultsExp10HalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10HalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp10HalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExp10HalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkExp10Half2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x2e422a29l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testExp10Half2Half2(inV, out);
+            verifyResultsExp10Half2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testExp10Half2Half2(inV, out);
+            verifyResultsExp10Half2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp10Half2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExp10Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkExp10Half3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x8d49ef1dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testExp10Half3Half3(inV, out);
+            verifyResultsExp10Half3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testExp10Half3Half3(inV, out);
+            verifyResultsExp10Half3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp10Half3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExp10Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkExp10Half4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xec51b411l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testExp10Half4Half4(inV, out);
+            verifyResultsExp10Half4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testExp10Half4Half4(inV, out);
+            verifyResultsExp10Half4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp10Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp10Half4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExp10Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testExp10() {
         checkExp10FloatFloat();
         checkExp10Float2Float2();
         checkExp10Float3Float3();
         checkExp10Float4Float4();
+        checkExp10HalfHalf();
+        checkExp10Half2Half2();
+        checkExp10Half3Half3();
+        checkExp10Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp10.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp10.rs
index 4922768..dc30f5a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp10.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp10.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testExp10Float4Float4(float4 inV) {
     return exp10(inV);
 }
+
+half __attribute__((kernel)) testExp10HalfHalf(half inV) {
+    return exp10(inV);
+}
+
+half2 __attribute__((kernel)) testExp10Half2Half2(half2 inV) {
+    return exp10(inV);
+}
+
+half3 __attribute__((kernel)) testExp10Half3Half3(half3 inV) {
+    return exp10(inV);
+}
+
+half4 __attribute__((kernel)) testExp10Half4Half4(half4 inV) {
+    return exp10(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp2.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp2.java
index a8d7520..abc7f9d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp2.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp2.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkExp2HalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe270827al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testExp2HalfHalf(inV, out);
+            verifyResultsExp2HalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2HalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testExp2HalfHalf(inV, out);
+            verifyResultsExp2HalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2HalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp2HalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExp2HalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkExp2Half2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x25d5714cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testExp2Half2Half2(inV, out);
+            verifyResultsExp2Half2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testExp2Half2Half2(inV, out);
+            verifyResultsExp2Half2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp2Half2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExp2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkExp2Half3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x84dd3640l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testExp2Half3Half3(inV, out);
+            verifyResultsExp2Half3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testExp2Half3Half3(inV, out);
+            verifyResultsExp2Half3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp2Half3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExp2Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkExp2Half4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xe3e4fb34l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testExp2Half4Half4(inV, out);
+            verifyResultsExp2Half4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testExp2Half4Half4(inV, out);
+            verifyResultsExp2Half4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExp2Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExp2Half4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExp2Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testExp2() {
         checkExp2FloatFloat();
         checkExp2Float2Float2();
         checkExp2Float3Float3();
         checkExp2Float4Float4();
+        checkExp2HalfHalf();
+        checkExp2Half2Half2();
+        checkExp2Half3Half3();
+        checkExp2Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp2.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp2.rs
index 1f02f27..47007d4 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp2.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExp2.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testExp2Float4Float4(float4 inV) {
     return exp2(inV);
 }
+
+half __attribute__((kernel)) testExp2HalfHalf(half inV) {
+    return exp2(inV);
+}
+
+half2 __attribute__((kernel)) testExp2Half2Half2(half2 inV) {
+    return exp2(inV);
+}
+
+half3 __attribute__((kernel)) testExp2Half3Half3(half3 inV) {
+    return exp2(inV);
+}
+
+half4 __attribute__((kernel)) testExp2Half4Half4(half4 inV) {
+    return exp2(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExpm1.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExpm1.java
index 2b72471..e10b400 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExpm1.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExpm1.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkExpm1HalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x45f98ceel, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testExpm1HalfHalf(inV, out);
+            verifyResultsExpm1HalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1HalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testExpm1HalfHalf(inV, out);
+            verifyResultsExpm1HalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1HalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpm1HalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExpm1(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExpm1HalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkExpm1Half2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xea1f120l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testExpm1Half2Half2(inV, out);
+            verifyResultsExpm1Half2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testExpm1Half2Half2(inV, out);
+            verifyResultsExpm1Half2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpm1Half2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExpm1(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExpm1Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkExpm1Half3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x6da9b614l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testExpm1Half3Half3(inV, out);
+            verifyResultsExpm1Half3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testExpm1Half3Half3(inV, out);
+            verifyResultsExpm1Half3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpm1Half3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExpm1(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExpm1Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkExpm1Half4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xccb17b08l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testExpm1Half4Half4(inV, out);
+            verifyResultsExpm1Half4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testExpm1Half4Half4(inV, out);
+            verifyResultsExpm1Half4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testExpm1Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsExpm1Half4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeExpm1(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkExpm1Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testExpm1() {
         checkExpm1FloatFloat();
         checkExpm1Float2Float2();
         checkExpm1Float3Float3();
         checkExpm1Float4Float4();
+        checkExpm1HalfHalf();
+        checkExpm1Half2Half2();
+        checkExpm1Half3Half3();
+        checkExpm1Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExpm1.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExpm1.rs
index 5a084cf..3b6f869 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExpm1.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestExpm1.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testExpm1Float4Float4(float4 inV) {
     return expm1(inV);
 }
+
+half __attribute__((kernel)) testExpm1HalfHalf(half inV) {
+    return expm1(inV);
+}
+
+half2 __attribute__((kernel)) testExpm1Half2Half2(half2 inV) {
+    return expm1(inV);
+}
+
+half3 __attribute__((kernel)) testExpm1Half3Half3(half3 inV) {
+    return expm1(inV);
+}
+
+half4 __attribute__((kernel)) testExpm1Half4Half4(half4 inV) {
+    return expm1(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFabs.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFabs.java
index 3421871..50d468b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFabs.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFabs.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkFabsHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe268991bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testFabsHalfHalf(inV, out);
+            verifyResultsFabsHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testFabsHalfHalf(inV, out);
+            verifyResultsFabsHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFabsHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFabs(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFabsHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFabsHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xecb0e225l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testFabsHalf2Half2(inV, out);
+            verifyResultsFabsHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testFabsHalf2Half2(inV, out);
+            verifyResultsFabsHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFabsHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFabs(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFabsHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFabsHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x4bb8a719l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testFabsHalf3Half3(inV, out);
+            verifyResultsFabsHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testFabsHalf3Half3(inV, out);
+            verifyResultsFabsHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFabsHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFabs(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFabsHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFabsHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xaac06c0dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testFabsHalf4Half4(inV, out);
+            verifyResultsFabsHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testFabsHalf4Half4(inV, out);
+            verifyResultsFabsHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFabsHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFabsHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFabs(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFabsHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testFabs() {
         checkFabsFloatFloat();
         checkFabsFloat2Float2();
         checkFabsFloat3Float3();
         checkFabsFloat4Float4();
+        checkFabsHalfHalf();
+        checkFabsHalf2Half2();
+        checkFabsHalf3Half3();
+        checkFabsHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFabs.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFabs.rs
index b54e891..6266b63 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFabs.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFabs.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testFabsFloat4Float4(float4 inV) {
     return fabs(inV);
 }
+
+half __attribute__((kernel)) testFabsHalfHalf(half inV) {
+    return fabs(inV);
+}
+
+half2 __attribute__((kernel)) testFabsHalf2Half2(half2 inV) {
+    return fabs(inV);
+}
+
+half3 __attribute__((kernel)) testFabsHalf3Half3(half3 inV) {
+    return fabs(inV);
+}
+
+half4 __attribute__((kernel)) testFabsHalf4Half4(half4 inV) {
+    return fabs(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFdim.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFdim.java
index 1dea48f..ed9ed1e 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFdim.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFdim.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inA;
+        public double inADouble;
+        public short inB;
+        public double inBDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkFdimHalfHalfHalf() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x3357407dl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x3357407el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFdimHalfHalfHalf(inA, out);
+            verifyResultsFdimHalfHalfHalf(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFdimHalfHalfHalf(inA, out);
+            verifyResultsFdimHalfHalfHalf(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFdimHalfHalfHalf(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFdim(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFdimHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFdimHalf2Half2Half2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xfa8ab75bl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xfa8ab75cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFdimHalf2Half2Half2(inA, out);
+            verifyResultsFdimHalf2Half2Half2(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFdimHalf2Half2Half2(inA, out);
+            verifyResultsFdimHalf2Half2Half2(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFdimHalf2Half2Half2(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 2 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 2 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFdim(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFdimHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFdimHalf3Half3Half3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x5929c82al, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x5929c82bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFdimHalf3Half3Half3(inA, out);
+            verifyResultsFdimHalf3Half3Half3(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFdimHalf3Half3Half3(inA, out);
+            verifyResultsFdimHalf3Half3Half3(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFdimHalf3Half3Half3(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFdim(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFdimHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFdimHalf4Half4Half4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xb7c8d8f9l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xb7c8d8fal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFdimHalf4Half4Half4(inA, out);
+            verifyResultsFdimHalf4Half4Half4(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFdimHalf4Half4Half4(inA, out);
+            verifyResultsFdimHalf4Half4Half4(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFdimHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFdimHalf4Half4Half4(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFdim(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFdimHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testFdim() {
         checkFdimFloatFloatFloat();
         checkFdimFloat2Float2Float2();
         checkFdimFloat3Float3Float3();
         checkFdimFloat4Float4Float4();
+        checkFdimHalfHalfHalf();
+        checkFdimHalf2Half2Half2();
+        checkFdimHalf3Half3Half3();
+        checkFdimHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFdim.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFdim.rs
index 3d987e8..f9c8852 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFdim.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFdim.rs
@@ -40,3 +40,23 @@
     float4 inB = rsGetElementAt_float4(gAllocInB, x);
     return fdim(inA, inB);
 }
+
+half __attribute__((kernel)) testFdimHalfHalfHalf(half inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return fdim(inA, inB);
+}
+
+half2 __attribute__((kernel)) testFdimHalf2Half2Half2(half2 inA, unsigned int x) {
+    half2 inB = rsGetElementAt_half2(gAllocInB, x);
+    return fdim(inA, inB);
+}
+
+half3 __attribute__((kernel)) testFdimHalf3Half3Half3(half3 inA, unsigned int x) {
+    half3 inB = rsGetElementAt_half3(gAllocInB, x);
+    return fdim(inA, inB);
+}
+
+half4 __attribute__((kernel)) testFdimHalf4Half4Half4(half4 inA, unsigned int x) {
+    half4 inB = rsGetElementAt_half4(gAllocInB, x);
+    return fdim(inA, inB);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFma.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFma.java
index cd02537..80d387b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFma.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFma.java
@@ -400,10 +400,404 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalfHalf {
+        public short inMultiplicand1;
+        public double inMultiplicand1Double;
+        public short inMultiplicand2;
+        public double inMultiplicand2Double;
+        public short inOffset;
+        public double inOffsetDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkFmaHalfHalfHalfHalf() {
+        Allocation inMultiplicand1 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xd7c6a182l, false);
+        Allocation inMultiplicand2 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xd7c6a183l, false);
+        Allocation inOffset = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x663f87al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInMultiplicand2(inMultiplicand2);
+            script.set_gAllocInOffset(inOffset);
+            script.forEach_testFmaHalfHalfHalfHalf(inMultiplicand1, out);
+            verifyResultsFmaHalfHalfHalfHalf(inMultiplicand1, inMultiplicand2, inOffset, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaHalfHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMultiplicand2(inMultiplicand2);
+            scriptRelaxed.set_gAllocInOffset(inOffset);
+            scriptRelaxed.forEach_testFmaHalfHalfHalfHalf(inMultiplicand1, out);
+            verifyResultsFmaHalfHalfHalfHalf(inMultiplicand1, inMultiplicand2, inOffset, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaHalfHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaHalfHalfHalfHalf(Allocation inMultiplicand1, Allocation inMultiplicand2, Allocation inOffset, Allocation out, boolean relaxed) {
+        short[] arrayInMultiplicand1 = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMultiplicand1, (short) 42);
+        inMultiplicand1.copyTo(arrayInMultiplicand1);
+        short[] arrayInMultiplicand2 = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMultiplicand2, (short) 42);
+        inMultiplicand2.copyTo(arrayInMultiplicand2);
+        short[] arrayInOffset = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInOffset, (short) 42);
+        inOffset.copyTo(arrayInOffset);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inMultiplicand1 = arrayInMultiplicand1[i];
+                args.inMultiplicand1Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand1);
+                args.inMultiplicand2 = arrayInMultiplicand2[i];
+                args.inMultiplicand2Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand2);
+                args.inOffset = arrayInOffset[i];
+                args.inOffsetDouble = Float16Utils.convertFloat16ToDouble(args.inOffset);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inMultiplicand1: ");
+                        appendVariableToMessage(message, args.inMultiplicand1);
+                        message.append("\n");
+                        message.append("Input inMultiplicand2: ");
+                        appendVariableToMessage(message, args.inMultiplicand2);
+                        message.append("\n");
+                        message.append("Input inOffset: ");
+                        appendVariableToMessage(message, args.inOffset);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmaHalfHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFmaHalf2Half2Half2Half2() {
+        Allocation inMultiplicand1 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x2f0bb556l, false);
+        Allocation inMultiplicand2 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x2f0bb557l, false);
+        Allocation inOffset = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xb6e9fa96l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInMultiplicand2(inMultiplicand2);
+            script.set_gAllocInOffset(inOffset);
+            script.forEach_testFmaHalf2Half2Half2Half2(inMultiplicand1, out);
+            verifyResultsFmaHalf2Half2Half2Half2(inMultiplicand1, inMultiplicand2, inOffset, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaHalf2Half2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMultiplicand2(inMultiplicand2);
+            scriptRelaxed.set_gAllocInOffset(inOffset);
+            scriptRelaxed.forEach_testFmaHalf2Half2Half2Half2(inMultiplicand1, out);
+            verifyResultsFmaHalf2Half2Half2Half2(inMultiplicand1, inMultiplicand2, inOffset, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaHalf2Half2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaHalf2Half2Half2Half2(Allocation inMultiplicand1, Allocation inMultiplicand2, Allocation inOffset, Allocation out, boolean relaxed) {
+        short[] arrayInMultiplicand1 = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInMultiplicand1, (short) 42);
+        inMultiplicand1.copyTo(arrayInMultiplicand1);
+        short[] arrayInMultiplicand2 = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInMultiplicand2, (short) 42);
+        inMultiplicand2.copyTo(arrayInMultiplicand2);
+        short[] arrayInOffset = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInOffset, (short) 42);
+        inOffset.copyTo(arrayInOffset);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inMultiplicand1 = arrayInMultiplicand1[i * 2 + j];
+                args.inMultiplicand1Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand1);
+                args.inMultiplicand2 = arrayInMultiplicand2[i * 2 + j];
+                args.inMultiplicand2Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand2);
+                args.inOffset = arrayInOffset[i * 2 + j];
+                args.inOffsetDouble = Float16Utils.convertFloat16ToDouble(args.inOffset);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inMultiplicand1: ");
+                        appendVariableToMessage(message, args.inMultiplicand1);
+                        message.append("\n");
+                        message.append("Input inMultiplicand2: ");
+                        appendVariableToMessage(message, args.inMultiplicand2);
+                        message.append("\n");
+                        message.append("Input inOffset: ");
+                        appendVariableToMessage(message, args.inOffset);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmaHalf2Half2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFmaHalf3Half3Half3Half3() {
+        Allocation inMultiplicand1 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x1a5f3c9el, false);
+        Allocation inMultiplicand2 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x1a5f3c9fl, false);
+        Allocation inOffset = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x1b05aael, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInMultiplicand2(inMultiplicand2);
+            script.set_gAllocInOffset(inOffset);
+            script.forEach_testFmaHalf3Half3Half3Half3(inMultiplicand1, out);
+            verifyResultsFmaHalf3Half3Half3Half3(inMultiplicand1, inMultiplicand2, inOffset, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaHalf3Half3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMultiplicand2(inMultiplicand2);
+            scriptRelaxed.set_gAllocInOffset(inOffset);
+            scriptRelaxed.forEach_testFmaHalf3Half3Half3Half3(inMultiplicand1, out);
+            verifyResultsFmaHalf3Half3Half3Half3(inMultiplicand1, inMultiplicand2, inOffset, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaHalf3Half3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaHalf3Half3Half3Half3(Allocation inMultiplicand1, Allocation inMultiplicand2, Allocation inOffset, Allocation out, boolean relaxed) {
+        short[] arrayInMultiplicand1 = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMultiplicand1, (short) 42);
+        inMultiplicand1.copyTo(arrayInMultiplicand1);
+        short[] arrayInMultiplicand2 = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMultiplicand2, (short) 42);
+        inMultiplicand2.copyTo(arrayInMultiplicand2);
+        short[] arrayInOffset = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInOffset, (short) 42);
+        inOffset.copyTo(arrayInOffset);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inMultiplicand1 = arrayInMultiplicand1[i * 4 + j];
+                args.inMultiplicand1Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand1);
+                args.inMultiplicand2 = arrayInMultiplicand2[i * 4 + j];
+                args.inMultiplicand2Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand2);
+                args.inOffset = arrayInOffset[i * 4 + j];
+                args.inOffsetDouble = Float16Utils.convertFloat16ToDouble(args.inOffset);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inMultiplicand1: ");
+                        appendVariableToMessage(message, args.inMultiplicand1);
+                        message.append("\n");
+                        message.append("Input inMultiplicand2: ");
+                        appendVariableToMessage(message, args.inMultiplicand2);
+                        message.append("\n");
+                        message.append("Input inOffset: ");
+                        appendVariableToMessage(message, args.inOffset);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmaHalf3Half3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFmaHalf4Half4Half4Half4() {
+        Allocation inMultiplicand1 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x5b2c3e6l, false);
+        Allocation inMultiplicand2 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x5b2c3e7l, false);
+        Allocation inOffset = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x4c76bac6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInMultiplicand2(inMultiplicand2);
+            script.set_gAllocInOffset(inOffset);
+            script.forEach_testFmaHalf4Half4Half4Half4(inMultiplicand1, out);
+            verifyResultsFmaHalf4Half4Half4Half4(inMultiplicand1, inMultiplicand2, inOffset, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaHalf4Half4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMultiplicand2(inMultiplicand2);
+            scriptRelaxed.set_gAllocInOffset(inOffset);
+            scriptRelaxed.forEach_testFmaHalf4Half4Half4Half4(inMultiplicand1, out);
+            verifyResultsFmaHalf4Half4Half4Half4(inMultiplicand1, inMultiplicand2, inOffset, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaHalf4Half4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaHalf4Half4Half4Half4(Allocation inMultiplicand1, Allocation inMultiplicand2, Allocation inOffset, Allocation out, boolean relaxed) {
+        short[] arrayInMultiplicand1 = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMultiplicand1, (short) 42);
+        inMultiplicand1.copyTo(arrayInMultiplicand1);
+        short[] arrayInMultiplicand2 = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMultiplicand2, (short) 42);
+        inMultiplicand2.copyTo(arrayInMultiplicand2);
+        short[] arrayInOffset = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInOffset, (short) 42);
+        inOffset.copyTo(arrayInOffset);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inMultiplicand1 = arrayInMultiplicand1[i * 4 + j];
+                args.inMultiplicand1Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand1);
+                args.inMultiplicand2 = arrayInMultiplicand2[i * 4 + j];
+                args.inMultiplicand2Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand2);
+                args.inOffset = arrayInOffset[i * 4 + j];
+                args.inOffsetDouble = Float16Utils.convertFloat16ToDouble(args.inOffset);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inMultiplicand1: ");
+                        appendVariableToMessage(message, args.inMultiplicand1);
+                        message.append("\n");
+                        message.append("Input inMultiplicand2: ");
+                        appendVariableToMessage(message, args.inMultiplicand2);
+                        message.append("\n");
+                        message.append("Input inOffset: ");
+                        appendVariableToMessage(message, args.inOffset);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmaHalf4Half4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testFma() {
         checkFmaFloatFloatFloatFloat();
         checkFmaFloat2Float2Float2Float2();
         checkFmaFloat3Float3Float3Float3();
         checkFmaFloat4Float4Float4Float4();
+        checkFmaHalfHalfHalfHalf();
+        checkFmaHalf2Half2Half2Half2();
+        checkFmaHalf3Half3Half3Half3();
+        checkFmaHalf4Half4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFma.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFma.rs
index 67e2e54..9ddeb76 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFma.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFma.rs
@@ -45,3 +45,27 @@
     float4 inOffset = rsGetElementAt_float4(gAllocInOffset, x);
     return fma(inMultiplicand1, inMultiplicand2, inOffset);
 }
+
+half __attribute__((kernel)) testFmaHalfHalfHalfHalf(half inMultiplicand1, unsigned int x) {
+    half inMultiplicand2 = rsGetElementAt_half(gAllocInMultiplicand2, x);
+    half inOffset = rsGetElementAt_half(gAllocInOffset, x);
+    return fma(inMultiplicand1, inMultiplicand2, inOffset);
+}
+
+half2 __attribute__((kernel)) testFmaHalf2Half2Half2Half2(half2 inMultiplicand1, unsigned int x) {
+    half2 inMultiplicand2 = rsGetElementAt_half2(gAllocInMultiplicand2, x);
+    half2 inOffset = rsGetElementAt_half2(gAllocInOffset, x);
+    return fma(inMultiplicand1, inMultiplicand2, inOffset);
+}
+
+half3 __attribute__((kernel)) testFmaHalf3Half3Half3Half3(half3 inMultiplicand1, unsigned int x) {
+    half3 inMultiplicand2 = rsGetElementAt_half3(gAllocInMultiplicand2, x);
+    half3 inOffset = rsGetElementAt_half3(gAllocInOffset, x);
+    return fma(inMultiplicand1, inMultiplicand2, inOffset);
+}
+
+half4 __attribute__((kernel)) testFmaHalf4Half4Half4Half4(half4 inMultiplicand1, unsigned int x) {
+    half4 inMultiplicand2 = rsGetElementAt_half4(gAllocInMultiplicand2, x);
+    half4 inOffset = rsGetElementAt_half4(gAllocInOffset, x);
+    return fma(inMultiplicand1, inMultiplicand2, inOffset);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmax.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmax.java
index 5b8d11e..b370652 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmax.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmax.java
@@ -359,6 +359,350 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inA;
+        public double inADouble;
+        public short inB;
+        public double inBDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkFmaxHalfHalfHalf() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x6dad4699l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x6dad469al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFmaxHalfHalfHalf(inA, out);
+            verifyResultsFmaxHalfHalfHalf(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFmaxHalfHalfHalf(inA, out);
+            verifyResultsFmaxHalfHalfHalf(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxHalfHalfHalf(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmaxHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFmaxHalf2Half2Half2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xa556216fl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xa5562170l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFmaxHalf2Half2Half2(inA, out);
+            verifyResultsFmaxHalf2Half2Half2(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFmaxHalf2Half2Half2(inA, out);
+            verifyResultsFmaxHalf2Half2Half2(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxHalf2Half2Half2(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 2 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 2 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmaxHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFmaxHalf3Half3Half3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x3f5323el, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x3f5323fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFmaxHalf3Half3Half3(inA, out);
+            verifyResultsFmaxHalf3Half3Half3(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFmaxHalf3Half3Half3(inA, out);
+            verifyResultsFmaxHalf3Half3Half3(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxHalf3Half3Half3(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmaxHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFmaxHalf4Half4Half4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x6294430dl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x6294430el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFmaxHalf4Half4Half4(inA, out);
+            verifyResultsFmaxHalf4Half4Half4(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFmaxHalf4Half4Half4(inA, out);
+            verifyResultsFmaxHalf4Half4Half4(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxHalf4Half4Half4(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmaxHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     private void checkFmaxFloat2FloatFloat2() {
         Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0xdc631102l, false);
         Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xdc631103l, false);
@@ -596,13 +940,272 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    private void checkFmaxHalf2HalfHalf2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x3546cdbdl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x3546cdbel, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFmaxHalf2HalfHalf2(inA, out);
+            verifyResultsFmaxHalf2HalfHalf2(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalf2HalfHalf2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFmaxHalf2HalfHalf2(inA, out);
+            verifyResultsFmaxHalf2HalfHalf2(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalf2HalfHalf2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxHalf2HalfHalf2(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 2 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmaxHalf2HalfHalf2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFmaxHalf3HalfHalf3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xe7e05f61l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe7e05f62l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFmaxHalf3HalfHalf3(inA, out);
+            verifyResultsFmaxHalf3HalfHalf3(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalf3HalfHalf3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFmaxHalf3HalfHalf3(inA, out);
+            verifyResultsFmaxHalf3HalfHalf3(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalf3HalfHalf3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxHalf3HalfHalf3(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmaxHalf3HalfHalf3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFmaxHalf4HalfHalf4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x9a79f105l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x9a79f106l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFmaxHalf4HalfHalf4(inA, out);
+            verifyResultsFmaxHalf4HalfHalf4(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalf4HalfHalf4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFmaxHalf4HalfHalf4(inA, out);
+            verifyResultsFmaxHalf4HalfHalf4(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmaxHalf4HalfHalf4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmaxHalf4HalfHalf4(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmaxHalf4HalfHalf4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testFmax() {
         checkFmaxFloatFloatFloat();
         checkFmaxFloat2Float2Float2();
         checkFmaxFloat3Float3Float3();
         checkFmaxFloat4Float4Float4();
+        checkFmaxHalfHalfHalf();
+        checkFmaxHalf2Half2Half2();
+        checkFmaxHalf3Half3Half3();
+        checkFmaxHalf4Half4Half4();
         checkFmaxFloat2FloatFloat2();
         checkFmaxFloat3FloatFloat3();
         checkFmaxFloat4FloatFloat4();
+        checkFmaxHalf2HalfHalf2();
+        checkFmaxHalf3HalfHalf3();
+        checkFmaxHalf4HalfHalf4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmax.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmax.rs
index e3dec67..9e4ae5b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmax.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmax.rs
@@ -41,6 +41,26 @@
     return fmax(inA, inB);
 }
 
+half __attribute__((kernel)) testFmaxHalfHalfHalf(half inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return fmax(inA, inB);
+}
+
+half2 __attribute__((kernel)) testFmaxHalf2Half2Half2(half2 inA, unsigned int x) {
+    half2 inB = rsGetElementAt_half2(gAllocInB, x);
+    return fmax(inA, inB);
+}
+
+half3 __attribute__((kernel)) testFmaxHalf3Half3Half3(half3 inA, unsigned int x) {
+    half3 inB = rsGetElementAt_half3(gAllocInB, x);
+    return fmax(inA, inB);
+}
+
+half4 __attribute__((kernel)) testFmaxHalf4Half4Half4(half4 inA, unsigned int x) {
+    half4 inB = rsGetElementAt_half4(gAllocInB, x);
+    return fmax(inA, inB);
+}
+
 float2 __attribute__((kernel)) testFmaxFloat2FloatFloat2(float2 inA, unsigned int x) {
     float inB = rsGetElementAt_float(gAllocInB, x);
     return fmax(inA, inB);
@@ -55,3 +75,18 @@
     float inB = rsGetElementAt_float(gAllocInB, x);
     return fmax(inA, inB);
 }
+
+half2 __attribute__((kernel)) testFmaxHalf2HalfHalf2(half2 inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return fmax(inA, inB);
+}
+
+half3 __attribute__((kernel)) testFmaxHalf3HalfHalf3(half3 inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return fmax(inA, inB);
+}
+
+half4 __attribute__((kernel)) testFmaxHalf4HalfHalf4(half4 inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return fmax(inA, inB);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmin.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmin.java
index 7ce9ce6..8b81c47 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmin.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmin.java
@@ -359,6 +359,350 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inA;
+        public double inADouble;
+        public short inB;
+        public double inBDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkFminHalfHalfHalf() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xc5ee8503l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xc5ee8504l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFminHalfHalfHalf(inA, out);
+            verifyResultsFminHalfHalfHalf(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFminHalfHalfHalf(inA, out);
+            verifyResultsFminHalfHalfHalf(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminHalfHalfHalf(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFminHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFminHalf2Half2Half2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x5461544dl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x5461544el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFminHalf2Half2Half2(inA, out);
+            verifyResultsFminHalf2Half2Half2(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFminHalf2Half2Half2(inA, out);
+            verifyResultsFminHalf2Half2Half2(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminHalf2Half2Half2(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 2 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 2 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFminHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFminHalf3Half3Half3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb300651cl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb300651dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFminHalf3Half3Half3(inA, out);
+            verifyResultsFminHalf3Half3Half3(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFminHalf3Half3Half3(inA, out);
+            verifyResultsFminHalf3Half3Half3(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminHalf3Half3Half3(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFminHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFminHalf4Half4Half4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x119f75ebl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x119f75ecl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFminHalf4Half4Half4(inA, out);
+            verifyResultsFminHalf4Half4Half4(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFminHalf4Half4Half4(inA, out);
+            verifyResultsFminHalf4Half4Half4(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminHalf4Half4Half4(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFminHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     private void checkFminFloat2FloatFloat2() {
         Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x24457670l, false);
         Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x24457671l, false);
@@ -596,13 +940,272 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    private void checkFminHalf2HalfHalf2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xa4829957l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xa4829958l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFminHalf2HalfHalf2(inA, out);
+            verifyResultsFminHalf2HalfHalf2(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalf2HalfHalf2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFminHalf2HalfHalf2(inA, out);
+            verifyResultsFminHalf2HalfHalf2(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalf2HalfHalf2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminHalf2HalfHalf2(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 2 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFminHalf2HalfHalf2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFminHalf3HalfHalf3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x571c2afbl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x571c2afcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFminHalf3HalfHalf3(inA, out);
+            verifyResultsFminHalf3HalfHalf3(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalf3HalfHalf3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFminHalf3HalfHalf3(inA, out);
+            verifyResultsFminHalf3HalfHalf3(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalf3HalfHalf3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminHalf3HalfHalf3(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFminHalf3HalfHalf3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFminHalf4HalfHalf4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x9b5bc9fl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x9b5bca0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testFminHalf4HalfHalf4(inA, out);
+            verifyResultsFminHalf4HalfHalf4(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalf4HalfHalf4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testFminHalf4HalfHalf4(inA, out);
+            verifyResultsFminHalf4HalfHalf4(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFminHalf4HalfHalf4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFminHalf4HalfHalf4(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFminHalf4HalfHalf4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testFmin() {
         checkFminFloatFloatFloat();
         checkFminFloat2Float2Float2();
         checkFminFloat3Float3Float3();
         checkFminFloat4Float4Float4();
+        checkFminHalfHalfHalf();
+        checkFminHalf2Half2Half2();
+        checkFminHalf3Half3Half3();
+        checkFminHalf4Half4Half4();
         checkFminFloat2FloatFloat2();
         checkFminFloat3FloatFloat3();
         checkFminFloat4FloatFloat4();
+        checkFminHalf2HalfHalf2();
+        checkFminHalf3HalfHalf3();
+        checkFminHalf4HalfHalf4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmin.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmin.rs
index 465d493..7e6c6dd 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmin.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmin.rs
@@ -41,6 +41,26 @@
     return fmin(inA, inB);
 }
 
+half __attribute__((kernel)) testFminHalfHalfHalf(half inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return fmin(inA, inB);
+}
+
+half2 __attribute__((kernel)) testFminHalf2Half2Half2(half2 inA, unsigned int x) {
+    half2 inB = rsGetElementAt_half2(gAllocInB, x);
+    return fmin(inA, inB);
+}
+
+half3 __attribute__((kernel)) testFminHalf3Half3Half3(half3 inA, unsigned int x) {
+    half3 inB = rsGetElementAt_half3(gAllocInB, x);
+    return fmin(inA, inB);
+}
+
+half4 __attribute__((kernel)) testFminHalf4Half4Half4(half4 inA, unsigned int x) {
+    half4 inB = rsGetElementAt_half4(gAllocInB, x);
+    return fmin(inA, inB);
+}
+
 float2 __attribute__((kernel)) testFminFloat2FloatFloat2(float2 inA, unsigned int x) {
     float inB = rsGetElementAt_float(gAllocInB, x);
     return fmin(inA, inB);
@@ -55,3 +75,18 @@
     float inB = rsGetElementAt_float(gAllocInB, x);
     return fmin(inA, inB);
 }
+
+half2 __attribute__((kernel)) testFminHalf2HalfHalf2(half2 inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return fmin(inA, inB);
+}
+
+half3 __attribute__((kernel)) testFminHalf3HalfHalf3(half3 inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return fmin(inA, inB);
+}
+
+half4 __attribute__((kernel)) testFminHalf4HalfHalf4(half4 inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return fmin(inA, inB);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmod.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmod.java
index cdbd1ec..921c261 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmod.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmod.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inNumerator;
+        public double inNumeratorDouble;
+        public short inDenominator;
+        public double inDenominatorDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkFmodHalfHalfHalf() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x9b7bf563l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x699a0144l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testFmodHalfHalfHalf(inNumerator, out);
+            verifyResultsFmodHalfHalfHalf(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testFmodHalfHalfHalf(inNumerator, out);
+            verifyResultsFmodHalfHalfHalf(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmodHalfHalfHalf(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmod(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmodHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFmodHalf2Half2Half2() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xe67736bdl, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xfa55044el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testFmodHalf2Half2Half2(inNumerator, out);
+            verifyResultsFmodHalf2Half2Half2(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testFmodHalf2Half2Half2(inNumerator, out);
+            verifyResultsFmodHalf2Half2Half2(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmodHalf2Half2Half2(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 2 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 2 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmod(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmodHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFmodHalf3Half3Half3() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x31e9672cl, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xe614d605l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testFmodHalf3Half3Half3(inNumerator, out);
+            verifyResultsFmodHalf3Half3Half3(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testFmodHalf3Half3Half3(inNumerator, out);
+            verifyResultsFmodHalf3Half3Half3(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmodHalf3Half3Half3(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 4 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 4 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmod(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmodHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFmodHalf4Half4Half4() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x7d5b979bl, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xd1d4a7bcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testFmodHalf4Half4Half4(inNumerator, out);
+            verifyResultsFmodHalf4Half4Half4(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testFmodHalf4Half4Half4(inNumerator, out);
+            verifyResultsFmodHalf4Half4Half4(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFmodHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFmodHalf4Half4Half4(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 4 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 4 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFmod(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFmodHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testFmod() {
         checkFmodFloatFloatFloat();
         checkFmodFloat2Float2Float2();
         checkFmodFloat3Float3Float3();
         checkFmodFloat4Float4Float4();
+        checkFmodHalfHalfHalf();
+        checkFmodHalf2Half2Half2();
+        checkFmodHalf3Half3Half3();
+        checkFmodHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmod.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmod.rs
index 8ff9756..56ed83f 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmod.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFmod.rs
@@ -40,3 +40,23 @@
     float4 inDenominator = rsGetElementAt_float4(gAllocInDenominator, x);
     return fmod(inNumerator, inDenominator);
 }
+
+half __attribute__((kernel)) testFmodHalfHalfHalf(half inNumerator, unsigned int x) {
+    half inDenominator = rsGetElementAt_half(gAllocInDenominator, x);
+    return fmod(inNumerator, inDenominator);
+}
+
+half2 __attribute__((kernel)) testFmodHalf2Half2Half2(half2 inNumerator, unsigned int x) {
+    half2 inDenominator = rsGetElementAt_half2(gAllocInDenominator, x);
+    return fmod(inNumerator, inDenominator);
+}
+
+half3 __attribute__((kernel)) testFmodHalf3Half3Half3(half3 inNumerator, unsigned int x) {
+    half3 inDenominator = rsGetElementAt_half3(gAllocInDenominator, x);
+    return fmod(inNumerator, inDenominator);
+}
+
+half4 __attribute__((kernel)) testFmodHalf4Half4Half4(half4 inNumerator, unsigned int x) {
+    half4 inDenominator = rsGetElementAt_half4(gAllocInDenominator, x);
+    return fmod(inNumerator, inDenominator);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFract.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFract.java
index 4040b43..b11b36e 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFract.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFract.java
@@ -676,6 +676,691 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty outFloor;
+        public Target.Floaty out;
+    }
+
+    private void checkFractHalfHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x64a42fb6l, false);
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocOutFloor(outFloor);
+            script.forEach_testFractHalfHalfHalf(inV, out);
+            verifyResultsFractHalfHalfHalf(inV, outFloor, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutFloor(outFloor);
+            scriptRelaxed.forEach_testFractHalfHalfHalf(inV, out);
+            verifyResultsFractHalfHalfHalf(inV, outFloor, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractHalfHalfHalf(Allocation inV, Allocation outFloor, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOutFloor = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOutFloor, (short) 42);
+        outFloor.copyTo(arrayOutFloor);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outFloor.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutFloor[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output outFloor: ");
+                        appendVariableToMessage(message, args.outFloor);
+                        message.append("\n");
+                        message.append("Actual   output outFloor: ");
+                        appendVariableToMessage(message, arrayOutFloor[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output outFloor (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOutFloor[i * 1 + j]));
+                        if (!args.outFloor.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutFloor[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFractHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFractHalf2Half2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x734da11cl, false);
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocOutFloor(outFloor);
+            script.forEach_testFractHalf2Half2Half2(inV, out);
+            verifyResultsFractHalf2Half2Half2(inV, outFloor, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutFloor(outFloor);
+            scriptRelaxed.forEach_testFractHalf2Half2Half2(inV, out);
+            verifyResultsFractHalf2Half2Half2(inV, outFloor, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractHalf2Half2Half2(Allocation inV, Allocation outFloor, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOutFloor = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOutFloor, (short) 42);
+        outFloor.copyTo(arrayOutFloor);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outFloor.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutFloor[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output outFloor: ");
+                        appendVariableToMessage(message, args.outFloor);
+                        message.append("\n");
+                        message.append("Actual   output outFloor: ");
+                        appendVariableToMessage(message, arrayOutFloor[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output outFloor (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOutFloor[i * 2 + j]));
+                        if (!args.outFloor.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutFloor[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFractHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFractHalf3Half3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xd1ecb1ebl, false);
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocOutFloor(outFloor);
+            script.forEach_testFractHalf3Half3Half3(inV, out);
+            verifyResultsFractHalf3Half3Half3(inV, outFloor, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutFloor(outFloor);
+            scriptRelaxed.forEach_testFractHalf3Half3Half3(inV, out);
+            verifyResultsFractHalf3Half3Half3(inV, outFloor, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractHalf3Half3Half3(Allocation inV, Allocation outFloor, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOutFloor = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOutFloor, (short) 42);
+        outFloor.copyTo(arrayOutFloor);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outFloor.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutFloor[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output outFloor: ");
+                        appendVariableToMessage(message, args.outFloor);
+                        message.append("\n");
+                        message.append("Actual   output outFloor: ");
+                        appendVariableToMessage(message, arrayOutFloor[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output outFloor (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOutFloor[i * 4 + j]));
+                        if (!args.outFloor.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutFloor[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFractHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFractHalf4Half4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x308bc2bal, false);
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocOutFloor(outFloor);
+            script.forEach_testFractHalf4Half4Half4(inV, out);
+            verifyResultsFractHalf4Half4Half4(inV, outFloor, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation outFloor = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutFloor(outFloor);
+            scriptRelaxed.forEach_testFractHalf4Half4Half4(inV, out);
+            verifyResultsFractHalf4Half4Half4(inV, outFloor, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractHalf4Half4Half4(Allocation inV, Allocation outFloor, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOutFloor = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOutFloor, (short) 42);
+        outFloor.copyTo(arrayOutFloor);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outFloor.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutFloor[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output outFloor: ");
+                        appendVariableToMessage(message, args.outFloor);
+                        message.append("\n");
+                        message.append("Actual   output outFloor: ");
+                        appendVariableToMessage(message, arrayOutFloor[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output outFloor (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOutFloor[i * 4 + j]));
+                        if (!args.outFloor.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutFloor[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFractHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkFractHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x96468e55l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testFractHalfHalf(inV, out);
+            verifyResultsFractHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testFractHalfHalf(inV, out);
+            verifyResultsFractHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFractHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFractHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xad1120fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testFractHalf2Half2(inV, out);
+            verifyResultsFractHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testFractHalf2Half2(inV, out);
+            verifyResultsFractHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFractHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFractHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x69d8d703l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testFractHalf3Half3(inV, out);
+            verifyResultsFractHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testFractHalf3Half3(inV, out);
+            verifyResultsFractHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFractHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkFractHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xc8e09bf7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testFractHalf4Half4(inV, out);
+            verifyResultsFractHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testFractHalf4Half4(inV, out);
+            verifyResultsFractHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testFractHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsFractHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeFract(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkFractHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testFract() {
         checkFractFloatFloatFloat();
         checkFractFloat2Float2Float2();
@@ -685,5 +1370,13 @@
         checkFractFloat2Float2();
         checkFractFloat3Float3();
         checkFractFloat4Float4();
+        checkFractHalfHalfHalf();
+        checkFractHalf2Half2Half2();
+        checkFractHalf3Half3Half3();
+        checkFractHalf4Half4Half4();
+        checkFractHalfHalf();
+        checkFractHalf2Half2();
+        checkFractHalf3Half3();
+        checkFractHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFract.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFract.rs
index 32f4178..4fd65d3 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFract.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestFract.rs
@@ -64,3 +64,47 @@
 float4 __attribute__((kernel)) testFractFloat4Float4(float4 inV) {
     return fract(inV);
 }
+
+half __attribute__((kernel)) testFractHalfHalfHalf(half inV, unsigned int x) {
+    half outFloor = 0;
+    half out = fract(inV, &outFloor);
+    rsSetElementAt_half(gAllocOutFloor, outFloor, x);
+    return out;
+}
+
+half2 __attribute__((kernel)) testFractHalf2Half2Half2(half2 inV, unsigned int x) {
+    half2 outFloor = 0;
+    half2 out = fract(inV, &outFloor);
+    rsSetElementAt_half2(gAllocOutFloor, outFloor, x);
+    return out;
+}
+
+half3 __attribute__((kernel)) testFractHalf3Half3Half3(half3 inV, unsigned int x) {
+    half3 outFloor = 0;
+    half3 out = fract(inV, &outFloor);
+    rsSetElementAt_half3(gAllocOutFloor, outFloor, x);
+    return out;
+}
+
+half4 __attribute__((kernel)) testFractHalf4Half4Half4(half4 inV, unsigned int x) {
+    half4 outFloor = 0;
+    half4 out = fract(inV, &outFloor);
+    rsSetElementAt_half4(gAllocOutFloor, outFloor, x);
+    return out;
+}
+
+half __attribute__((kernel)) testFractHalfHalf(half inV) {
+    return fract(inV);
+}
+
+half2 __attribute__((kernel)) testFractHalf2Half2(half2 inV) {
+    return fract(inV);
+}
+
+half3 __attribute__((kernel)) testFractHalf3Half3(half3 inV) {
+    return fract(inV);
+}
+
+half4 __attribute__((kernel)) testFractHalf4Half4(half4 inV) {
+    return fract(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestHypot.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestHypot.java
index e0144b8..9b02e25 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestHypot.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestHypot.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inA;
+        public double inADouble;
+        public short inB;
+        public double inBDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkHypotHalfHalfHalf() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xff770667l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xff770668l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testHypotHalfHalfHalf(inA, out);
+            verifyResultsHypotHalfHalfHalf(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testHypotHalfHalfHalf(inA, out);
+            verifyResultsHypotHalfHalfHalf(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHypotHalfHalfHalf(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkHypotHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkHypotHalf2Half2Half2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xaa72b8b9l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xaa72b8bal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testHypotHalf2Half2Half2(inA, out);
+            verifyResultsHypotHalf2Half2Half2(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testHypotHalf2Half2Half2(inA, out);
+            verifyResultsHypotHalf2Half2Half2(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHypotHalf2Half2Half2(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 2 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 2 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkHypotHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkHypotHalf3Half3Half3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x911c988l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x911c989l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testHypotHalf3Half3Half3(inA, out);
+            verifyResultsHypotHalf3Half3Half3(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testHypotHalf3Half3Half3(inA, out);
+            verifyResultsHypotHalf3Half3Half3(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHypotHalf3Half3Half3(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkHypotHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkHypotHalf4Half4Half4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x67b0da57l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x67b0da58l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testHypotHalf4Half4Half4(inA, out);
+            verifyResultsHypotHalf4Half4Half4(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testHypotHalf4Half4Half4(inA, out);
+            verifyResultsHypotHalf4Half4Half4(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testHypotHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsHypotHalf4Half4Half4(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkHypotHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testHypot() {
         checkHypotFloatFloatFloat();
         checkHypotFloat2Float2Float2();
         checkHypotFloat3Float3Float3();
         checkHypotFloat4Float4Float4();
+        checkHypotHalfHalfHalf();
+        checkHypotHalf2Half2Half2();
+        checkHypotHalf3Half3Half3();
+        checkHypotHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestHypot.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestHypot.rs
index 7d020066..90d822d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestHypot.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestHypot.rs
@@ -40,3 +40,23 @@
     float4 inB = rsGetElementAt_float4(gAllocInB, x);
     return hypot(inA, inB);
 }
+
+half __attribute__((kernel)) testHypotHalfHalfHalf(half inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return hypot(inA, inB);
+}
+
+half2 __attribute__((kernel)) testHypotHalf2Half2Half2(half2 inA, unsigned int x) {
+    half2 inB = rsGetElementAt_half2(gAllocInB, x);
+    return hypot(inA, inB);
+}
+
+half3 __attribute__((kernel)) testHypotHalf3Half3Half3(half3 inA, unsigned int x) {
+    half3 inB = rsGetElementAt_half3(gAllocInB, x);
+    return hypot(inA, inB);
+}
+
+half4 __attribute__((kernel)) testHypotHalf4Half4Half4(half4 inA, unsigned int x) {
+    half4 inB = rsGetElementAt_half4(gAllocInB, x);
+    return hypot(inA, inB);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog.java
index 64a91b2..de3eecf 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkLogHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x35076dfl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testLogHalfHalf(inV, out);
+            verifyResultsLogHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLogHalfHalf(inV, out);
+            verifyResultsLogHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLogHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLogHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x97619ec9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testLogHalf2Half2(inV, out);
+            verifyResultsLogHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testLogHalf2Half2(inV, out);
+            verifyResultsLogHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLogHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLogHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xf66963bdl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testLogHalf3Half3(inV, out);
+            verifyResultsLogHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testLogHalf3Half3(inV, out);
+            verifyResultsLogHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLogHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLogHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x557128b1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testLogHalf4Half4(inV, out);
+            verifyResultsLogHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testLogHalf4Half4(inV, out);
+            verifyResultsLogHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLogHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testLog() {
         checkLogFloatFloat();
         checkLogFloat2Float2();
         checkLogFloat3Float3();
         checkLogFloat4Float4();
+        checkLogHalfHalf();
+        checkLogHalf2Half2();
+        checkLogHalf3Half3();
+        checkLogHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog.rs
index 00151d7..0d0881a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testLogFloat4Float4(float4 inV) {
     return log(inV);
 }
+
+half __attribute__((kernel)) testLogHalfHalf(half inV) {
+    return log(inV);
+}
+
+half2 __attribute__((kernel)) testLogHalf2Half2(half2 inV) {
+    return log(inV);
+}
+
+half3 __attribute__((kernel)) testLogHalf3Half3(half3 inV) {
+    return log(inV);
+}
+
+half4 __attribute__((kernel)) testLogHalf4Half4(half4 inV) {
+    return log(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog10.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog10.java
index d01ec9e..a5589e5 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog10.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog10.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkLog10HalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xdd61cbd0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testLog10HalfHalf(inV, out);
+            verifyResultsLog10HalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10HalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLog10HalfHalf(inV, out);
+            verifyResultsLog10HalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10HalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog10HalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLog10HalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLog10Half2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x9e901f72l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testLog10Half2Half2(inV, out);
+            verifyResultsLog10Half2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testLog10Half2Half2(inV, out);
+            verifyResultsLog10Half2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog10Half2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLog10Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLog10Half3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xfd97e466l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testLog10Half3Half3(inV, out);
+            verifyResultsLog10Half3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testLog10Half3Half3(inV, out);
+            verifyResultsLog10Half3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog10Half3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLog10Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLog10Half4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x5c9fa95al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testLog10Half4Half4(inV, out);
+            verifyResultsLog10Half4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testLog10Half4Half4(inV, out);
+            verifyResultsLog10Half4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog10Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog10Half4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLog10Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testLog10() {
         checkLog10FloatFloat();
         checkLog10Float2Float2();
         checkLog10Float3Float3();
         checkLog10Float4Float4();
+        checkLog10HalfHalf();
+        checkLog10Half2Half2();
+        checkLog10Half3Half3();
+        checkLog10Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog10.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog10.rs
index 00544b8..03f657d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog10.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog10.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testLog10Float4Float4(float4 inV) {
     return log10(inV);
 }
+
+half __attribute__((kernel)) testLog10HalfHalf(half inV) {
+    return log10(inV);
+}
+
+half2 __attribute__((kernel)) testLog10Half2Half2(half2 inV) {
+    return log10(inV);
+}
+
+half3 __attribute__((kernel)) testLog10Half3Half3(half3 inV) {
+    return log10(inV);
+}
+
+half4 __attribute__((kernel)) testLog10Half4Half4(half4 inV) {
+    return log10(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog1p.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog1p.java
index 405ef89..8a17d9e 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog1p.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog1p.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkLog1pHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x28afb890l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testLog1pHalfHalf(inV, out);
+            verifyResultsLog1pHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLog1pHalfHalf(inV, out);
+            verifyResultsLog1pHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog1pHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLog1pHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLog1pHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x84631632l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testLog1pHalf2Half2(inV, out);
+            verifyResultsLog1pHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testLog1pHalf2Half2(inV, out);
+            verifyResultsLog1pHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog1pHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLog1pHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLog1pHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xe36adb26l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testLog1pHalf3Half3(inV, out);
+            verifyResultsLog1pHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testLog1pHalf3Half3(inV, out);
+            verifyResultsLog1pHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog1pHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLog1pHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLog1pHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x4272a01al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testLog1pHalf4Half4(inV, out);
+            verifyResultsLog1pHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testLog1pHalf4Half4(inV, out);
+            verifyResultsLog1pHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog1pHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog1pHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLog1pHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testLog1p() {
         checkLog1pFloatFloat();
         checkLog1pFloat2Float2();
         checkLog1pFloat3Float3();
         checkLog1pFloat4Float4();
+        checkLog1pHalfHalf();
+        checkLog1pHalf2Half2();
+        checkLog1pHalf3Half3();
+        checkLog1pHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog1p.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog1p.rs
index aa27a39..cc11620 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog1p.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog1p.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testLog1pFloat4Float4(float4 inV) {
     return log1p(inV);
 }
+
+half __attribute__((kernel)) testLog1pHalfHalf(half inV) {
+    return log1p(inV);
+}
+
+half2 __attribute__((kernel)) testLog1pHalf2Half2(half2 inV) {
+    return log1p(inV);
+}
+
+half3 __attribute__((kernel)) testLog1pHalf3Half3(half3 inV) {
+    return log1p(inV);
+}
+
+half4 __attribute__((kernel)) testLog1pHalf4Half4(half4 inV) {
+    return log1p(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog2.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog2.java
index fce95f2..1c3b09c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog2.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog2.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkLog2HalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x23a7d4adl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testLog2HalfHalf(inV, out);
+            verifyResultsLog2HalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2HalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLog2HalfHalf(inV, out);
+            verifyResultsLog2HalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2HalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog2HalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLog2HalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLog2Half2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x2e6623a7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testLog2Half2Half2(inV, out);
+            verifyResultsLog2Half2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testLog2Half2Half2(inV, out);
+            verifyResultsLog2Half2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog2Half2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLog2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLog2Half3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x8d6de89bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testLog2Half3Half3(inV, out);
+            verifyResultsLog2Half3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testLog2Half3Half3(inV, out);
+            verifyResultsLog2Half3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog2Half3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLog2Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLog2Half4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xec75ad8fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testLog2Half4Half4(inV, out);
+            verifyResultsLog2Half4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testLog2Half4Half4(inV, out);
+            verifyResultsLog2Half4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLog2Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLog2Half4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLog2Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testLog2() {
         checkLog2FloatFloat();
         checkLog2Float2Float2();
         checkLog2Float3Float3();
         checkLog2Float4Float4();
+        checkLog2HalfHalf();
+        checkLog2Half2Half2();
+        checkLog2Half3Half3();
+        checkLog2Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog2.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog2.rs
index bcdca89..e11e2b6 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog2.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLog2.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testLog2Float4Float4(float4 inV) {
     return log2(inV);
 }
+
+half __attribute__((kernel)) testLog2HalfHalf(half inV) {
+    return log2(inV);
+}
+
+half2 __attribute__((kernel)) testLog2Half2Half2(half2 inV) {
+    return log2(inV);
+}
+
+half3 __attribute__((kernel)) testLog2Half3Half3(half3 inV) {
+    return log2(inV);
+}
+
+half4 __attribute__((kernel)) testLog2Half4Half4(half4 inV) {
+    return log2(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLogb.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLogb.java
index f176573..d641200 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLogb.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLogb.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkLogbHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x5c22463dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testLogbHalfHalf(inV, out);
+            verifyResultsLogbHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testLogbHalfHalf(inV, out);
+            verifyResultsLogbHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogbHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLogb(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLogbHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLogbHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x1ac45cb7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testLogbHalf2Half2(inV, out);
+            verifyResultsLogbHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testLogbHalf2Half2(inV, out);
+            verifyResultsLogbHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogbHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLogb(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLogbHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLogbHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x79cc21abl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testLogbHalf3Half3(inV, out);
+            verifyResultsLogbHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testLogbHalf3Half3(inV, out);
+            verifyResultsLogbHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogbHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLogb(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLogbHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkLogbHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xd8d3e69fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testLogbHalf4Half4(inV, out);
+            verifyResultsLogbHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testLogbHalf4Half4(inV, out);
+            verifyResultsLogbHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testLogbHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsLogbHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeLogb(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkLogbHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testLogb() {
         checkLogbFloatFloat();
         checkLogbFloat2Float2();
         checkLogbFloat3Float3();
         checkLogbFloat4Float4();
+        checkLogbHalfHalf();
+        checkLogbHalf2Half2();
+        checkLogbHalf3Half3();
+        checkLogbHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLogb.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLogb.rs
index eb46e0b..45cc762 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLogb.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestLogb.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testLogbFloat4Float4(float4 inV) {
     return logb(inV);
 }
+
+half __attribute__((kernel)) testLogbHalfHalf(half inV) {
+    return logb(inV);
+}
+
+half2 __attribute__((kernel)) testLogbHalf2Half2(half2 inV) {
+    return logb(inV);
+}
+
+half3 __attribute__((kernel)) testLogbHalf3Half3(half3 inV) {
+    return logb(inV);
+}
+
+half4 __attribute__((kernel)) testLogbHalf4Half4(half4 inV) {
+    return logb(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMad.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMad.java
index f905f98..29e2828 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMad.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMad.java
@@ -400,10 +400,404 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalfHalf {
+        public short inMultiplicand1;
+        public double inMultiplicand1Double;
+        public short inMultiplicand2;
+        public double inMultiplicand2Double;
+        public short inOffset;
+        public double inOffsetDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkMadHalfHalfHalfHalf() {
+        Allocation inMultiplicand1 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xcfbe7d2cl, false);
+        Allocation inMultiplicand2 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xcfbe7d2dl, false);
+        Allocation inOffset = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xfd6cfcc8l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInMultiplicand2(inMultiplicand2);
+            script.set_gAllocInOffset(inOffset);
+            script.forEach_testMadHalfHalfHalfHalf(inMultiplicand1, out);
+            verifyResultsMadHalfHalfHalfHalf(inMultiplicand1, inMultiplicand2, inOffset, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadHalfHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMultiplicand2(inMultiplicand2);
+            scriptRelaxed.set_gAllocInOffset(inOffset);
+            scriptRelaxed.forEach_testMadHalfHalfHalfHalf(inMultiplicand1, out);
+            verifyResultsMadHalfHalfHalfHalf(inMultiplicand1, inMultiplicand2, inOffset, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadHalfHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMadHalfHalfHalfHalf(Allocation inMultiplicand1, Allocation inMultiplicand2, Allocation inOffset, Allocation out, boolean relaxed) {
+        short[] arrayInMultiplicand1 = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMultiplicand1, (short) 42);
+        inMultiplicand1.copyTo(arrayInMultiplicand1);
+        short[] arrayInMultiplicand2 = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInMultiplicand2, (short) 42);
+        inMultiplicand2.copyTo(arrayInMultiplicand2);
+        short[] arrayInOffset = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInOffset, (short) 42);
+        inOffset.copyTo(arrayInOffset);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inMultiplicand1 = arrayInMultiplicand1[i];
+                args.inMultiplicand1Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand1);
+                args.inMultiplicand2 = arrayInMultiplicand2[i];
+                args.inMultiplicand2Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand2);
+                args.inOffset = arrayInOffset[i];
+                args.inOffsetDouble = Float16Utils.convertFloat16ToDouble(args.inOffset);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMad(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inMultiplicand1: ");
+                        appendVariableToMessage(message, args.inMultiplicand1);
+                        message.append("\n");
+                        message.append("Input inMultiplicand2: ");
+                        appendVariableToMessage(message, args.inMultiplicand2);
+                        message.append("\n");
+                        message.append("Input inOffset: ");
+                        appendVariableToMessage(message, args.inOffset);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMadHalfHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMadHalf2Half2Half2Half2() {
+        Allocation inMultiplicand1 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xe9fc79e0l, false);
+        Allocation inMultiplicand2 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xe9fc79e1l, false);
+        Allocation inOffset = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xdeb2c084l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInMultiplicand2(inMultiplicand2);
+            script.set_gAllocInOffset(inOffset);
+            script.forEach_testMadHalf2Half2Half2Half2(inMultiplicand1, out);
+            verifyResultsMadHalf2Half2Half2Half2(inMultiplicand1, inMultiplicand2, inOffset, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadHalf2Half2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMultiplicand2(inMultiplicand2);
+            scriptRelaxed.set_gAllocInOffset(inOffset);
+            scriptRelaxed.forEach_testMadHalf2Half2Half2Half2(inMultiplicand1, out);
+            verifyResultsMadHalf2Half2Half2Half2(inMultiplicand1, inMultiplicand2, inOffset, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadHalf2Half2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMadHalf2Half2Half2Half2(Allocation inMultiplicand1, Allocation inMultiplicand2, Allocation inOffset, Allocation out, boolean relaxed) {
+        short[] arrayInMultiplicand1 = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInMultiplicand1, (short) 42);
+        inMultiplicand1.copyTo(arrayInMultiplicand1);
+        short[] arrayInMultiplicand2 = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInMultiplicand2, (short) 42);
+        inMultiplicand2.copyTo(arrayInMultiplicand2);
+        short[] arrayInOffset = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInOffset, (short) 42);
+        inOffset.copyTo(arrayInOffset);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inMultiplicand1 = arrayInMultiplicand1[i * 2 + j];
+                args.inMultiplicand1Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand1);
+                args.inMultiplicand2 = arrayInMultiplicand2[i * 2 + j];
+                args.inMultiplicand2Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand2);
+                args.inOffset = arrayInOffset[i * 2 + j];
+                args.inOffsetDouble = Float16Utils.convertFloat16ToDouble(args.inOffset);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMad(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inMultiplicand1: ");
+                        appendVariableToMessage(message, args.inMultiplicand1);
+                        message.append("\n");
+                        message.append("Input inMultiplicand2: ");
+                        appendVariableToMessage(message, args.inMultiplicand2);
+                        message.append("\n");
+                        message.append("Input inOffset: ");
+                        appendVariableToMessage(message, args.inOffset);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMadHalf2Half2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMadHalf3Half3Half3Half3() {
+        Allocation inMultiplicand1 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xd5500128l, false);
+        Allocation inMultiplicand2 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xd5500129l, false);
+        Allocation inOffset = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x2979209cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInMultiplicand2(inMultiplicand2);
+            script.set_gAllocInOffset(inOffset);
+            script.forEach_testMadHalf3Half3Half3Half3(inMultiplicand1, out);
+            verifyResultsMadHalf3Half3Half3Half3(inMultiplicand1, inMultiplicand2, inOffset, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadHalf3Half3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMultiplicand2(inMultiplicand2);
+            scriptRelaxed.set_gAllocInOffset(inOffset);
+            scriptRelaxed.forEach_testMadHalf3Half3Half3Half3(inMultiplicand1, out);
+            verifyResultsMadHalf3Half3Half3Half3(inMultiplicand1, inMultiplicand2, inOffset, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadHalf3Half3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMadHalf3Half3Half3Half3(Allocation inMultiplicand1, Allocation inMultiplicand2, Allocation inOffset, Allocation out, boolean relaxed) {
+        short[] arrayInMultiplicand1 = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMultiplicand1, (short) 42);
+        inMultiplicand1.copyTo(arrayInMultiplicand1);
+        short[] arrayInMultiplicand2 = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMultiplicand2, (short) 42);
+        inMultiplicand2.copyTo(arrayInMultiplicand2);
+        short[] arrayInOffset = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInOffset, (short) 42);
+        inOffset.copyTo(arrayInOffset);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inMultiplicand1 = arrayInMultiplicand1[i * 4 + j];
+                args.inMultiplicand1Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand1);
+                args.inMultiplicand2 = arrayInMultiplicand2[i * 4 + j];
+                args.inMultiplicand2Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand2);
+                args.inOffset = arrayInOffset[i * 4 + j];
+                args.inOffsetDouble = Float16Utils.convertFloat16ToDouble(args.inOffset);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMad(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inMultiplicand1: ");
+                        appendVariableToMessage(message, args.inMultiplicand1);
+                        message.append("\n");
+                        message.append("Input inMultiplicand2: ");
+                        appendVariableToMessage(message, args.inMultiplicand2);
+                        message.append("\n");
+                        message.append("Input inOffset: ");
+                        appendVariableToMessage(message, args.inOffset);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMadHalf3Half3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMadHalf4Half4Half4Half4() {
+        Allocation inMultiplicand1 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xc0a38870l, false);
+        Allocation inMultiplicand2 = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xc0a38871l, false);
+        Allocation inOffset = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x743f80b4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInMultiplicand2(inMultiplicand2);
+            script.set_gAllocInOffset(inOffset);
+            script.forEach_testMadHalf4Half4Half4Half4(inMultiplicand1, out);
+            verifyResultsMadHalf4Half4Half4Half4(inMultiplicand1, inMultiplicand2, inOffset, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadHalf4Half4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInMultiplicand2(inMultiplicand2);
+            scriptRelaxed.set_gAllocInOffset(inOffset);
+            scriptRelaxed.forEach_testMadHalf4Half4Half4Half4(inMultiplicand1, out);
+            verifyResultsMadHalf4Half4Half4Half4(inMultiplicand1, inMultiplicand2, inOffset, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMadHalf4Half4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMadHalf4Half4Half4Half4(Allocation inMultiplicand1, Allocation inMultiplicand2, Allocation inOffset, Allocation out, boolean relaxed) {
+        short[] arrayInMultiplicand1 = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMultiplicand1, (short) 42);
+        inMultiplicand1.copyTo(arrayInMultiplicand1);
+        short[] arrayInMultiplicand2 = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInMultiplicand2, (short) 42);
+        inMultiplicand2.copyTo(arrayInMultiplicand2);
+        short[] arrayInOffset = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInOffset, (short) 42);
+        inOffset.copyTo(arrayInOffset);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inMultiplicand1 = arrayInMultiplicand1[i * 4 + j];
+                args.inMultiplicand1Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand1);
+                args.inMultiplicand2 = arrayInMultiplicand2[i * 4 + j];
+                args.inMultiplicand2Double = Float16Utils.convertFloat16ToDouble(args.inMultiplicand2);
+                args.inOffset = arrayInOffset[i * 4 + j];
+                args.inOffsetDouble = Float16Utils.convertFloat16ToDouble(args.inOffset);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMad(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inMultiplicand1: ");
+                        appendVariableToMessage(message, args.inMultiplicand1);
+                        message.append("\n");
+                        message.append("Input inMultiplicand2: ");
+                        appendVariableToMessage(message, args.inMultiplicand2);
+                        message.append("\n");
+                        message.append("Input inOffset: ");
+                        appendVariableToMessage(message, args.inOffset);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMadHalf4Half4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testMad() {
         checkMadFloatFloatFloatFloat();
         checkMadFloat2Float2Float2Float2();
         checkMadFloat3Float3Float3Float3();
         checkMadFloat4Float4Float4Float4();
+        checkMadHalfHalfHalfHalf();
+        checkMadHalf2Half2Half2Half2();
+        checkMadHalf3Half3Half3Half3();
+        checkMadHalf4Half4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMad.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMad.rs
index 735df6f..8131cf9 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMad.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMad.rs
@@ -45,3 +45,27 @@
     float4 inOffset = rsGetElementAt_float4(gAllocInOffset, x);
     return mad(inMultiplicand1, inMultiplicand2, inOffset);
 }
+
+half __attribute__((kernel)) testMadHalfHalfHalfHalf(half inMultiplicand1, unsigned int x) {
+    half inMultiplicand2 = rsGetElementAt_half(gAllocInMultiplicand2, x);
+    half inOffset = rsGetElementAt_half(gAllocInOffset, x);
+    return mad(inMultiplicand1, inMultiplicand2, inOffset);
+}
+
+half2 __attribute__((kernel)) testMadHalf2Half2Half2Half2(half2 inMultiplicand1, unsigned int x) {
+    half2 inMultiplicand2 = rsGetElementAt_half2(gAllocInMultiplicand2, x);
+    half2 inOffset = rsGetElementAt_half2(gAllocInOffset, x);
+    return mad(inMultiplicand1, inMultiplicand2, inOffset);
+}
+
+half3 __attribute__((kernel)) testMadHalf3Half3Half3Half3(half3 inMultiplicand1, unsigned int x) {
+    half3 inMultiplicand2 = rsGetElementAt_half3(gAllocInMultiplicand2, x);
+    half3 inOffset = rsGetElementAt_half3(gAllocInOffset, x);
+    return mad(inMultiplicand1, inMultiplicand2, inOffset);
+}
+
+half4 __attribute__((kernel)) testMadHalf4Half4Half4Half4(half4 inMultiplicand1, unsigned int x) {
+    half4 inMultiplicand2 = rsGetElementAt_half4(gAllocInMultiplicand2, x);
+    half4 inOffset = rsGetElementAt_half4(gAllocInOffset, x);
+    return mad(inMultiplicand1, inMultiplicand2, inOffset);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMax.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMax.java
index 61a8292..f01f791 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMax.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMax.java
@@ -359,6 +359,350 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inA;
+        public double inADouble;
+        public short inB;
+        public double inBDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkMaxHalfHalfHalf() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xb6e25ddbl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xb6e25ddcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMaxHalfHalfHalf(inA, out);
+            verifyResultsMaxHalfHalfHalf(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMaxHalfHalfHalf(inA, out);
+            verifyResultsMaxHalfHalfHalf(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxHalfHalfHalf(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMaxHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMaxHalf2Half2Half2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xf8fc6855l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xf8fc6856l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMaxHalf2Half2Half2(inA, out);
+            verifyResultsMaxHalf2Half2Half2(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMaxHalf2Half2Half2(inA, out);
+            verifyResultsMaxHalf2Half2Half2(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxHalf2Half2Half2(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 2 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 2 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMaxHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMaxHalf3Half3Half3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x579b7924l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x579b7925l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMaxHalf3Half3Half3(inA, out);
+            verifyResultsMaxHalf3Half3Half3(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMaxHalf3Half3Half3(inA, out);
+            verifyResultsMaxHalf3Half3Half3(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxHalf3Half3Half3(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMaxHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMaxHalf4Half4Half4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xb63a89f3l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xb63a89f4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMaxHalf4Half4Half4(inA, out);
+            verifyResultsMaxHalf4Half4Half4(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMaxHalf4Half4Half4(inA, out);
+            verifyResultsMaxHalf4Half4Half4(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxHalf4Half4Half4(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMaxHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     private void checkMaxFloat2FloatFloat2() {
         Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x8592438l, false);
         Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x8592439l, false);
@@ -596,6 +940,258 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    private void checkMaxHalf2HalfHalf2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xf5bbc96fl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xf5bbc970l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMaxHalf2HalfHalf2(inA, out);
+            verifyResultsMaxHalf2HalfHalf2(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalf2HalfHalf2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMaxHalf2HalfHalf2(inA, out);
+            verifyResultsMaxHalf2HalfHalf2(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalf2HalfHalf2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxHalf2HalfHalf2(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 2 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMaxHalf2HalfHalf2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMaxHalf3HalfHalf3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xa8555b13l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xa8555b14l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMaxHalf3HalfHalf3(inA, out);
+            verifyResultsMaxHalf3HalfHalf3(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalf3HalfHalf3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMaxHalf3HalfHalf3(inA, out);
+            verifyResultsMaxHalf3HalfHalf3(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalf3HalfHalf3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxHalf3HalfHalf3(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMaxHalf3HalfHalf3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMaxHalf4HalfHalf4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x5aeeecb7l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x5aeeecb8l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMaxHalf4HalfHalf4(inA, out);
+            verifyResultsMaxHalf4HalfHalf4(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalf4HalfHalf4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMaxHalf4HalfHalf4(inA, out);
+            verifyResultsMaxHalf4HalfHalf4(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMaxHalf4HalfHalf4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMaxHalf4HalfHalf4(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMax(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMaxHalf4HalfHalf4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public class ArgumentsCharCharChar {
         public byte inA;
         public byte inB;
@@ -3145,9 +3741,16 @@
         checkMaxFloat2Float2Float2();
         checkMaxFloat3Float3Float3();
         checkMaxFloat4Float4Float4();
+        checkMaxHalfHalfHalf();
+        checkMaxHalf2Half2Half2();
+        checkMaxHalf3Half3Half3();
+        checkMaxHalf4Half4Half4();
         checkMaxFloat2FloatFloat2();
         checkMaxFloat3FloatFloat3();
         checkMaxFloat4FloatFloat4();
+        checkMaxHalf2HalfHalf2();
+        checkMaxHalf3HalfHalf3();
+        checkMaxHalf4HalfHalf4();
         checkMaxCharCharChar();
         checkMaxChar2Char2Char2();
         checkMaxChar3Char3Char3();
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMax.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMax.rs
index 9a12e95..ae1e739 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMax.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMax.rs
@@ -41,6 +41,26 @@
     return max(inA, inB);
 }
 
+half __attribute__((kernel)) testMaxHalfHalfHalf(half inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return max(inA, inB);
+}
+
+half2 __attribute__((kernel)) testMaxHalf2Half2Half2(half2 inA, unsigned int x) {
+    half2 inB = rsGetElementAt_half2(gAllocInB, x);
+    return max(inA, inB);
+}
+
+half3 __attribute__((kernel)) testMaxHalf3Half3Half3(half3 inA, unsigned int x) {
+    half3 inB = rsGetElementAt_half3(gAllocInB, x);
+    return max(inA, inB);
+}
+
+half4 __attribute__((kernel)) testMaxHalf4Half4Half4(half4 inA, unsigned int x) {
+    half4 inB = rsGetElementAt_half4(gAllocInB, x);
+    return max(inA, inB);
+}
+
 float2 __attribute__((kernel)) testMaxFloat2FloatFloat2(float2 inA, unsigned int x) {
     float inB = rsGetElementAt_float(gAllocInB, x);
     return max(inA, inB);
@@ -56,6 +76,21 @@
     return max(inA, inB);
 }
 
+half2 __attribute__((kernel)) testMaxHalf2HalfHalf2(half2 inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return max(inA, inB);
+}
+
+half3 __attribute__((kernel)) testMaxHalf3HalfHalf3(half3 inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return max(inA, inB);
+}
+
+half4 __attribute__((kernel)) testMaxHalf4HalfHalf4(half4 inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return max(inA, inB);
+}
+
 char __attribute__((kernel)) testMaxCharCharChar(char inA, unsigned int x) {
     char inB = rsGetElementAt_char(gAllocInB, x);
     return max(inA, inB);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMin.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMin.java
index 28fea4e..c806d18 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMin.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMin.java
@@ -359,6 +359,350 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inA;
+        public double inADouble;
+        public short inB;
+        public double inBDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkMinHalfHalfHalf() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xf239c45l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xf239c46l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMinHalfHalfHalf(inA, out);
+            verifyResultsMinHalfHalfHalf(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMinHalfHalfHalf(inA, out);
+            verifyResultsMinHalfHalfHalf(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinHalfHalfHalf(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMinHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMinHalf2Half2Half2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xa8079b33l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xa8079b34l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMinHalf2Half2Half2(inA, out);
+            verifyResultsMinHalf2Half2Half2(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMinHalf2Half2Half2(inA, out);
+            verifyResultsMinHalf2Half2Half2(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinHalf2Half2Half2(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 2 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 2 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMinHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMinHalf3Half3Half3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x6a6ac02l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x6a6ac03l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMinHalf3Half3Half3(inA, out);
+            verifyResultsMinHalf3Half3Half3(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMinHalf3Half3Half3(inA, out);
+            verifyResultsMinHalf3Half3Half3(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinHalf3Half3Half3(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMinHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMinHalf4Half4Half4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x6545bcd1l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x6545bcd2l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMinHalf4Half4Half4(inA, out);
+            verifyResultsMinHalf4Half4Half4(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMinHalf4Half4Half4(inA, out);
+            verifyResultsMinHalf4Half4Half4(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinHalf4Half4Half4(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMinHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     private void checkMinFloat2FloatFloat2() {
         Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x503b89a6l, false);
         Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x503b89a7l, false);
@@ -596,6 +940,258 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    private void checkMinHalf2HalfHalf2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x64f79509l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x64f7950al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMinHalf2HalfHalf2(inA, out);
+            verifyResultsMinHalf2HalfHalf2(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalf2HalfHalf2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMinHalf2HalfHalf2(inA, out);
+            verifyResultsMinHalf2HalfHalf2(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalf2HalfHalf2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinHalf2HalfHalf2(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 2 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMinHalf2HalfHalf2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMinHalf3HalfHalf3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x179126adl, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x179126ael, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMinHalf3HalfHalf3(inA, out);
+            verifyResultsMinHalf3HalfHalf3(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalf3HalfHalf3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMinHalf3HalfHalf3(inA, out);
+            verifyResultsMinHalf3HalfHalf3(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalf3HalfHalf3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinHalf3HalfHalf3(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMinHalf3HalfHalf3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMinHalf4HalfHalf4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xca2ab851l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xca2ab852l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testMinHalf4HalfHalf4(inA, out);
+            verifyResultsMinHalf4HalfHalf4(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalf4HalfHalf4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testMinHalf4HalfHalf4(inA, out);
+            verifyResultsMinHalf4HalfHalf4(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMinHalf4HalfHalf4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMinHalf4HalfHalf4(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMinHalf4HalfHalf4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public class ArgumentsCharCharChar {
         public byte inA;
         public byte inB;
@@ -3145,9 +3741,16 @@
         checkMinFloat2Float2Float2();
         checkMinFloat3Float3Float3();
         checkMinFloat4Float4Float4();
+        checkMinHalfHalfHalf();
+        checkMinHalf2Half2Half2();
+        checkMinHalf3Half3Half3();
+        checkMinHalf4Half4Half4();
         checkMinFloat2FloatFloat2();
         checkMinFloat3FloatFloat3();
         checkMinFloat4FloatFloat4();
+        checkMinHalf2HalfHalf2();
+        checkMinHalf3HalfHalf3();
+        checkMinHalf4HalfHalf4();
         checkMinCharCharChar();
         checkMinChar2Char2Char2();
         checkMinChar3Char3Char3();
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMin.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMin.rs
index d8469bd..998f8c2 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMin.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMin.rs
@@ -41,6 +41,26 @@
     return min(inA, inB);
 }
 
+half __attribute__((kernel)) testMinHalfHalfHalf(half inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return min(inA, inB);
+}
+
+half2 __attribute__((kernel)) testMinHalf2Half2Half2(half2 inA, unsigned int x) {
+    half2 inB = rsGetElementAt_half2(gAllocInB, x);
+    return min(inA, inB);
+}
+
+half3 __attribute__((kernel)) testMinHalf3Half3Half3(half3 inA, unsigned int x) {
+    half3 inB = rsGetElementAt_half3(gAllocInB, x);
+    return min(inA, inB);
+}
+
+half4 __attribute__((kernel)) testMinHalf4Half4Half4(half4 inA, unsigned int x) {
+    half4 inB = rsGetElementAt_half4(gAllocInB, x);
+    return min(inA, inB);
+}
+
 float2 __attribute__((kernel)) testMinFloat2FloatFloat2(float2 inA, unsigned int x) {
     float inB = rsGetElementAt_float(gAllocInB, x);
     return min(inA, inB);
@@ -56,6 +76,21 @@
     return min(inA, inB);
 }
 
+half2 __attribute__((kernel)) testMinHalf2HalfHalf2(half2 inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return min(inA, inB);
+}
+
+half3 __attribute__((kernel)) testMinHalf3HalfHalf3(half3 inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return min(inA, inB);
+}
+
+half4 __attribute__((kernel)) testMinHalf4HalfHalf4(half4 inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return min(inA, inB);
+}
+
 char __attribute__((kernel)) testMinCharCharChar(char inA, unsigned int x) {
     char inB = rsGetElementAt_char(gAllocInB, x);
     return min(inA, inB);
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMix.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMix.java
index cc14f0e..7978f3a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMix.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMix.java
@@ -400,6 +400,396 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalfHalf {
+        public short inStart;
+        public double inStartDouble;
+        public short inStop;
+        public double inStopDouble;
+        public short inFraction;
+        public double inFractionDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkMixHalfHalfHalfHalf() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xa5c04055l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xbc69b07bl, false);
+        Allocation inFraction = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x4936a9cbl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInFraction(inFraction);
+            script.forEach_testMixHalfHalfHalfHalf(inStart, out);
+            verifyResultsMixHalfHalfHalfHalf(inStart, inStop, inFraction, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalfHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInFraction(inFraction);
+            scriptRelaxed.forEach_testMixHalfHalfHalfHalf(inStart, out);
+            verifyResultsMixHalfHalfHalfHalf(inStart, inStop, inFraction, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalfHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixHalfHalfHalfHalf(Allocation inStart, Allocation inStop, Allocation inFraction, Allocation out, boolean relaxed) {
+        short[] arrayInStart = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInStart, (short) 42);
+        inStart.copyTo(arrayInStart);
+        short[] arrayInStop = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInStop, (short) 42);
+        inStop.copyTo(arrayInStop);
+        short[] arrayInFraction = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInFraction, (short) 42);
+        inFraction.copyTo(arrayInFraction);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inStart = arrayInStart[i];
+                args.inStartDouble = Float16Utils.convertFloat16ToDouble(args.inStart);
+                args.inStop = arrayInStop[i];
+                args.inStopDouble = Float16Utils.convertFloat16ToDouble(args.inStop);
+                args.inFraction = arrayInFraction[i];
+                args.inFractionDouble = Float16Utils.convertFloat16ToDouble(args.inFraction);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inStart: ");
+                        appendVariableToMessage(message, args.inStart);
+                        message.append("\n");
+                        message.append("Input inStop: ");
+                        appendVariableToMessage(message, args.inStop);
+                        message.append("\n");
+                        message.append("Input inFraction: ");
+                        appendVariableToMessage(message, args.inFraction);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMixHalfHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMixHalf2Half2Half2Half2() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x2fe5c049l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x7114257l, false);
+        Allocation inFraction = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x5b09ae7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInFraction(inFraction);
+            script.forEach_testMixHalf2Half2Half2Half2(inStart, out);
+            verifyResultsMixHalf2Half2Half2Half2(inStart, inStop, inFraction, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalf2Half2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInFraction(inFraction);
+            scriptRelaxed.forEach_testMixHalf2Half2Half2Half2(inStart, out);
+            verifyResultsMixHalf2Half2Half2Half2(inStart, inStop, inFraction, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalf2Half2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixHalf2Half2Half2Half2(Allocation inStart, Allocation inStop, Allocation inFraction, Allocation out, boolean relaxed) {
+        short[] arrayInStart = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInStart, (short) 42);
+        inStart.copyTo(arrayInStart);
+        short[] arrayInStop = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInStop, (short) 42);
+        inStop.copyTo(arrayInStop);
+        short[] arrayInFraction = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInFraction, (short) 42);
+        inFraction.copyTo(arrayInFraction);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inStart = arrayInStart[i * 2 + j];
+                args.inStartDouble = Float16Utils.convertFloat16ToDouble(args.inStart);
+                args.inStop = arrayInStop[i * 2 + j];
+                args.inStopDouble = Float16Utils.convertFloat16ToDouble(args.inStop);
+                args.inFraction = arrayInFraction[i * 2 + j];
+                args.inFractionDouble = Float16Utils.convertFloat16ToDouble(args.inFraction);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inStart: ");
+                        appendVariableToMessage(message, args.inStart);
+                        message.append("\n");
+                        message.append("Input inStop: ");
+                        appendVariableToMessage(message, args.inStop);
+                        message.append("\n");
+                        message.append("Input inFraction: ");
+                        appendVariableToMessage(message, args.inFraction);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMixHalf2Half2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMixHalf3Half3Half3Half3() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x25babc91l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xcb4bcb2fl, false);
+        Allocation inFraction = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x187ca83fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInFraction(inFraction);
+            script.forEach_testMixHalf3Half3Half3Half3(inStart, out);
+            verifyResultsMixHalf3Half3Half3Half3(inStart, inStop, inFraction, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalf3Half3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInFraction(inFraction);
+            scriptRelaxed.forEach_testMixHalf3Half3Half3Half3(inStart, out);
+            verifyResultsMixHalf3Half3Half3Half3(inStart, inStop, inFraction, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalf3Half3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixHalf3Half3Half3Half3(Allocation inStart, Allocation inStop, Allocation inFraction, Allocation out, boolean relaxed) {
+        short[] arrayInStart = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInStart, (short) 42);
+        inStart.copyTo(arrayInStart);
+        short[] arrayInStop = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInStop, (short) 42);
+        inStop.copyTo(arrayInStop);
+        short[] arrayInFraction = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInFraction, (short) 42);
+        inFraction.copyTo(arrayInFraction);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inStart = arrayInStart[i * 4 + j];
+                args.inStartDouble = Float16Utils.convertFloat16ToDouble(args.inStart);
+                args.inStop = arrayInStop[i * 4 + j];
+                args.inStopDouble = Float16Utils.convertFloat16ToDouble(args.inStop);
+                args.inFraction = arrayInFraction[i * 4 + j];
+                args.inFractionDouble = Float16Utils.convertFloat16ToDouble(args.inFraction);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inStart: ");
+                        appendVariableToMessage(message, args.inStart);
+                        message.append("\n");
+                        message.append("Input inStop: ");
+                        appendVariableToMessage(message, args.inStop);
+                        message.append("\n");
+                        message.append("Input inFraction: ");
+                        appendVariableToMessage(message, args.inFraction);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMixHalf3Half3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMixHalf4Half4Half4Half4() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x1b8fb8d9l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x8f865407l, false);
+        Allocation inFraction = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x2b48b597l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInFraction(inFraction);
+            script.forEach_testMixHalf4Half4Half4Half4(inStart, out);
+            verifyResultsMixHalf4Half4Half4Half4(inStart, inStop, inFraction, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalf4Half4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInFraction(inFraction);
+            scriptRelaxed.forEach_testMixHalf4Half4Half4Half4(inStart, out);
+            verifyResultsMixHalf4Half4Half4Half4(inStart, inStop, inFraction, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalf4Half4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixHalf4Half4Half4Half4(Allocation inStart, Allocation inStop, Allocation inFraction, Allocation out, boolean relaxed) {
+        short[] arrayInStart = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInStart, (short) 42);
+        inStart.copyTo(arrayInStart);
+        short[] arrayInStop = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInStop, (short) 42);
+        inStop.copyTo(arrayInStop);
+        short[] arrayInFraction = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInFraction, (short) 42);
+        inFraction.copyTo(arrayInFraction);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inStart = arrayInStart[i * 4 + j];
+                args.inStartDouble = Float16Utils.convertFloat16ToDouble(args.inStart);
+                args.inStop = arrayInStop[i * 4 + j];
+                args.inStopDouble = Float16Utils.convertFloat16ToDouble(args.inStop);
+                args.inFraction = arrayInFraction[i * 4 + j];
+                args.inFractionDouble = Float16Utils.convertFloat16ToDouble(args.inFraction);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inStart: ");
+                        appendVariableToMessage(message, args.inStart);
+                        message.append("\n");
+                        message.append("Input inStop: ");
+                        appendVariableToMessage(message, args.inStop);
+                        message.append("\n");
+                        message.append("Input inFraction: ");
+                        appendVariableToMessage(message, args.inFraction);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMixHalf4Half4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     private void checkMixFloat2Float2FloatFloat2() {
         Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x2bd1d7c3l, false);
         Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x3c8dd1c5l, false);
@@ -667,13 +1057,305 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    private void checkMixHalf2Half2HalfHalf2() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xc5a4349l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x2fea4b57l, false);
+        Allocation inFraction = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xb339d3e7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInFraction(inFraction);
+            script.forEach_testMixHalf2Half2HalfHalf2(inStart, out);
+            verifyResultsMixHalf2Half2HalfHalf2(inStart, inStop, inFraction, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalf2Half2HalfHalf2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInFraction(inFraction);
+            scriptRelaxed.forEach_testMixHalf2Half2HalfHalf2(inStart, out);
+            verifyResultsMixHalf2Half2HalfHalf2(inStart, inStop, inFraction, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalf2Half2HalfHalf2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixHalf2Half2HalfHalf2(Allocation inStart, Allocation inStop, Allocation inFraction, Allocation out, boolean relaxed) {
+        short[] arrayInStart = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInStart, (short) 42);
+        inStart.copyTo(arrayInStart);
+        short[] arrayInStop = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInStop, (short) 42);
+        inStop.copyTo(arrayInStop);
+        short[] arrayInFraction = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInFraction, (short) 42);
+        inFraction.copyTo(arrayInFraction);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inStart = arrayInStart[i * 2 + j];
+                args.inStartDouble = Float16Utils.convertFloat16ToDouble(args.inStart);
+                args.inStop = arrayInStop[i * 2 + j];
+                args.inStopDouble = Float16Utils.convertFloat16ToDouble(args.inStop);
+                args.inFraction = arrayInFraction[i];
+                args.inFractionDouble = Float16Utils.convertFloat16ToDouble(args.inFraction);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inStart: ");
+                        appendVariableToMessage(message, args.inStart);
+                        message.append("\n");
+                        message.append("Input inStop: ");
+                        appendVariableToMessage(message, args.inStop);
+                        message.append("\n");
+                        message.append("Input inFraction: ");
+                        appendVariableToMessage(message, args.inFraction);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMixHalf2Half2HalfHalf2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMixHalf3Half3HalfHalf3() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x204615a8l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x541973f4l, false);
+        Allocation inFraction = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xb462aa74l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInFraction(inFraction);
+            script.forEach_testMixHalf3Half3HalfHalf3(inStart, out);
+            verifyResultsMixHalf3Half3HalfHalf3(inStart, inStop, inFraction, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalf3Half3HalfHalf3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInFraction(inFraction);
+            scriptRelaxed.forEach_testMixHalf3Half3HalfHalf3(inStart, out);
+            verifyResultsMixHalf3Half3HalfHalf3(inStart, inStop, inFraction, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalf3Half3HalfHalf3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixHalf3Half3HalfHalf3(Allocation inStart, Allocation inStop, Allocation inFraction, Allocation out, boolean relaxed) {
+        short[] arrayInStart = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInStart, (short) 42);
+        inStart.copyTo(arrayInStart);
+        short[] arrayInStop = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInStop, (short) 42);
+        inStop.copyTo(arrayInStop);
+        short[] arrayInFraction = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInFraction, (short) 42);
+        inFraction.copyTo(arrayInFraction);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inStart = arrayInStart[i * 4 + j];
+                args.inStartDouble = Float16Utils.convertFloat16ToDouble(args.inStart);
+                args.inStop = arrayInStop[i * 4 + j];
+                args.inStopDouble = Float16Utils.convertFloat16ToDouble(args.inStop);
+                args.inFraction = arrayInFraction[i];
+                args.inFractionDouble = Float16Utils.convertFloat16ToDouble(args.inFraction);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inStart: ");
+                        appendVariableToMessage(message, args.inStart);
+                        message.append("\n");
+                        message.append("Input inStop: ");
+                        appendVariableToMessage(message, args.inStop);
+                        message.append("\n");
+                        message.append("Input inFraction: ");
+                        appendVariableToMessage(message, args.inFraction);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMixHalf3Half3HalfHalf3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkMixHalf4Half4HalfHalf4() {
+        Allocation inStart = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x3431e807l, false);
+        Allocation inStop = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x78489c91l, false);
+        Allocation inFraction = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xb58b8101l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInStop(inStop);
+            script.set_gAllocInFraction(inFraction);
+            script.forEach_testMixHalf4Half4HalfHalf4(inStart, out);
+            verifyResultsMixHalf4Half4HalfHalf4(inStart, inStop, inFraction, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalf4Half4HalfHalf4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInStop(inStop);
+            scriptRelaxed.set_gAllocInFraction(inFraction);
+            scriptRelaxed.forEach_testMixHalf4Half4HalfHalf4(inStart, out);
+            verifyResultsMixHalf4Half4HalfHalf4(inStart, inStop, inFraction, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testMixHalf4Half4HalfHalf4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsMixHalf4Half4HalfHalf4(Allocation inStart, Allocation inStop, Allocation inFraction, Allocation out, boolean relaxed) {
+        short[] arrayInStart = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInStart, (short) 42);
+        inStart.copyTo(arrayInStart);
+        short[] arrayInStop = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInStop, (short) 42);
+        inStop.copyTo(arrayInStop);
+        short[] arrayInFraction = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInFraction, (short) 42);
+        inFraction.copyTo(arrayInFraction);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalfHalf args = new ArgumentsHalfHalfHalfHalf();
+                args.inStart = arrayInStart[i * 4 + j];
+                args.inStartDouble = Float16Utils.convertFloat16ToDouble(args.inStart);
+                args.inStop = arrayInStop[i * 4 + j];
+                args.inStopDouble = Float16Utils.convertFloat16ToDouble(args.inStop);
+                args.inFraction = arrayInFraction[i];
+                args.inFractionDouble = Float16Utils.convertFloat16ToDouble(args.inFraction);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeMix(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inStart: ");
+                        appendVariableToMessage(message, args.inStart);
+                        message.append("\n");
+                        message.append("Input inStop: ");
+                        appendVariableToMessage(message, args.inStop);
+                        message.append("\n");
+                        message.append("Input inFraction: ");
+                        appendVariableToMessage(message, args.inFraction);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkMixHalf4Half4HalfHalf4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testMix() {
         checkMixFloatFloatFloatFloat();
         checkMixFloat2Float2Float2Float2();
         checkMixFloat3Float3Float3Float3();
         checkMixFloat4Float4Float4Float4();
+        checkMixHalfHalfHalfHalf();
+        checkMixHalf2Half2Half2Half2();
+        checkMixHalf3Half3Half3Half3();
+        checkMixHalf4Half4Half4Half4();
         checkMixFloat2Float2FloatFloat2();
         checkMixFloat3Float3FloatFloat3();
         checkMixFloat4Float4FloatFloat4();
+        checkMixHalf2Half2HalfHalf2();
+        checkMixHalf3Half3HalfHalf3();
+        checkMixHalf4Half4HalfHalf4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMix.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMix.rs
index 94b40cc..b8c7440 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMix.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestMix.rs
@@ -46,6 +46,30 @@
     return mix(inStart, inStop, inFraction);
 }
 
+half __attribute__((kernel)) testMixHalfHalfHalfHalf(half inStart, unsigned int x) {
+    half inStop = rsGetElementAt_half(gAllocInStop, x);
+    half inFraction = rsGetElementAt_half(gAllocInFraction, x);
+    return mix(inStart, inStop, inFraction);
+}
+
+half2 __attribute__((kernel)) testMixHalf2Half2Half2Half2(half2 inStart, unsigned int x) {
+    half2 inStop = rsGetElementAt_half2(gAllocInStop, x);
+    half2 inFraction = rsGetElementAt_half2(gAllocInFraction, x);
+    return mix(inStart, inStop, inFraction);
+}
+
+half3 __attribute__((kernel)) testMixHalf3Half3Half3Half3(half3 inStart, unsigned int x) {
+    half3 inStop = rsGetElementAt_half3(gAllocInStop, x);
+    half3 inFraction = rsGetElementAt_half3(gAllocInFraction, x);
+    return mix(inStart, inStop, inFraction);
+}
+
+half4 __attribute__((kernel)) testMixHalf4Half4Half4Half4(half4 inStart, unsigned int x) {
+    half4 inStop = rsGetElementAt_half4(gAllocInStop, x);
+    half4 inFraction = rsGetElementAt_half4(gAllocInFraction, x);
+    return mix(inStart, inStop, inFraction);
+}
+
 float2 __attribute__((kernel)) testMixFloat2Float2FloatFloat2(float2 inStart, unsigned int x) {
     float2 inStop = rsGetElementAt_float2(gAllocInStop, x);
     float inFraction = rsGetElementAt_float(gAllocInFraction, x);
@@ -63,3 +87,21 @@
     float inFraction = rsGetElementAt_float(gAllocInFraction, x);
     return mix(inStart, inStop, inFraction);
 }
+
+half2 __attribute__((kernel)) testMixHalf2Half2HalfHalf2(half2 inStart, unsigned int x) {
+    half2 inStop = rsGetElementAt_half2(gAllocInStop, x);
+    half inFraction = rsGetElementAt_half(gAllocInFraction, x);
+    return mix(inStart, inStop, inFraction);
+}
+
+half3 __attribute__((kernel)) testMixHalf3Half3HalfHalf3(half3 inStart, unsigned int x) {
+    half3 inStop = rsGetElementAt_half3(gAllocInStop, x);
+    half inFraction = rsGetElementAt_half(gAllocInFraction, x);
+    return mix(inStart, inStop, inFraction);
+}
+
+half4 __attribute__((kernel)) testMixHalf4Half4HalfHalf4(half4 inStart, unsigned int x) {
+    half4 inStop = rsGetElementAt_half4(gAllocInStop, x);
+    half inFraction = rsGetElementAt_half(gAllocInFraction, x);
+    return mix(inStart, inStop, inFraction);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNanHalf.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNanHalf.java
new file mode 100644
index 0000000..51f6fb7
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNanHalf.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/generate.sh.
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.Element;
+import android.renderscript.cts.Target;
+
+import java.util.Arrays;
+
+public class TestNanHalf extends RSBaseCompute {
+
+    private ScriptC_TestNanHalf script;
+    private ScriptC_TestNanHalfRelaxed scriptRelaxed;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        script = new ScriptC_TestNanHalf(mRS);
+        scriptRelaxed = new ScriptC_TestNanHalfRelaxed(mRS);
+    }
+
+    public class ArgumentsHalf {
+        public Target.Floaty out;
+    }
+
+    private void checkNanHalfHalf() {
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNanHalfHalf(out);
+            verifyResultsNanHalfHalf(out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNanHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNanHalfHalf(out);
+            verifyResultsNanHalfHalf(out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNanHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNanHalfHalf(Allocation out, boolean relaxed) {
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalf args = new ArgumentsHalf();
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNanHalf(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNanHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public void testNanHalf() {
+        checkNanHalfHalf();
+    }
+}
diff --git a/tests/uiautomator/app/res/values/styles.xml b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNanHalf.rs
similarity index 65%
copy from tests/uiautomator/app/res/values/styles.xml
copy to tests/tests/renderscript/src/android/renderscript/cts/generated/TestNanHalf.rs
index bce88ae..24a7dcf 100644
--- a/tests/uiautomator/app/res/values/styles.xml
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNanHalf.rs
@@ -1,7 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- * Copyright (C) 2011 The Android Open Source Project
+/*
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,9 +12,14 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- -->
-<resources>
+ */
 
-    <style name="AppTheme" parent="android:Theme.Light" />
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/generate.sh.
 
-</resources>
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+
+half __attribute__((kernel)) testNanHalfHalf() {
+    return nan_half();
+}
diff --git a/tests/uiautomator/app/res/values/styles.xml b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNanHalfRelaxed.rs
similarity index 73%
rename from tests/uiautomator/app/res/values/styles.xml
rename to tests/tests/renderscript/src/android/renderscript/cts/generated/TestNanHalfRelaxed.rs
index bce88ae..619400c 100644
--- a/tests/uiautomator/app/res/values/styles.xml
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNanHalfRelaxed.rs
@@ -1,7 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- * Copyright (C) 2011 The Android Open Source Project
+/*
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,9 +12,9 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- -->
-<resources>
+ */
 
-    <style name="AppTheme" parent="android:Theme.Light" />
+// Don't edit this file!  It is auto-generated by frameworks/rs/api/generate.sh.
 
-</resources>
+#include "TestNanHalf.rs"
+#pragma rs_fp_relaxed
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcos.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcos.java
index 24059a1..2fcd1e3 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcos.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcos.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAcosHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xde848e1el, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeAcosHalfHalf(inV, out);
+            verifyResultsNativeAcosHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcosHalfHalf(inV, out);
+            verifyResultsNativeAcosHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcosHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAcosHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAcosHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xd29d84d0l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeAcosHalf2Half2(inV, out);
+            verifyResultsNativeAcosHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcosHalf2Half2(inV, out);
+            verifyResultsNativeAcosHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcosHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAcosHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAcosHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x31a549c4l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeAcosHalf3Half3(inV, out);
+            verifyResultsNativeAcosHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcosHalf3Half3(inV, out);
+            verifyResultsNativeAcosHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcosHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAcosHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAcosHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x90ad0eb8l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeAcosHalf4Half4(inV, out);
+            verifyResultsNativeAcosHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcosHalf4Half4(inV, out);
+            verifyResultsNativeAcosHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcosHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcosHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAcos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAcosHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeAcos() {
         checkNativeAcosFloatFloat();
         checkNativeAcosFloat2Float2();
         checkNativeAcosFloat3Float3();
         checkNativeAcosFloat4Float4();
+        checkNativeAcosHalfHalf();
+        checkNativeAcosHalf2Half2();
+        checkNativeAcosHalf3Half3();
+        checkNativeAcosHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcos.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcos.rs
index 6562e59..ca5bf5f 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcos.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcos.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeAcosFloat4Float4(float4 inV) {
     return native_acos(inV);
 }
+
+half __attribute__((kernel)) testNativeAcosHalfHalf(half inV) {
+    return native_acos(inV);
+}
+
+half2 __attribute__((kernel)) testNativeAcosHalf2Half2(half2 inV) {
+    return native_acos(inV);
+}
+
+half3 __attribute__((kernel)) testNativeAcosHalf3Half3(half3 inV) {
+    return native_acos(inV);
+}
+
+half4 __attribute__((kernel)) testNativeAcosHalf4Half4(half4 inV) {
+    return native_acos(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcosh.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcosh.java
index 561419c..8c609d4 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcosh.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcosh.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAcoshHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x34f17c04l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeAcoshHalfHalf(inV, out);
+            verifyResultsNativeAcoshHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcoshHalfHalf(inV, out);
+            verifyResultsNativeAcoshHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcoshHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAcoshHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAcoshHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xb5fc706l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeAcoshHalf2Half2(inV, out);
+            verifyResultsNativeAcoshHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcoshHalf2Half2(inV, out);
+            verifyResultsNativeAcoshHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcoshHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAcoshHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAcoshHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x6a678bfal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeAcoshHalf3Half3(inV, out);
+            verifyResultsNativeAcoshHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcoshHalf3Half3(inV, out);
+            verifyResultsNativeAcoshHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcoshHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAcoshHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAcoshHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xc96f50eel, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeAcoshHalf4Half4(inV, out);
+            verifyResultsNativeAcoshHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcoshHalf4Half4(inV, out);
+            verifyResultsNativeAcoshHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcoshHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcoshHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAcosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAcoshHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeAcosh() {
         checkNativeAcoshFloatFloat();
         checkNativeAcoshFloat2Float2();
         checkNativeAcoshFloat3Float3();
         checkNativeAcoshFloat4Float4();
+        checkNativeAcoshHalfHalf();
+        checkNativeAcoshHalf2Half2();
+        checkNativeAcoshHalf3Half3();
+        checkNativeAcoshHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcosh.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcosh.rs
index 7d7c945..e050468 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcosh.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcosh.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeAcoshFloat4Float4(float4 inV) {
     return native_acosh(inV);
 }
+
+half __attribute__((kernel)) testNativeAcoshHalfHalf(half inV) {
+    return native_acosh(inV);
+}
+
+half2 __attribute__((kernel)) testNativeAcoshHalf2Half2(half2 inV) {
+    return native_acosh(inV);
+}
+
+half3 __attribute__((kernel)) testNativeAcoshHalf3Half3(half3 inV) {
+    return native_acosh(inV);
+}
+
+half4 __attribute__((kernel)) testNativeAcoshHalf4Half4(half4 inV) {
+    return native_acosh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcospi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcospi.java
index 02625f8..1a71e07 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcospi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcospi.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAcospiHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xcf2d81e1l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeAcospiHalfHalf(inV, out);
+            verifyResultsNativeAcospiHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcospiHalfHalf(inV, out);
+            verifyResultsNativeAcospiHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcospiHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAcospiHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAcospiHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x6e6203bl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeAcospiHalf2Half2(inV, out);
+            verifyResultsNativeAcospiHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcospiHalf2Half2(inV, out);
+            verifyResultsNativeAcospiHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcospiHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAcospiHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAcospiHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x65ede52fl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeAcospiHalf3Half3(inV, out);
+            verifyResultsNativeAcospiHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcospiHalf3Half3(inV, out);
+            verifyResultsNativeAcospiHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcospiHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAcospiHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAcospiHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xc4f5aa23l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeAcospiHalf4Half4(inV, out);
+            verifyResultsNativeAcospiHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAcospiHalf4Half4(inV, out);
+            verifyResultsNativeAcospiHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAcospiHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAcospiHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAcospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAcospiHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeAcospi() {
         checkNativeAcospiFloatFloat();
         checkNativeAcospiFloat2Float2();
         checkNativeAcospiFloat3Float3();
         checkNativeAcospiFloat4Float4();
+        checkNativeAcospiHalfHalf();
+        checkNativeAcospiHalf2Half2();
+        checkNativeAcospiHalf3Half3();
+        checkNativeAcospiHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcospi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcospi.rs
index aa761ed..612cf26 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcospi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAcospi.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeAcospiFloat4Float4(float4 inV) {
     return native_acospi(inV);
 }
+
+half __attribute__((kernel)) testNativeAcospiHalfHalf(half inV) {
+    return native_acospi(inV);
+}
+
+half2 __attribute__((kernel)) testNativeAcospiHalf2Half2(half2 inV) {
+    return native_acospi(inV);
+}
+
+half3 __attribute__((kernel)) testNativeAcospiHalf3Half3(half3 inV) {
+    return native_acospi(inV);
+}
+
+half4 __attribute__((kernel)) testNativeAcospiHalf4Half4(half4 inV) {
+    return native_acospi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsin.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsin.java
index 513147f..442b62a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsin.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsin.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAsinHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x228512e9l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeAsinHalfHalf(inV, out);
+            verifyResultsNativeAsinHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinHalfHalf(inV, out);
+            verifyResultsNativeAsinHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAsinHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAsinHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xfa5ca303l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeAsinHalf2Half2(inV, out);
+            verifyResultsNativeAsinHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinHalf2Half2(inV, out);
+            verifyResultsNativeAsinHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAsinHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAsinHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x596467f7l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeAsinHalf3Half3(inV, out);
+            verifyResultsNativeAsinHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinHalf3Half3(inV, out);
+            verifyResultsNativeAsinHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAsinHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAsinHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xb86c2cebl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeAsinHalf4Half4(inV, out);
+            verifyResultsNativeAsinHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinHalf4Half4(inV, out);
+            verifyResultsNativeAsinHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAsin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAsinHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeAsin() {
         checkNativeAsinFloatFloat();
         checkNativeAsinFloat2Float2();
         checkNativeAsinFloat3Float3();
         checkNativeAsinFloat4Float4();
+        checkNativeAsinHalfHalf();
+        checkNativeAsinHalf2Half2();
+        checkNativeAsinHalf3Half3();
+        checkNativeAsinHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsin.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsin.rs
index f4086e7..ddb08c2 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsin.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsin.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeAsinFloat4Float4(float4 inV) {
     return native_asin(inV);
 }
+
+half __attribute__((kernel)) testNativeAsinHalfHalf(half inV) {
+    return native_asin(inV);
+}
+
+half2 __attribute__((kernel)) testNativeAsinHalf2Half2(half2 inV) {
+    return native_asin(inV);
+}
+
+half3 __attribute__((kernel)) testNativeAsinHalf3Half3(half3 inV) {
+    return native_asin(inV);
+}
+
+half4 __attribute__((kernel)) testNativeAsinHalf4Half4(half4 inV) {
+    return native_asin(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinh.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinh.java
index ebdb5de..581e80c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinh.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinh.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAsinhHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xa107ca1dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeAsinhHalfHalf(inV, out);
+            verifyResultsNativeAsinhHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinhHalfHalf(inV, out);
+            verifyResultsNativeAsinhHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinhHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAsinhHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAsinhHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xb879d997l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeAsinhHalf2Half2(inV, out);
+            verifyResultsNativeAsinhHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinhHalf2Half2(inV, out);
+            verifyResultsNativeAsinhHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinhHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAsinhHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAsinhHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x17819e8bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeAsinhHalf3Half3(inV, out);
+            verifyResultsNativeAsinhHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinhHalf3Half3(inV, out);
+            verifyResultsNativeAsinhHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinhHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAsinhHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAsinhHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x7689637fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeAsinhHalf4Half4(inV, out);
+            verifyResultsNativeAsinhHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinhHalf4Half4(inV, out);
+            verifyResultsNativeAsinhHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinhHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinhHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAsinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAsinhHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeAsinh() {
         checkNativeAsinhFloatFloat();
         checkNativeAsinhFloat2Float2();
         checkNativeAsinhFloat3Float3();
         checkNativeAsinhFloat4Float4();
+        checkNativeAsinhHalfHalf();
+        checkNativeAsinhHalf2Half2();
+        checkNativeAsinhHalf3Half3();
+        checkNativeAsinhHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinh.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinh.rs
index 0e48891..1b21ce7 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinh.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinh.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeAsinhFloat4Float4(float4 inV) {
     return native_asinh(inV);
 }
+
+half __attribute__((kernel)) testNativeAsinhHalfHalf(half inV) {
+    return native_asinh(inV);
+}
+
+half2 __attribute__((kernel)) testNativeAsinhHalf2Half2(half2 inV) {
+    return native_asinh(inV);
+}
+
+half3 __attribute__((kernel)) testNativeAsinhHalf3Half3(half3 inV) {
+    return native_asinh(inV);
+}
+
+half4 __attribute__((kernel)) testNativeAsinhHalf4Half4(half4 inV) {
+    return native_asinh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinpi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinpi.java
index e0acde3..5a40037 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinpi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinpi.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAsinpiHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xf6eca014l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeAsinpiHalfHalf(inV, out);
+            verifyResultsNativeAsinpiHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinpiHalfHalf(inV, out);
+            verifyResultsNativeAsinpiHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinpiHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAsinpiHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAsinpiHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x1a473e96l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeAsinpiHalf2Half2(inV, out);
+            verifyResultsNativeAsinpiHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinpiHalf2Half2(inV, out);
+            verifyResultsNativeAsinpiHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinpiHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAsinpiHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAsinpiHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x794f038al, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeAsinpiHalf3Half3(inV, out);
+            verifyResultsNativeAsinpiHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinpiHalf3Half3(inV, out);
+            verifyResultsNativeAsinpiHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinpiHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAsinpiHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAsinpiHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xd856c87el, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeAsinpiHalf4Half4(inV, out);
+            verifyResultsNativeAsinpiHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAsinpiHalf4Half4(inV, out);
+            verifyResultsNativeAsinpiHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAsinpiHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAsinpiHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAsinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAsinpiHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeAsinpi() {
         checkNativeAsinpiFloatFloat();
         checkNativeAsinpiFloat2Float2();
         checkNativeAsinpiFloat3Float3();
         checkNativeAsinpiFloat4Float4();
+        checkNativeAsinpiHalfHalf();
+        checkNativeAsinpiHalf2Half2();
+        checkNativeAsinpiHalf3Half3();
+        checkNativeAsinpiHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinpi.rs
index ec278cc..863e42c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinpi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAsinpi.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeAsinpiFloat4Float4(float4 inV) {
     return native_asinpi(inV);
 }
+
+half __attribute__((kernel)) testNativeAsinpiHalfHalf(half inV) {
+    return native_asinpi(inV);
+}
+
+half2 __attribute__((kernel)) testNativeAsinpiHalf2Half2(half2 inV) {
+    return native_asinpi(inV);
+}
+
+half3 __attribute__((kernel)) testNativeAsinpiHalf3Half3(half3 inV) {
+    return native_asinpi(inV);
+}
+
+half4 __attribute__((kernel)) testNativeAsinpiHalf4Half4(half4 inV) {
+    return native_asinpi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan.java
index 54b52cd..d12a831 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAtanHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x8d59863cl, -1,  1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeAtanHalfHalf(inV, out);
+            verifyResultsNativeAtanHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanHalfHalf(inV, out);
+            verifyResultsNativeAtanHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtanHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtanHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x92d1957el, -1,  1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeAtanHalf2Half2(inV, out);
+            verifyResultsNativeAtanHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanHalf2Half2(inV, out);
+            verifyResultsNativeAtanHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtanHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtanHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xf1d95a72l, -1,  1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeAtanHalf3Half3(inV, out);
+            verifyResultsNativeAtanHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanHalf3Half3(inV, out);
+            verifyResultsNativeAtanHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtanHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtanHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x50e11f66l, -1,  1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeAtanHalf4Half4(inV, out);
+            verifyResultsNativeAtanHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanHalf4Half4(inV, out);
+            verifyResultsNativeAtanHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtanHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeAtan() {
         checkNativeAtanFloatFloat();
         checkNativeAtanFloat2Float2();
         checkNativeAtanFloat3Float3();
         checkNativeAtanFloat4Float4();
+        checkNativeAtanHalfHalf();
+        checkNativeAtanHalf2Half2();
+        checkNativeAtanHalf3Half3();
+        checkNativeAtanHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan.rs
index 06c94c1..72887bc 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeAtanFloat4Float4(float4 inV) {
     return native_atan(inV);
 }
+
+half __attribute__((kernel)) testNativeAtanHalfHalf(half inV) {
+    return native_atan(inV);
+}
+
+half2 __attribute__((kernel)) testNativeAtanHalf2Half2(half2 inV) {
+    return native_atan(inV);
+}
+
+half3 __attribute__((kernel)) testNativeAtanHalf3Half3(half3 inV) {
+    return native_atan(inV);
+}
+
+half4 __attribute__((kernel)) testNativeAtanHalf4Half4(half4 inV) {
+    return native_atan(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2.java
index 63569fd..8d2a826 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inNumerator;
+        public double inNumeratorDouble;
+        public short inDenominator;
+        public double inDenominatorDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAtan2HalfHalfHalf() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe3d252c0l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe16255f9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testNativeAtan2HalfHalfHalf(inNumerator, out);
+            verifyResultsNativeAtan2HalfHalfHalf(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2HalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testNativeAtan2HalfHalfHalf(inNumerator, out);
+            verifyResultsNativeAtan2HalfHalfHalf(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2HalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2HalfHalfHalf(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtan2HalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtan2Half2Half2Half2() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x51d7124l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x58f0d63dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testNativeAtan2Half2Half2Half2(inNumerator, out);
+            verifyResultsNativeAtan2Half2Half2Half2(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2Half2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testNativeAtan2Half2Half2Half2(inNumerator, out);
+            verifyResultsNativeAtan2Half2Half2Half2(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2Half2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2Half2Half2Half2(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 2 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 2 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtan2Half2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtan2Half3Half3Half3() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x508fa193l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x44b0a7f4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testNativeAtan2Half3Half3Half3(inNumerator, out);
+            verifyResultsNativeAtan2Half3Half3Half3(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2Half3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testNativeAtan2Half3Half3Half3(inNumerator, out);
+            verifyResultsNativeAtan2Half3Half3Half3(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2Half3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2Half3Half3Half3(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 4 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 4 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtan2Half3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtan2Half4Half4Half4() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x9c01d202l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x307079abl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testNativeAtan2Half4Half4Half4(inNumerator, out);
+            verifyResultsNativeAtan2Half4Half4Half4(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2Half4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testNativeAtan2Half4Half4Half4(inNumerator, out);
+            verifyResultsNativeAtan2Half4Half4Half4(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2Half4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2Half4Half4Half4(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 4 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 4 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtan2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtan2Half4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeAtan2() {
         checkNativeAtan2FloatFloatFloat();
         checkNativeAtan2Float2Float2Float2();
         checkNativeAtan2Float3Float3Float3();
         checkNativeAtan2Float4Float4Float4();
+        checkNativeAtan2HalfHalfHalf();
+        checkNativeAtan2Half2Half2Half2();
+        checkNativeAtan2Half3Half3Half3();
+        checkNativeAtan2Half4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2.rs
index feda737..2142819 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2.rs
@@ -40,3 +40,23 @@
     float4 inDenominator = rsGetElementAt_float4(gAllocInDenominator, x);
     return native_atan2(inNumerator, inDenominator);
 }
+
+half __attribute__((kernel)) testNativeAtan2HalfHalfHalf(half inNumerator, unsigned int x) {
+    half inDenominator = rsGetElementAt_half(gAllocInDenominator, x);
+    return native_atan2(inNumerator, inDenominator);
+}
+
+half2 __attribute__((kernel)) testNativeAtan2Half2Half2Half2(half2 inNumerator, unsigned int x) {
+    half2 inDenominator = rsGetElementAt_half2(gAllocInDenominator, x);
+    return native_atan2(inNumerator, inDenominator);
+}
+
+half3 __attribute__((kernel)) testNativeAtan2Half3Half3Half3(half3 inNumerator, unsigned int x) {
+    half3 inDenominator = rsGetElementAt_half3(gAllocInDenominator, x);
+    return native_atan2(inNumerator, inDenominator);
+}
+
+half4 __attribute__((kernel)) testNativeAtan2Half4Half4Half4(half4 inNumerator, unsigned int x) {
+    half4 inDenominator = rsGetElementAt_half4(gAllocInDenominator, x);
+    return native_atan2(inNumerator, inDenominator);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2pi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2pi.java
index c12db90..572c8c8 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2pi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2pi.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inNumerator;
+        public double inNumeratorDouble;
+        public short inDenominator;
+        public double inDenominatorDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAtan2piHalfHalfHalf() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x474bf8c3l, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x5b0261a4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testNativeAtan2piHalfHalfHalf(inNumerator, out);
+            verifyResultsNativeAtan2piHalfHalfHalf(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testNativeAtan2piHalfHalfHalf(inNumerator, out);
+            verifyResultsNativeAtan2piHalfHalfHalf(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2piHalfHalfHalf(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtan2piHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtan2piHalf2Half2Half2() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x72ff66ddl, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xfdf89b6el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testNativeAtan2piHalf2Half2Half2(inNumerator, out);
+            verifyResultsNativeAtan2piHalf2Half2Half2(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testNativeAtan2piHalf2Half2Half2(inNumerator, out);
+            verifyResultsNativeAtan2piHalf2Half2Half2(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2piHalf2Half2Half2(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 2 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 2 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtan2piHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtan2piHalf3Half3Half3() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xbe71974cl, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xe9b86d25l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testNativeAtan2piHalf3Half3Half3(inNumerator, out);
+            verifyResultsNativeAtan2piHalf3Half3Half3(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testNativeAtan2piHalf3Half3Half3(inNumerator, out);
+            verifyResultsNativeAtan2piHalf3Half3Half3(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2piHalf3Half3Half3(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 4 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 4 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtan2piHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtan2piHalf4Half4Half4() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x9e3c7bbl, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xd5783edcl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testNativeAtan2piHalf4Half4Half4(inNumerator, out);
+            verifyResultsNativeAtan2piHalf4Half4Half4(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testNativeAtan2piHalf4Half4Half4(inNumerator, out);
+            verifyResultsNativeAtan2piHalf4Half4Half4(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtan2piHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtan2piHalf4Half4Half4(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 4 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 4 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtan2pi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtan2piHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeAtan2pi() {
         checkNativeAtan2piFloatFloatFloat();
         checkNativeAtan2piFloat2Float2Float2();
         checkNativeAtan2piFloat3Float3Float3();
         checkNativeAtan2piFloat4Float4Float4();
+        checkNativeAtan2piHalfHalfHalf();
+        checkNativeAtan2piHalf2Half2Half2();
+        checkNativeAtan2piHalf3Half3Half3();
+        checkNativeAtan2piHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2pi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2pi.rs
index ad88624..cf3f66d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2pi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtan2pi.rs
@@ -40,3 +40,23 @@
     float4 inDenominator = rsGetElementAt_float4(gAllocInDenominator, x);
     return native_atan2pi(inNumerator, inDenominator);
 }
+
+half __attribute__((kernel)) testNativeAtan2piHalfHalfHalf(half inNumerator, unsigned int x) {
+    half inDenominator = rsGetElementAt_half(gAllocInDenominator, x);
+    return native_atan2pi(inNumerator, inDenominator);
+}
+
+half2 __attribute__((kernel)) testNativeAtan2piHalf2Half2Half2(half2 inNumerator, unsigned int x) {
+    half2 inDenominator = rsGetElementAt_half2(gAllocInDenominator, x);
+    return native_atan2pi(inNumerator, inDenominator);
+}
+
+half3 __attribute__((kernel)) testNativeAtan2piHalf3Half3Half3(half3 inNumerator, unsigned int x) {
+    half3 inDenominator = rsGetElementAt_half3(gAllocInDenominator, x);
+    return native_atan2pi(inNumerator, inDenominator);
+}
+
+half4 __attribute__((kernel)) testNativeAtan2piHalf4Half4Half4(half4 inNumerator, unsigned int x) {
+    half4 inDenominator = rsGetElementAt_half4(gAllocInDenominator, x);
+    return native_atan2pi(inNumerator, inDenominator);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanh.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanh.java
index 72009d6..f8bd311 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanh.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanh.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAtanhHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x92b7290el, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeAtanhHalfHalf(inV, out);
+            verifyResultsNativeAtanhHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanhHalfHalf(inV, out);
+            verifyResultsNativeAtanhHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanhHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtanhHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtanhHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x541e9440l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeAtanhHalf2Half2(inV, out);
+            verifyResultsNativeAtanhHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanhHalf2Half2(inV, out);
+            verifyResultsNativeAtanhHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanhHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtanhHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtanhHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb3265934l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeAtanhHalf3Half3(inV, out);
+            verifyResultsNativeAtanhHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanhHalf3Half3(inV, out);
+            verifyResultsNativeAtanhHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanhHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtanhHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtanhHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x122e1e28l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeAtanhHalf4Half4(inV, out);
+            verifyResultsNativeAtanhHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanhHalf4Half4(inV, out);
+            verifyResultsNativeAtanhHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanhHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanhHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtanhHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeAtanh() {
         checkNativeAtanhFloatFloat();
         checkNativeAtanhFloat2Float2();
         checkNativeAtanhFloat3Float3();
         checkNativeAtanhFloat4Float4();
+        checkNativeAtanhHalfHalf();
+        checkNativeAtanhHalf2Half2();
+        checkNativeAtanhHalf3Half3();
+        checkNativeAtanhHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanh.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanh.rs
index b4a4a0a..7e117f3 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanh.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanh.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeAtanhFloat4Float4(float4 inV) {
     return native_atanh(inV);
 }
+
+half __attribute__((kernel)) testNativeAtanhHalfHalf(half inV) {
+    return native_atanh(inV);
+}
+
+half2 __attribute__((kernel)) testNativeAtanhHalf2Half2(half2 inV) {
+    return native_atanh(inV);
+}
+
+half3 __attribute__((kernel)) testNativeAtanhHalf3Half3(half3 inV) {
+    return native_atanh(inV);
+}
+
+half4 __attribute__((kernel)) testNativeAtanhHalf4Half4(half4 inV) {
+    return native_atanh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanpi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanpi.java
index f3c64c6..1ae95de 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanpi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanpi.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeAtanpiHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x8f61928fl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeAtanpiHalfHalf(inV, out);
+            verifyResultsNativeAtanpiHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanpiHalfHalf(inV, out);
+            verifyResultsNativeAtanpiHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanpiHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtanpiHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtanpiHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x3ef298f9l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeAtanpiHalf2Half2(inV, out);
+            verifyResultsNativeAtanpiHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanpiHalf2Half2(inV, out);
+            verifyResultsNativeAtanpiHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanpiHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtanpiHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtanpiHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x9dfa5dedl, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeAtanpiHalf3Half3(inV, out);
+            verifyResultsNativeAtanpiHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanpiHalf3Half3(inV, out);
+            verifyResultsNativeAtanpiHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanpiHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtanpiHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeAtanpiHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xfd0222e1l, -1, 1);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeAtanpiHalf4Half4(inV, out);
+            verifyResultsNativeAtanpiHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeAtanpiHalf4Half4(inV, out);
+            verifyResultsNativeAtanpiHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeAtanpiHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeAtanpiHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeAtanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeAtanpiHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeAtanpi() {
         checkNativeAtanpiFloatFloat();
         checkNativeAtanpiFloat2Float2();
         checkNativeAtanpiFloat3Float3();
         checkNativeAtanpiFloat4Float4();
+        checkNativeAtanpiHalfHalf();
+        checkNativeAtanpiHalf2Half2();
+        checkNativeAtanpiHalf3Half3();
+        checkNativeAtanpiHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanpi.rs
index 2f8d1c2..6eb4f87 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanpi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeAtanpi.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeAtanpiFloat4Float4(float4 inV) {
     return native_atanpi(inV);
 }
+
+half __attribute__((kernel)) testNativeAtanpiHalfHalf(half inV) {
+    return native_atanpi(inV);
+}
+
+half2 __attribute__((kernel)) testNativeAtanpiHalf2Half2(half2 inV) {
+    return native_atanpi(inV);
+}
+
+half3 __attribute__((kernel)) testNativeAtanpiHalf3Half3(half3 inV) {
+    return native_atanpi(inV);
+}
+
+half4 __attribute__((kernel)) testNativeAtanpiHalf4Half4(half4 inV) {
+    return native_atanpi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCbrt.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCbrt.java
index 1a98da2..f561747 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCbrt.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCbrt.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeCbrtHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x54b706bbl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeCbrtHalfHalf(inV, out);
+            verifyResultsNativeCbrtHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCbrtHalfHalf(inV, out);
+            verifyResultsNativeCbrtHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCbrtHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCbrtHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeCbrtHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x8526aac5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeCbrtHalf2Half2(inV, out);
+            verifyResultsNativeCbrtHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCbrtHalf2Half2(inV, out);
+            verifyResultsNativeCbrtHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCbrtHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCbrtHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeCbrtHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xe42e6fb9l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeCbrtHalf3Half3(inV, out);
+            verifyResultsNativeCbrtHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCbrtHalf3Half3(inV, out);
+            verifyResultsNativeCbrtHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCbrtHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCbrtHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeCbrtHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x433634adl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeCbrtHalf4Half4(inV, out);
+            verifyResultsNativeCbrtHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCbrtHalf4Half4(inV, out);
+            verifyResultsNativeCbrtHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCbrtHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCbrtHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCbrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCbrtHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeCbrt() {
         checkNativeCbrtFloatFloat();
         checkNativeCbrtFloat2Float2();
         checkNativeCbrtFloat3Float3();
         checkNativeCbrtFloat4Float4();
+        checkNativeCbrtHalfHalf();
+        checkNativeCbrtHalf2Half2();
+        checkNativeCbrtHalf3Half3();
+        checkNativeCbrtHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCbrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCbrt.rs
index c61100b..38e972a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCbrt.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCbrt.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeCbrtFloat4Float4(float4 inV) {
     return native_cbrt(inV);
 }
+
+half __attribute__((kernel)) testNativeCbrtHalfHalf(half inV) {
+    return native_cbrt(inV);
+}
+
+half2 __attribute__((kernel)) testNativeCbrtHalf2Half2(half2 inV) {
+    return native_cbrt(inV);
+}
+
+half3 __attribute__((kernel)) testNativeCbrtHalf3Half3(half3 inV) {
+    return native_cbrt(inV);
+}
+
+half4 __attribute__((kernel)) testNativeCbrtHalf4Half4(half4 inV) {
+    return native_cbrt(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCos.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCos.java
index 51b85fa..1aefbed 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCos.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCos.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeCosHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x8f9bf427l, -314, 314);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeCosHalfHalf(inV, out);
+            verifyResultsNativeCosHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCosHalfHalf(inV, out);
+            verifyResultsNativeCosHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCosHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCosHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeCosHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xe49d7bd1l, -314, 314);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeCosHalf2Half2(inV, out);
+            verifyResultsNativeCosHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCosHalf2Half2(inV, out);
+            verifyResultsNativeCosHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCosHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCosHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeCosHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x43a540c5l, -314, 314);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeCosHalf3Half3(inV, out);
+            verifyResultsNativeCosHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCosHalf3Half3(inV, out);
+            verifyResultsNativeCosHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCosHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCosHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeCosHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xa2ad05b9l, -314, 314);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeCosHalf4Half4(inV, out);
+            verifyResultsNativeCosHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCosHalf4Half4(inV, out);
+            verifyResultsNativeCosHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCosHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCosHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCosHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeCos() {
         checkNativeCosFloatFloat();
         checkNativeCosFloat2Float2();
         checkNativeCosFloat3Float3();
         checkNativeCosFloat4Float4();
+        checkNativeCosHalfHalf();
+        checkNativeCosHalf2Half2();
+        checkNativeCosHalf3Half3();
+        checkNativeCosHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCos.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCos.rs
index 0d97777..dac5219 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCos.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCos.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeCosFloat4Float4(float4 inV) {
     return native_cos(inV);
 }
+
+half __attribute__((kernel)) testNativeCosHalfHalf(half inV) {
+    return native_cos(inV);
+}
+
+half2 __attribute__((kernel)) testNativeCosHalf2Half2(half2 inV) {
+    return native_cos(inV);
+}
+
+half3 __attribute__((kernel)) testNativeCosHalf3Half3(half3 inV) {
+    return native_cos(inV);
+}
+
+half4 __attribute__((kernel)) testNativeCosHalf4Half4(half4 inV) {
+    return native_cos(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCosh.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCosh.java
index c9918d2..4d5ec23 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCosh.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCosh.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeCoshHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xf3df9f87l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeCoshHalfHalf(inV, out);
+            verifyResultsNativeCoshHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCoshHalfHalf(inV, out);
+            verifyResultsNativeCoshHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCoshHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCoshHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeCoshHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x115e4431l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeCoshHalf2Half2(inV, out);
+            verifyResultsNativeCoshHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCoshHalf2Half2(inV, out);
+            verifyResultsNativeCoshHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCoshHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCoshHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeCoshHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x70660925l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeCoshHalf3Half3(inV, out);
+            verifyResultsNativeCoshHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCoshHalf3Half3(inV, out);
+            verifyResultsNativeCoshHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCoshHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCoshHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeCoshHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xcf6dce19l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeCoshHalf4Half4(inV, out);
+            verifyResultsNativeCoshHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCoshHalf4Half4(inV, out);
+            verifyResultsNativeCoshHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCoshHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCoshHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCosh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCoshHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeCosh() {
         checkNativeCoshFloatFloat();
         checkNativeCoshFloat2Float2();
         checkNativeCoshFloat3Float3();
         checkNativeCoshFloat4Float4();
+        checkNativeCoshHalfHalf();
+        checkNativeCoshHalf2Half2();
+        checkNativeCoshHalf3Half3();
+        checkNativeCoshHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCosh.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCosh.rs
index 97f178d..364c84e 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCosh.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCosh.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeCoshFloat4Float4(float4 inV) {
     return native_cosh(inV);
 }
+
+half __attribute__((kernel)) testNativeCoshHalfHalf(half inV) {
+    return native_cosh(inV);
+}
+
+half2 __attribute__((kernel)) testNativeCoshHalf2Half2(half2 inV) {
+    return native_cosh(inV);
+}
+
+half3 __attribute__((kernel)) testNativeCoshHalf3Half3(half3 inV) {
+    return native_cosh(inV);
+}
+
+half4 __attribute__((kernel)) testNativeCoshHalf4Half4(half4 inV) {
+    return native_cosh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCospi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCospi.java
index bbefc75..5a6aa10 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCospi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCospi.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeCospiHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe12d78e2l, -100, 100);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeCospiHalfHalf(inV, out);
+            verifyResultsNativeCospiHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCospiHalfHalf(inV, out);
+            verifyResultsNativeCospiHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCospiHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCospiHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeCospiHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x8a52674l, -100, 100);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeCospiHalf2Half2(inV, out);
+            verifyResultsNativeCospiHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCospiHalf2Half2(inV, out);
+            verifyResultsNativeCospiHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCospiHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCospiHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeCospiHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x67aceb68l, -100, 100);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeCospiHalf3Half3(inV, out);
+            verifyResultsNativeCospiHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCospiHalf3Half3(inV, out);
+            verifyResultsNativeCospiHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCospiHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCospiHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeCospiHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xc6b4b05cl, -100, 100);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeCospiHalf4Half4(inV, out);
+            verifyResultsNativeCospiHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeCospiHalf4Half4(inV, out);
+            verifyResultsNativeCospiHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeCospiHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeCospiHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeCospi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeCospiHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeCospi() {
         checkNativeCospiFloatFloat();
         checkNativeCospiFloat2Float2();
         checkNativeCospiFloat3Float3();
         checkNativeCospiFloat4Float4();
+        checkNativeCospiHalfHalf();
+        checkNativeCospiHalf2Half2();
+        checkNativeCospiHalf3Half3();
+        checkNativeCospiHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCospi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCospi.rs
index dea2770..fbb5028 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCospi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeCospi.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeCospiFloat4Float4(float4 inV) {
     return native_cospi(inV);
 }
+
+half __attribute__((kernel)) testNativeCospiHalfHalf(half inV) {
+    return native_cospi(inV);
+}
+
+half2 __attribute__((kernel)) testNativeCospiHalf2Half2(half2 inV) {
+    return native_cospi(inV);
+}
+
+half3 __attribute__((kernel)) testNativeCospiHalf3Half3(half3 inV) {
+    return native_cospi(inV);
+}
+
+half4 __attribute__((kernel)) testNativeCospiHalf4Half4(half4 inV) {
+    return native_cospi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDistance.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDistance.java
index bf4f898..ced227b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDistance.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDistance.java
@@ -383,10 +383,390 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inLeftVector;
+        public double inLeftVectorDouble;
+        public short inRightVector;
+        public double inRightVectorDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeDistanceHalfHalfHalf() {
+        Allocation inLeftVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x4093c950l, false);
+        Allocation inRightVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x46eb99f5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInRightVector(inRightVector);
+            script.forEach_testNativeDistanceHalfHalfHalf(inLeftVector, out);
+            verifyResultsNativeDistanceHalfHalfHalf(inLeftVector, inRightVector, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRightVector(inRightVector);
+            scriptRelaxed.forEach_testNativeDistanceHalfHalfHalf(inLeftVector, out);
+            verifyResultsNativeDistanceHalfHalfHalf(inLeftVector, inRightVector, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDistanceHalfHalfHalf(Allocation inLeftVector, Allocation inRightVector, Allocation out, boolean relaxed) {
+        short[] arrayInLeftVector = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInLeftVector, (short) 42);
+        inLeftVector.copyTo(arrayInLeftVector);
+        short[] arrayInRightVector = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInRightVector, (short) 42);
+        inRightVector.copyTo(arrayInRightVector);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+            // Create the appropriate sized arrays in args
+            // Fill args with the input values
+            args.inLeftVector = arrayInLeftVector[i];
+            args.inLeftVectorDouble = Float16Utils.convertFloat16ToDouble(args.inLeftVector);
+            args.inRightVector = arrayInRightVector[i];
+            args.inRightVectorDouble = Float16Utils.convertFloat16ToDouble(args.inRightVector);
+            Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+            CoreMathVerifier.computeNativeDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i]))) {
+                valid = false;
+            }
+            if (!valid) {
+                if (!errorFound) {
+                    errorFound = true;
+                    message.append("Input inLeftVector: ");
+                    appendVariableToMessage(message, arrayInLeftVector[i]);
+                    message.append("\n");
+                    message.append("Input inRightVector: ");
+                    appendVariableToMessage(message, arrayInRightVector[i]);
+                    message.append("\n");
+                    message.append("Expected output out: ");
+                    appendVariableToMessage(message, args.out);
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    appendVariableToMessage(message, arrayOut[i]);
+                    message.append("\n");
+                    message.append("Actual   output out (in double): ");
+                    appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i]));
+                    if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i]))) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Errors at");
+                }
+                message.append(" [");
+                message.append(Integer.toString(i));
+                message.append("]");
+            }
+        }
+        assertFalse("Incorrect output for checkNativeDistanceHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    public class ArgumentsHalfNHalfNHalf {
+        public short[] inLeftVector;
+        public double[] inLeftVectorDouble;
+        public short[] inRightVector;
+        public double[] inRightVectorDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeDistanceHalf2Half2Half() {
+        Allocation inLeftVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x30493el, false);
+        Allocation inRightVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x763516efl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInRightVector(inRightVector);
+            script.forEach_testNativeDistanceHalf2Half2Half(inLeftVector, out);
+            verifyResultsNativeDistanceHalf2Half2Half(inLeftVector, inRightVector, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceHalf2Half2Half: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRightVector(inRightVector);
+            scriptRelaxed.forEach_testNativeDistanceHalf2Half2Half(inLeftVector, out);
+            verifyResultsNativeDistanceHalf2Half2Half(inLeftVector, inRightVector, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceHalf2Half2Half: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDistanceHalf2Half2Half(Allocation inLeftVector, Allocation inRightVector, Allocation out, boolean relaxed) {
+        short[] arrayInLeftVector = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInLeftVector, (short) 42);
+        inLeftVector.copyTo(arrayInLeftVector);
+        short[] arrayInRightVector = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInRightVector, (short) 42);
+        inRightVector.copyTo(arrayInRightVector);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsHalfNHalfNHalf args = new ArgumentsHalfNHalfNHalf();
+            // Create the appropriate sized arrays in args
+            args.inLeftVector = new short[2];
+            args.inLeftVectorDouble = new double[2];
+            args.inRightVector = new short[2];
+            args.inRightVectorDouble = new double[2];
+            // Fill args with the input values
+            for (int j = 0; j < 2 ; j++) {
+                args.inLeftVector[j] = arrayInLeftVector[i * 2 + j];
+                args.inLeftVectorDouble[j] = Float16Utils.convertFloat16ToDouble(args.inLeftVector[j]);
+            }
+            for (int j = 0; j < 2 ; j++) {
+                args.inRightVector[j] = arrayInRightVector[i * 2 + j];
+                args.inRightVectorDouble[j] = Float16Utils.convertFloat16ToDouble(args.inRightVector[j]);
+            }
+            Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+            CoreMathVerifier.computeNativeDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i]))) {
+                valid = false;
+            }
+            if (!valid) {
+                if (!errorFound) {
+                    errorFound = true;
+                    for (int j = 0; j < 2 ; j++) {
+                        message.append("Input inLeftVector: ");
+                        appendVariableToMessage(message, arrayInLeftVector[i * 2 + j]);
+                        message.append("\n");
+                    }
+                    for (int j = 0; j < 2 ; j++) {
+                        message.append("Input inRightVector: ");
+                        appendVariableToMessage(message, arrayInRightVector[i * 2 + j]);
+                        message.append("\n");
+                    }
+                    message.append("Expected output out: ");
+                    appendVariableToMessage(message, args.out);
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    appendVariableToMessage(message, arrayOut[i]);
+                    message.append("\n");
+                    message.append("Actual   output out (in double): ");
+                    appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i]));
+                    if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i]))) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Errors at");
+                }
+                message.append(" [");
+                message.append(Integer.toString(i));
+                message.append("]");
+            }
+        }
+        assertFalse("Incorrect output for checkNativeDistanceHalf2Half2Half" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeDistanceHalf3Half3Half() {
+        Allocation inLeftVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xca7541fal, false);
+        Allocation inRightVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x6fcade83l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInRightVector(inRightVector);
+            script.forEach_testNativeDistanceHalf3Half3Half(inLeftVector, out);
+            verifyResultsNativeDistanceHalf3Half3Half(inLeftVector, inRightVector, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceHalf3Half3Half: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRightVector(inRightVector);
+            scriptRelaxed.forEach_testNativeDistanceHalf3Half3Half(inLeftVector, out);
+            verifyResultsNativeDistanceHalf3Half3Half(inLeftVector, inRightVector, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceHalf3Half3Half: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDistanceHalf3Half3Half(Allocation inLeftVector, Allocation inRightVector, Allocation out, boolean relaxed) {
+        short[] arrayInLeftVector = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInLeftVector, (short) 42);
+        inLeftVector.copyTo(arrayInLeftVector);
+        short[] arrayInRightVector = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInRightVector, (short) 42);
+        inRightVector.copyTo(arrayInRightVector);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsHalfNHalfNHalf args = new ArgumentsHalfNHalfNHalf();
+            // Create the appropriate sized arrays in args
+            args.inLeftVector = new short[3];
+            args.inLeftVectorDouble = new double[3];
+            args.inRightVector = new short[3];
+            args.inRightVectorDouble = new double[3];
+            // Fill args with the input values
+            for (int j = 0; j < 3 ; j++) {
+                args.inLeftVector[j] = arrayInLeftVector[i * 4 + j];
+                args.inLeftVectorDouble[j] = Float16Utils.convertFloat16ToDouble(args.inLeftVector[j]);
+            }
+            for (int j = 0; j < 3 ; j++) {
+                args.inRightVector[j] = arrayInRightVector[i * 4 + j];
+                args.inRightVectorDouble[j] = Float16Utils.convertFloat16ToDouble(args.inRightVector[j]);
+            }
+            Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+            CoreMathVerifier.computeNativeDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i]))) {
+                valid = false;
+            }
+            if (!valid) {
+                if (!errorFound) {
+                    errorFound = true;
+                    for (int j = 0; j < 3 ; j++) {
+                        message.append("Input inLeftVector: ");
+                        appendVariableToMessage(message, arrayInLeftVector[i * 4 + j]);
+                        message.append("\n");
+                    }
+                    for (int j = 0; j < 3 ; j++) {
+                        message.append("Input inRightVector: ");
+                        appendVariableToMessage(message, arrayInRightVector[i * 4 + j]);
+                        message.append("\n");
+                    }
+                    message.append("Expected output out: ");
+                    appendVariableToMessage(message, args.out);
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    appendVariableToMessage(message, arrayOut[i]);
+                    message.append("\n");
+                    message.append("Actual   output out (in double): ");
+                    appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i]));
+                    if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i]))) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Errors at");
+                }
+                message.append(" [");
+                message.append(Integer.toString(i));
+                message.append("]");
+            }
+        }
+        assertFalse("Incorrect output for checkNativeDistanceHalf3Half3Half" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeDistanceHalf4Half4Half() {
+        Allocation inLeftVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x94ba3ab6l, false);
+        Allocation inRightVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x6960a617l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInRightVector(inRightVector);
+            script.forEach_testNativeDistanceHalf4Half4Half(inLeftVector, out);
+            verifyResultsNativeDistanceHalf4Half4Half(inLeftVector, inRightVector, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceHalf4Half4Half: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRightVector(inRightVector);
+            scriptRelaxed.forEach_testNativeDistanceHalf4Half4Half(inLeftVector, out);
+            verifyResultsNativeDistanceHalf4Half4Half(inLeftVector, inRightVector, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDistanceHalf4Half4Half: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDistanceHalf4Half4Half(Allocation inLeftVector, Allocation inRightVector, Allocation out, boolean relaxed) {
+        short[] arrayInLeftVector = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInLeftVector, (short) 42);
+        inLeftVector.copyTo(arrayInLeftVector);
+        short[] arrayInRightVector = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInRightVector, (short) 42);
+        inRightVector.copyTo(arrayInRightVector);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            ArgumentsHalfNHalfNHalf args = new ArgumentsHalfNHalfNHalf();
+            // Create the appropriate sized arrays in args
+            args.inLeftVector = new short[4];
+            args.inLeftVectorDouble = new double[4];
+            args.inRightVector = new short[4];
+            args.inRightVectorDouble = new double[4];
+            // Fill args with the input values
+            for (int j = 0; j < 4 ; j++) {
+                args.inLeftVector[j] = arrayInLeftVector[i * 4 + j];
+                args.inLeftVectorDouble[j] = Float16Utils.convertFloat16ToDouble(args.inLeftVector[j]);
+            }
+            for (int j = 0; j < 4 ; j++) {
+                args.inRightVector[j] = arrayInRightVector[i * 4 + j];
+                args.inRightVectorDouble[j] = Float16Utils.convertFloat16ToDouble(args.inRightVector[j]);
+            }
+            Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+            CoreMathVerifier.computeNativeDistance(args, target);
+
+            // Compare the expected outputs to the actual values returned by RS.
+            boolean valid = true;
+            if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i]))) {
+                valid = false;
+            }
+            if (!valid) {
+                if (!errorFound) {
+                    errorFound = true;
+                    for (int j = 0; j < 4 ; j++) {
+                        message.append("Input inLeftVector: ");
+                        appendVariableToMessage(message, arrayInLeftVector[i * 4 + j]);
+                        message.append("\n");
+                    }
+                    for (int j = 0; j < 4 ; j++) {
+                        message.append("Input inRightVector: ");
+                        appendVariableToMessage(message, arrayInRightVector[i * 4 + j]);
+                        message.append("\n");
+                    }
+                    message.append("Expected output out: ");
+                    appendVariableToMessage(message, args.out);
+                    message.append("\n");
+                    message.append("Actual   output out: ");
+                    appendVariableToMessage(message, arrayOut[i]);
+                    message.append("\n");
+                    message.append("Actual   output out (in double): ");
+                    appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i]));
+                    if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i]))) {
+                        message.append(" FAIL");
+                    }
+                    message.append("\n");
+                    message.append("Errors at");
+                }
+                message.append(" [");
+                message.append(Integer.toString(i));
+                message.append("]");
+            }
+        }
+        assertFalse("Incorrect output for checkNativeDistanceHalf4Half4Half" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeDistance() {
         checkNativeDistanceFloatFloatFloat();
         checkNativeDistanceFloat2Float2Float();
         checkNativeDistanceFloat3Float3Float();
         checkNativeDistanceFloat4Float4Float();
+        checkNativeDistanceHalfHalfHalf();
+        checkNativeDistanceHalf2Half2Half();
+        checkNativeDistanceHalf3Half3Half();
+        checkNativeDistanceHalf4Half4Half();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDistance.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDistance.rs
index 3077625..de717e6 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDistance.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDistance.rs
@@ -40,3 +40,23 @@
     float4 inRightVector = rsGetElementAt_float4(gAllocInRightVector, x);
     return native_distance(inLeftVector, inRightVector);
 }
+
+half __attribute__((kernel)) testNativeDistanceHalfHalfHalf(half inLeftVector, unsigned int x) {
+    half inRightVector = rsGetElementAt_half(gAllocInRightVector, x);
+    return native_distance(inLeftVector, inRightVector);
+}
+
+half __attribute__((kernel)) testNativeDistanceHalf2Half2Half(half2 inLeftVector, unsigned int x) {
+    half2 inRightVector = rsGetElementAt_half2(gAllocInRightVector, x);
+    return native_distance(inLeftVector, inRightVector);
+}
+
+half __attribute__((kernel)) testNativeDistanceHalf3Half3Half(half3 inLeftVector, unsigned int x) {
+    half3 inRightVector = rsGetElementAt_half3(gAllocInRightVector, x);
+    return native_distance(inLeftVector, inRightVector);
+}
+
+half __attribute__((kernel)) testNativeDistanceHalf4Half4Half(half4 inLeftVector, unsigned int x) {
+    half4 inRightVector = rsGetElementAt_half4(gAllocInRightVector, x);
+    return native_distance(inLeftVector, inRightVector);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDivide.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDivide.java
index 4c864e6..603e92f 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDivide.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDivide.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inLeftVector;
+        public double inLeftVectorDouble;
+        public short inRightVector;
+        public double inRightVectorDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeDivideHalfHalfHalf() {
+        Allocation inLeftVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xaeea6bb8l, false);
+        Allocation inRightVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xcf78e16dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInRightVector(inRightVector);
+            script.forEach_testNativeDivideHalfHalfHalf(inLeftVector, out);
+            verifyResultsNativeDivideHalfHalfHalf(inLeftVector, inRightVector, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRightVector(inRightVector);
+            scriptRelaxed.forEach_testNativeDivideHalfHalfHalf(inLeftVector, out);
+            verifyResultsNativeDivideHalfHalfHalf(inLeftVector, inRightVector, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDivideHalfHalfHalf(Allocation inLeftVector, Allocation inRightVector, Allocation out, boolean relaxed) {
+        short[] arrayInLeftVector = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInLeftVector, (short) 42);
+        inLeftVector.copyTo(arrayInLeftVector);
+        short[] arrayInRightVector = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInRightVector, (short) 42);
+        inRightVector.copyTo(arrayInRightVector);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inLeftVector = arrayInLeftVector[i];
+                args.inLeftVectorDouble = Float16Utils.convertFloat16ToDouble(args.inLeftVector);
+                args.inRightVector = arrayInRightVector[i];
+                args.inRightVectorDouble = Float16Utils.convertFloat16ToDouble(args.inRightVector);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeDivide(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inLeftVector: ");
+                        appendVariableToMessage(message, args.inLeftVector);
+                        message.append("\n");
+                        message.append("Input inRightVector: ");
+                        appendVariableToMessage(message, args.inRightVector);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeDivideHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeDivideHalf2Half2Half2() {
+        Allocation inLeftVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x15982fb6l, false);
+        Allocation inRightVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xea8cd17l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInRightVector(inRightVector);
+            script.forEach_testNativeDivideHalf2Half2Half2(inLeftVector, out);
+            verifyResultsNativeDivideHalf2Half2Half2(inLeftVector, inRightVector, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRightVector(inRightVector);
+            scriptRelaxed.forEach_testNativeDivideHalf2Half2Half2(inLeftVector, out);
+            verifyResultsNativeDivideHalf2Half2Half2(inLeftVector, inRightVector, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDivideHalf2Half2Half2(Allocation inLeftVector, Allocation inRightVector, Allocation out, boolean relaxed) {
+        short[] arrayInLeftVector = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInLeftVector, (short) 42);
+        inLeftVector.copyTo(arrayInLeftVector);
+        short[] arrayInRightVector = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInRightVector, (short) 42);
+        inRightVector.copyTo(arrayInRightVector);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inLeftVector = arrayInLeftVector[i * 2 + j];
+                args.inLeftVectorDouble = Float16Utils.convertFloat16ToDouble(args.inLeftVector);
+                args.inRightVector = arrayInRightVector[i * 2 + j];
+                args.inRightVectorDouble = Float16Utils.convertFloat16ToDouble(args.inRightVector);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeDivide(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inLeftVector: ");
+                        appendVariableToMessage(message, args.inLeftVector);
+                        message.append("\n");
+                        message.append("Input inRightVector: ");
+                        appendVariableToMessage(message, args.inRightVector);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeDivideHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeDivideHalf3Half3Half3() {
+        Allocation inLeftVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xc1c6525bl, false);
+        Allocation inRightVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xfa689ecel, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInRightVector(inRightVector);
+            script.forEach_testNativeDivideHalf3Half3Half3(inLeftVector, out);
+            verifyResultsNativeDivideHalf3Half3Half3(inLeftVector, inRightVector, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRightVector(inRightVector);
+            scriptRelaxed.forEach_testNativeDivideHalf3Half3Half3(inLeftVector, out);
+            verifyResultsNativeDivideHalf3Half3Half3(inLeftVector, inRightVector, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDivideHalf3Half3Half3(Allocation inLeftVector, Allocation inRightVector, Allocation out, boolean relaxed) {
+        short[] arrayInLeftVector = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInLeftVector, (short) 42);
+        inLeftVector.copyTo(arrayInLeftVector);
+        short[] arrayInRightVector = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInRightVector, (short) 42);
+        inRightVector.copyTo(arrayInRightVector);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inLeftVector = arrayInLeftVector[i * 4 + j];
+                args.inLeftVectorDouble = Float16Utils.convertFloat16ToDouble(args.inLeftVector);
+                args.inRightVector = arrayInRightVector[i * 4 + j];
+                args.inRightVectorDouble = Float16Utils.convertFloat16ToDouble(args.inRightVector);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeDivide(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inLeftVector: ");
+                        appendVariableToMessage(message, args.inLeftVector);
+                        message.append("\n");
+                        message.append("Input inRightVector: ");
+                        appendVariableToMessage(message, args.inRightVector);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeDivideHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeDivideHalf4Half4Half4() {
+        Allocation inLeftVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x6df47500l, false);
+        Allocation inRightVector = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xe6287085l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInRightVector(inRightVector);
+            script.forEach_testNativeDivideHalf4Half4Half4(inLeftVector, out);
+            verifyResultsNativeDivideHalf4Half4Half4(inLeftVector, inRightVector, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInRightVector(inRightVector);
+            scriptRelaxed.forEach_testNativeDivideHalf4Half4Half4(inLeftVector, out);
+            verifyResultsNativeDivideHalf4Half4Half4(inLeftVector, inRightVector, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeDivideHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeDivideHalf4Half4Half4(Allocation inLeftVector, Allocation inRightVector, Allocation out, boolean relaxed) {
+        short[] arrayInLeftVector = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInLeftVector, (short) 42);
+        inLeftVector.copyTo(arrayInLeftVector);
+        short[] arrayInRightVector = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInRightVector, (short) 42);
+        inRightVector.copyTo(arrayInRightVector);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inLeftVector = arrayInLeftVector[i * 4 + j];
+                args.inLeftVectorDouble = Float16Utils.convertFloat16ToDouble(args.inLeftVector);
+                args.inRightVector = arrayInRightVector[i * 4 + j];
+                args.inRightVectorDouble = Float16Utils.convertFloat16ToDouble(args.inRightVector);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeDivide(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inLeftVector: ");
+                        appendVariableToMessage(message, args.inLeftVector);
+                        message.append("\n");
+                        message.append("Input inRightVector: ");
+                        appendVariableToMessage(message, args.inRightVector);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeDivideHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeDivide() {
         checkNativeDivideFloatFloatFloat();
         checkNativeDivideFloat2Float2Float2();
         checkNativeDivideFloat3Float3Float3();
         checkNativeDivideFloat4Float4Float4();
+        checkNativeDivideHalfHalfHalf();
+        checkNativeDivideHalf2Half2Half2();
+        checkNativeDivideHalf3Half3Half3();
+        checkNativeDivideHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDivide.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDivide.rs
index 58ec9ab..7bb31c0 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDivide.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeDivide.rs
@@ -40,3 +40,23 @@
     float4 inRightVector = rsGetElementAt_float4(gAllocInRightVector, x);
     return native_divide(inLeftVector, inRightVector);
 }
+
+half __attribute__((kernel)) testNativeDivideHalfHalfHalf(half inLeftVector, unsigned int x) {
+    half inRightVector = rsGetElementAt_half(gAllocInRightVector, x);
+    return native_divide(inLeftVector, inRightVector);
+}
+
+half2 __attribute__((kernel)) testNativeDivideHalf2Half2Half2(half2 inLeftVector, unsigned int x) {
+    half2 inRightVector = rsGetElementAt_half2(gAllocInRightVector, x);
+    return native_divide(inLeftVector, inRightVector);
+}
+
+half3 __attribute__((kernel)) testNativeDivideHalf3Half3Half3(half3 inLeftVector, unsigned int x) {
+    half3 inRightVector = rsGetElementAt_half3(gAllocInRightVector, x);
+    return native_divide(inLeftVector, inRightVector);
+}
+
+half4 __attribute__((kernel)) testNativeDivideHalf4Half4Half4(half4 inLeftVector, unsigned int x) {
+    half4 inRightVector = rsGetElementAt_half4(gAllocInRightVector, x);
+    return native_divide(inLeftVector, inRightVector);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp.java
index edef95d..baef7bd 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeExpHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x529e185dl, -86, 86);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeExpHalfHalf(inV, out);
+            verifyResultsNativeExpHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpHalfHalf(inV, out);
+            verifyResultsNativeExpHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExpHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeExpHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x5f1505d7l, -86, 86);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeExpHalf2Half2(inV, out);
+            verifyResultsNativeExpHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpHalf2Half2(inV, out);
+            verifyResultsNativeExpHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExpHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeExpHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xbe1ccacbl, -86, 86);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeExpHalf3Half3(inV, out);
+            verifyResultsNativeExpHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpHalf3Half3(inV, out);
+            verifyResultsNativeExpHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExpHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeExpHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x1d248fbfl, -86, 86);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeExpHalf4Half4(inV, out);
+            verifyResultsNativeExpHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpHalf4Half4(inV, out);
+            verifyResultsNativeExpHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeExp(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExpHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeExp() {
         checkNativeExpFloatFloat();
         checkNativeExpFloat2Float2();
         checkNativeExpFloat3Float3();
         checkNativeExpFloat4Float4();
+        checkNativeExpHalfHalf();
+        checkNativeExpHalf2Half2();
+        checkNativeExpHalf3Half3();
+        checkNativeExpHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp.rs
index 96c7a0e..2128469 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeExpFloat4Float4(float4 inV) {
     return native_exp(inV);
 }
+
+half __attribute__((kernel)) testNativeExpHalfHalf(half inV) {
+    return native_exp(inV);
+}
+
+half2 __attribute__((kernel)) testNativeExpHalf2Half2(half2 inV) {
+    return native_exp(inV);
+}
+
+half3 __attribute__((kernel)) testNativeExpHalf3Half3(half3 inV) {
+    return native_exp(inV);
+}
+
+half4 __attribute__((kernel)) testNativeExpHalf4Half4(half4 inV) {
+    return native_exp(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp10.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp10.java
index 84dbdae..6ff9a35 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp10.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp10.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeExp10HalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xa51532del, -37, 37);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeExp10HalfHalf(inV, out);
+            verifyResultsNativeExp10HalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10HalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp10HalfHalf(inV, out);
+            verifyResultsNativeExp10HalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10HalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp10HalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExp10HalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeExp10Half2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xfd537390l, -37, 37);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeExp10Half2Half2(inV, out);
+            verifyResultsNativeExp10Half2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp10Half2Half2(inV, out);
+            verifyResultsNativeExp10Half2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp10Half2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExp10Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeExp10Half3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x5c5b3884l, -37, 37);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeExp10Half3Half3(inV, out);
+            verifyResultsNativeExp10Half3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp10Half3Half3(inV, out);
+            verifyResultsNativeExp10Half3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp10Half3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExp10Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeExp10Half4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xbb62fd78l, -37, 37);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeExp10Half4Half4(inV, out);
+            verifyResultsNativeExp10Half4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp10Half4Half4(inV, out);
+            verifyResultsNativeExp10Half4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp10Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp10Half4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeExp10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExp10Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeExp10() {
         checkNativeExp10FloatFloat();
         checkNativeExp10Float2Float2();
         checkNativeExp10Float3Float3();
         checkNativeExp10Float4Float4();
+        checkNativeExp10HalfHalf();
+        checkNativeExp10Half2Half2();
+        checkNativeExp10Half3Half3();
+        checkNativeExp10Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp10.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp10.rs
index 853406b..93130220 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp10.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp10.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeExp10Float4Float4(float4 inV) {
     return native_exp10(inV);
 }
+
+half __attribute__((kernel)) testNativeExp10HalfHalf(half inV) {
+    return native_exp10(inV);
+}
+
+half2 __attribute__((kernel)) testNativeExp10Half2Half2(half2 inV) {
+    return native_exp10(inV);
+}
+
+half3 __attribute__((kernel)) testNativeExp10Half3Half3(half3 inV) {
+    return native_exp10(inV);
+}
+
+half4 __attribute__((kernel)) testNativeExp10Half4Half4(half4 inV) {
+    return native_exp10(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp2.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp2.java
index 094fa1d..4fc5cef 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp2.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp2.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeExp2HalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x75b1f4d7l, -125, 125);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeExp2HalfHalf(inV, out);
+            verifyResultsNativeExp2HalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2HalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp2HalfHalf(inV, out);
+            verifyResultsNativeExp2HalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2HalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp2HalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExp2HalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeExp2Half2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xb9887301l, -125, 125);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeExp2Half2Half2(inV, out);
+            verifyResultsNativeExp2Half2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp2Half2Half2(inV, out);
+            verifyResultsNativeExp2Half2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp2Half2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExp2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeExp2Half3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x189037f5l, -125, 125);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeExp2Half3Half3(inV, out);
+            verifyResultsNativeExp2Half3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp2Half3Half3(inV, out);
+            verifyResultsNativeExp2Half3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp2Half3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExp2Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeExp2Half4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x7797fce9l, -125, 125);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeExp2Half4Half4(inV, out);
+            verifyResultsNativeExp2Half4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExp2Half4Half4(inV, out);
+            verifyResultsNativeExp2Half4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExp2Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExp2Half4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeExp2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExp2Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeExp2() {
         checkNativeExp2FloatFloat();
         checkNativeExp2Float2Float2();
         checkNativeExp2Float3Float3();
         checkNativeExp2Float4Float4();
+        checkNativeExp2HalfHalf();
+        checkNativeExp2Half2Half2();
+        checkNativeExp2Half3Half3();
+        checkNativeExp2Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp2.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp2.rs
index 2fb6013..8aa5c0e 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp2.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExp2.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeExp2Float4Float4(float4 inV) {
     return native_exp2(inV);
 }
+
+half __attribute__((kernel)) testNativeExp2HalfHalf(half inV) {
+    return native_exp2(inV);
+}
+
+half2 __attribute__((kernel)) testNativeExp2Half2Half2(half2 inV) {
+    return native_exp2(inV);
+}
+
+half3 __attribute__((kernel)) testNativeExp2Half3Half3(half3 inV) {
+    return native_exp2(inV);
+}
+
+half4 __attribute__((kernel)) testNativeExp2Half4Half4(half4 inV) {
+    return native_exp2(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExpm1.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExpm1.java
index edae2df..3b4412b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExpm1.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExpm1.java
@@ -318,10 +318,293 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public short out;
+        public double outDouble;
+    }
+
+    private void checkNativeExpm1HalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x1f7c28dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeExpm1HalfHalf(inV, out);
+            verifyResultsNativeExpm1HalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1HalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpm1HalfHalf(inV, out);
+            verifyResultsNativeExpm1HalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1HalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpm1HalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Extract the outputs.
+                args.out = arrayOut[i * 1 + j];
+                args.outDouble = Float16Utils.convertFloat16ToDouble(args.out);
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                String errorMessage = CoreMathVerifier.verifyNativeExpm1(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("\n");
+                        message.append("Output out (in double): ");
+                        appendVariableToMessage(message, args.outDouble);
+                        message.append("\n");
+                        message.append(errorMessage);
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExpm1HalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeExpm1Half2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xddb33a87l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeExpm1Half2Half2(inV, out);
+            verifyResultsNativeExpm1Half2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpm1Half2Half2(inV, out);
+            verifyResultsNativeExpm1Half2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpm1Half2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Extract the outputs.
+                args.out = arrayOut[i * 2 + j];
+                args.outDouble = Float16Utils.convertFloat16ToDouble(args.out);
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                String errorMessage = CoreMathVerifier.verifyNativeExpm1(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("\n");
+                        message.append("Output out (in double): ");
+                        appendVariableToMessage(message, args.outDouble);
+                        message.append("\n");
+                        message.append(errorMessage);
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExpm1Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeExpm1Half3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x3cbaff7bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeExpm1Half3Half3(inV, out);
+            verifyResultsNativeExpm1Half3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpm1Half3Half3(inV, out);
+            verifyResultsNativeExpm1Half3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpm1Half3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Extract the outputs.
+                args.out = arrayOut[i * 4 + j];
+                args.outDouble = Float16Utils.convertFloat16ToDouble(args.out);
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                String errorMessage = CoreMathVerifier.verifyNativeExpm1(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("\n");
+                        message.append("Output out (in double): ");
+                        appendVariableToMessage(message, args.outDouble);
+                        message.append("\n");
+                        message.append(errorMessage);
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExpm1Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeExpm1Half4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x9bc2c46fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeExpm1Half4Half4(inV, out);
+            verifyResultsNativeExpm1Half4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeExpm1Half4Half4(inV, out);
+            verifyResultsNativeExpm1Half4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeExpm1Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeExpm1Half4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Extract the outputs.
+                args.out = arrayOut[i * 4 + j];
+                args.outDouble = Float16Utils.convertFloat16ToDouble(args.out);
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                String errorMessage = CoreMathVerifier.verifyNativeExpm1(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("\n");
+                        message.append("Output out (in double): ");
+                        appendVariableToMessage(message, args.outDouble);
+                        message.append("\n");
+                        message.append(errorMessage);
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeExpm1Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeExpm1() {
         checkNativeExpm1FloatFloat();
         checkNativeExpm1Float2Float2();
         checkNativeExpm1Float3Float3();
         checkNativeExpm1Float4Float4();
+        checkNativeExpm1HalfHalf();
+        checkNativeExpm1Half2Half2();
+        checkNativeExpm1Half3Half3();
+        checkNativeExpm1Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExpm1.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExpm1.rs
index 2cfee07..a965138 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExpm1.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeExpm1.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeExpm1Float4Float4(float4 inV) {
     return native_expm1(inV);
 }
+
+half __attribute__((kernel)) testNativeExpm1HalfHalf(half inV) {
+    return native_expm1(inV);
+}
+
+half2 __attribute__((kernel)) testNativeExpm1Half2Half2(half2 inV) {
+    return native_expm1(inV);
+}
+
+half3 __attribute__((kernel)) testNativeExpm1Half3Half3(half3 inV) {
+    return native_expm1(inV);
+}
+
+half4 __attribute__((kernel)) testNativeExpm1Half4Half4(half4 inV) {
+    return native_expm1(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeHypot.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeHypot.java
index a6f1c7f..4aee2bc 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeHypot.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeHypot.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inA;
+        public double inADouble;
+        public short inB;
+        public double inBDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeHypotHalfHalfHalf() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x93522f56l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x93522f57l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testNativeHypotHalfHalfHalf(inA, out);
+            verifyResultsNativeHypotHalfHalfHalf(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testNativeHypotHalfHalfHalf(inA, out);
+            verifyResultsNativeHypotHalfHalfHalf(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeHypotHalfHalfHalf(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeHypotHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeHypotHalf2Half2Half2() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xf4dca3f6l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xf4dca3f7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testNativeHypotHalf2Half2Half2(inA, out);
+            verifyResultsNativeHypotHalf2Half2Half2(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testNativeHypotHalf2Half2Half2(inA, out);
+            verifyResultsNativeHypotHalf2Half2Half2(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeHypotHalf2Half2Half2(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 2 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 2 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeHypotHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeHypotHalf3Half3Half3() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x537bb4c5l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x537bb4c6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testNativeHypotHalf3Half3Half3(inA, out);
+            verifyResultsNativeHypotHalf3Half3Half3(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testNativeHypotHalf3Half3Half3(inA, out);
+            verifyResultsNativeHypotHalf3Half3Half3(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeHypotHalf3Half3Half3(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeHypotHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeHypotHalf4Half4Half4() {
+        Allocation inA = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xb21ac594l, false);
+        Allocation inB = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xb21ac595l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInB(inB);
+            script.forEach_testNativeHypotHalf4Half4Half4(inA, out);
+            verifyResultsNativeHypotHalf4Half4Half4(inA, inB, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInB(inB);
+            scriptRelaxed.forEach_testNativeHypotHalf4Half4Half4(inA, out);
+            verifyResultsNativeHypotHalf4Half4Half4(inA, inB, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeHypotHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeHypotHalf4Half4Half4(Allocation inA, Allocation inB, Allocation out, boolean relaxed) {
+        short[] arrayInA = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInA, (short) 42);
+        inA.copyTo(arrayInA);
+        short[] arrayInB = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInB, (short) 42);
+        inB.copyTo(arrayInB);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inA = arrayInA[i * 4 + j];
+                args.inADouble = Float16Utils.convertFloat16ToDouble(args.inA);
+                args.inB = arrayInB[i * 4 + j];
+                args.inBDouble = Float16Utils.convertFloat16ToDouble(args.inB);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeHypot(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inA: ");
+                        appendVariableToMessage(message, args.inA);
+                        message.append("\n");
+                        message.append("Input inB: ");
+                        appendVariableToMessage(message, args.inB);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeHypotHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeHypot() {
         checkNativeHypotFloatFloatFloat();
         checkNativeHypotFloat2Float2Float2();
         checkNativeHypotFloat3Float3Float3();
         checkNativeHypotFloat4Float4Float4();
+        checkNativeHypotHalfHalfHalf();
+        checkNativeHypotHalf2Half2Half2();
+        checkNativeHypotHalf3Half3Half3();
+        checkNativeHypotHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeHypot.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeHypot.rs
index 9f3d9cd..8768883 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeHypot.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeHypot.rs
@@ -40,3 +40,23 @@
     float4 inB = rsGetElementAt_float4(gAllocInB, x);
     return native_hypot(inA, inB);
 }
+
+half __attribute__((kernel)) testNativeHypotHalfHalfHalf(half inA, unsigned int x) {
+    half inB = rsGetElementAt_half(gAllocInB, x);
+    return native_hypot(inA, inB);
+}
+
+half2 __attribute__((kernel)) testNativeHypotHalf2Half2Half2(half2 inA, unsigned int x) {
+    half2 inB = rsGetElementAt_half2(gAllocInB, x);
+    return native_hypot(inA, inB);
+}
+
+half3 __attribute__((kernel)) testNativeHypotHalf3Half3Half3(half3 inA, unsigned int x) {
+    half3 inB = rsGetElementAt_half3(gAllocInB, x);
+    return native_hypot(inA, inB);
+}
+
+half4 __attribute__((kernel)) testNativeHypotHalf4Half4Half4(half4 inA, unsigned int x) {
+    half4 inB = rsGetElementAt_half4(gAllocInB, x);
+    return native_hypot(inA, inB);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog.java
index c9dd50e..dd52d7b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeLogHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x7dcf0276l, 10e-5, 65504);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeLogHalfHalf(inV, out);
+            verifyResultsNativeLogHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLogHalfHalf(inV, out);
+            verifyResultsNativeLogHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLogHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLogHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeLogHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x535fd468l, 10e-5, 65504);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeLogHalf2Half2(inV, out);
+            verifyResultsNativeLogHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLogHalf2Half2(inV, out);
+            verifyResultsNativeLogHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLogHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLogHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeLogHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb267995cl, 10e-5, 65504);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeLogHalf3Half3(inV, out);
+            verifyResultsNativeLogHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLogHalf3Half3(inV, out);
+            verifyResultsNativeLogHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLogHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLogHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeLogHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x116f5e50l, 10e-5, 65504);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeLogHalf4Half4(inV, out);
+            verifyResultsNativeLogHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLogHalf4Half4(inV, out);
+            verifyResultsNativeLogHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLogHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLogHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLogHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeLog() {
         checkNativeLogFloatFloat();
         checkNativeLogFloat2Float2();
         checkNativeLogFloat3Float3();
         checkNativeLogFloat4Float4();
+        checkNativeLogHalfHalf();
+        checkNativeLogHalf2Half2();
+        checkNativeLogHalf3Half3();
+        checkNativeLogHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog.rs
index bd7dbb9..179d673 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeLogFloat4Float4(float4 inV) {
     return native_log(inV);
 }
+
+half __attribute__((kernel)) testNativeLogHalfHalf(half inV) {
+    return native_log(inV);
+}
+
+half2 __attribute__((kernel)) testNativeLogHalf2Half2(half2 inV) {
+    return native_log(inV);
+}
+
+half3 __attribute__((kernel)) testNativeLogHalf3Half3(half3 inV) {
+    return native_log(inV);
+}
+
+half4 __attribute__((kernel)) testNativeLogHalf4Half4(half4 inV) {
+    return native_log(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog10.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog10.java
index a5cf87f5..0854f26 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog10.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog10.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeLog10HalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x9960016fl, 10e-5, 65504);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeLog10HalfHalf(inV, out);
+            verifyResultsNativeLog10HalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10HalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog10HalfHalf(inV, out);
+            verifyResultsNativeLog10HalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10HalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog10HalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLog10HalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeLog10Half2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x6da168d9l, 10e-5, 65504);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeLog10Half2Half2(inV, out);
+            verifyResultsNativeLog10Half2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog10Half2Half2(inV, out);
+            verifyResultsNativeLog10Half2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog10Half2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLog10Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeLog10Half3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xcca92dcdl, 10e-5, 65504);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeLog10Half3Half3(inV, out);
+            verifyResultsNativeLog10Half3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog10Half3Half3(inV, out);
+            verifyResultsNativeLog10Half3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog10Half3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLog10Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeLog10Half4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x2bb0f2c1l, 10e-5, 65504);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeLog10Half4Half4(inV, out);
+            verifyResultsNativeLog10Half4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog10Half4Half4(inV, out);
+            verifyResultsNativeLog10Half4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog10Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog10Half4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog10(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLog10Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeLog10() {
         checkNativeLog10FloatFloat();
         checkNativeLog10Float2Float2();
         checkNativeLog10Float3Float3();
         checkNativeLog10Float4Float4();
+        checkNativeLog10HalfHalf();
+        checkNativeLog10Half2Half2();
+        checkNativeLog10Half3Half3();
+        checkNativeLog10Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog10.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog10.rs
index 462e31a..434b275 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog10.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog10.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeLog10Float4Float4(float4 inV) {
     return native_log10(inV);
 }
+
+half __attribute__((kernel)) testNativeLog10HalfHalf(half inV) {
+    return native_log10(inV);
+}
+
+half2 __attribute__((kernel)) testNativeLog10Half2Half2(half2 inV) {
+    return native_log10(inV);
+}
+
+half3 __attribute__((kernel)) testNativeLog10Half3Half3(half3 inV) {
+    return native_log10(inV);
+}
+
+half4 __attribute__((kernel)) testNativeLog10Half4Half4(half4 inV) {
+    return native_log10(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog1p.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog1p.java
index 5e1d2c5..4ef9bd1 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog1p.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog1p.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeLog1pHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe4adee2fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeLog1pHalfHalf(inV, out);
+            verifyResultsNativeLog1pHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog1pHalfHalf(inV, out);
+            verifyResultsNativeLog1pHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog1pHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLog1pHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeLog1pHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x53745f99l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeLog1pHalf2Half2(inV, out);
+            verifyResultsNativeLog1pHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog1pHalf2Half2(inV, out);
+            verifyResultsNativeLog1pHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog1pHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLog1pHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeLog1pHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb27c248dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeLog1pHalf3Half3(inV, out);
+            verifyResultsNativeLog1pHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog1pHalf3Half3(inV, out);
+            verifyResultsNativeLog1pHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog1pHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLog1pHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeLog1pHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x1183e981l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeLog1pHalf4Half4(inV, out);
+            verifyResultsNativeLog1pHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog1pHalf4Half4(inV, out);
+            verifyResultsNativeLog1pHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog1pHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog1pHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog1p(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLog1pHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeLog1p() {
         checkNativeLog1pFloatFloat();
         checkNativeLog1pFloat2Float2();
         checkNativeLog1pFloat3Float3();
         checkNativeLog1pFloat4Float4();
+        checkNativeLog1pHalfHalf();
+        checkNativeLog1pHalf2Half2();
+        checkNativeLog1pHalf3Half3();
+        checkNativeLog1pHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog1p.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog1p.rs
index 463c8e7..3d4fd21 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog1p.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog1p.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeLog1pFloat4Float4(float4 inV) {
     return native_log1p(inV);
 }
+
+half __attribute__((kernel)) testNativeLog1pHalfHalf(half inV) {
+    return native_log1p(inV);
+}
+
+half2 __attribute__((kernel)) testNativeLog1pHalf2Half2(half2 inV) {
+    return native_log1p(inV);
+}
+
+half3 __attribute__((kernel)) testNativeLog1pHalf3Half3(half3 inV) {
+    return native_log1p(inV);
+}
+
+half4 __attribute__((kernel)) testNativeLog1pHalf4Half4(half4 inV) {
+    return native_log1p(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog2.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog2.java
index 402a746..111150b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog2.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog2.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeLog2HalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xb6e9470al, 10e-5, 65504);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeLog2HalfHalf(inV, out);
+            verifyResultsNativeLog2HalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2HalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog2HalfHalf(inV, out);
+            verifyResultsNativeLog2HalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2HalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog2HalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLog2HalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeLog2Half2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xc219255cl, 10e-5, 65504);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeLog2Half2Half2(inV, out);
+            verifyResultsNativeLog2Half2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog2Half2Half2(inV, out);
+            verifyResultsNativeLog2Half2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog2Half2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLog2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeLog2Half3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x2120ea50l, 10e-5, 65504);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeLog2Half3Half3(inV, out);
+            verifyResultsNativeLog2Half3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog2Half3Half3(inV, out);
+            verifyResultsNativeLog2Half3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog2Half3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLog2Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeLog2Half4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x8028af44l, 10e-5, 65504);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeLog2Half4Half4(inV, out);
+            verifyResultsNativeLog2Half4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeLog2Half4Half4(inV, out);
+            verifyResultsNativeLog2Half4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeLog2Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeLog2Half4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeLog2(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeLog2Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeLog2() {
         checkNativeLog2FloatFloat();
         checkNativeLog2Float2Float2();
         checkNativeLog2Float3Float3();
         checkNativeLog2Float4Float4();
+        checkNativeLog2HalfHalf();
+        checkNativeLog2Half2Half2();
+        checkNativeLog2Half3Half3();
+        checkNativeLog2Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog2.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog2.rs
index 55f48bb..649d584 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog2.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeLog2.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeLog2Float4Float4(float4 inV) {
     return native_log2(inV);
 }
+
+half __attribute__((kernel)) testNativeLog2HalfHalf(half inV) {
+    return native_log2(inV);
+}
+
+half2 __attribute__((kernel)) testNativeLog2Half2Half2(half2 inV) {
+    return native_log2(inV);
+}
+
+half3 __attribute__((kernel)) testNativeLog2Half3Half3(half3 inV) {
+    return native_log2(inV);
+}
+
+half4 __attribute__((kernel)) testNativeLog2Half4Half4(half4 inV) {
+    return native_log2(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativePowr.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativePowr.java
index c1ef937..6656c4d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativePowr.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativePowr.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inBase;
+        public double inBaseDouble;
+        public short inExponent;
+        public double inExponentDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativePowrHalfHalfHalf() {
+        Allocation inBase = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x5f0b09f0l, 0, 256);
+        Allocation inExponent = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x2a404496l, -15, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testNativePowrHalfHalfHalf(inBase, out);
+            verifyResultsNativePowrHalfHalfHalf(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testNativePowrHalfHalfHalf(inBase, out);
+            verifyResultsNativePowrHalfHalfHalf(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativePowrHalfHalfHalf(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        short[] arrayInExponent = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInExponent, (short) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inBase = arrayInBase[i];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i];
+                args.inExponentDouble = Float16Utils.convertFloat16ToDouble(args.inExponent);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativePowrHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativePowrHalf2Half2Half2() {
+        Allocation inBase = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xdfd0cbe8l, 0, 256);
+        Allocation inExponent = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xb2e110el, -15, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testNativePowrHalf2Half2Half2(inBase, out);
+            verifyResultsNativePowrHalf2Half2Half2(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testNativePowrHalf2Half2Half2(inBase, out);
+            verifyResultsNativePowrHalf2Half2Half2(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativePowrHalf2Half2Half2(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        short[] arrayInExponent = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInExponent, (short) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inBase = arrayInBase[i * 2 + j];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i * 2 + j];
+                args.inExponentDouble = Float16Utils.convertFloat16ToDouble(args.inExponent);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativePowrHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativePowrHalf3Half3Half3() {
+        Allocation inBase = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xd3821cc5l, 0, 256);
+        Allocation inExponent = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xcef3bdbl, -15, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testNativePowrHalf3Half3Half3(inBase, out);
+            verifyResultsNativePowrHalf3Half3Half3(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testNativePowrHalf3Half3Half3(inBase, out);
+            verifyResultsNativePowrHalf3Half3Half3(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativePowrHalf3Half3Half3(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        short[] arrayInExponent = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInExponent, (short) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inBase = arrayInBase[i * 4 + j];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i * 4 + j];
+                args.inExponentDouble = Float16Utils.convertFloat16ToDouble(args.inExponent);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativePowrHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativePowrHalf4Half4Half4() {
+        Allocation inBase = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xc7336da2l, 0, 256);
+        Allocation inExponent = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xeb066a8l, -15, 15);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testNativePowrHalf4Half4Half4(inBase, out);
+            verifyResultsNativePowrHalf4Half4Half4(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testNativePowrHalf4Half4Half4(inBase, out);
+            verifyResultsNativePowrHalf4Half4Half4(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativePowrHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativePowrHalf4Half4Half4(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        short[] arrayInExponent = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInExponent, (short) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inBase = arrayInBase[i * 4 + j];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i * 4 + j];
+                args.inExponentDouble = Float16Utils.convertFloat16ToDouble(args.inExponent);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativePowrHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativePowr() {
         checkNativePowrFloatFloatFloat();
         checkNativePowrFloat2Float2Float2();
         checkNativePowrFloat3Float3Float3();
         checkNativePowrFloat4Float4Float4();
+        checkNativePowrHalfHalfHalf();
+        checkNativePowrHalf2Half2Half2();
+        checkNativePowrHalf3Half3Half3();
+        checkNativePowrHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativePowr.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativePowr.rs
index 10e1e85..c3c7472 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativePowr.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativePowr.rs
@@ -40,3 +40,23 @@
     float4 inExponent = rsGetElementAt_float4(gAllocInExponent, x);
     return native_powr(inBase, inExponent);
 }
+
+half __attribute__((kernel)) testNativePowrHalfHalfHalf(half inBase, unsigned int x) {
+    half inExponent = rsGetElementAt_half(gAllocInExponent, x);
+    return native_powr(inBase, inExponent);
+}
+
+half2 __attribute__((kernel)) testNativePowrHalf2Half2Half2(half2 inBase, unsigned int x) {
+    half2 inExponent = rsGetElementAt_half2(gAllocInExponent, x);
+    return native_powr(inBase, inExponent);
+}
+
+half3 __attribute__((kernel)) testNativePowrHalf3Half3Half3(half3 inBase, unsigned int x) {
+    half3 inExponent = rsGetElementAt_half3(gAllocInExponent, x);
+    return native_powr(inBase, inExponent);
+}
+
+half4 __attribute__((kernel)) testNativePowrHalf4Half4Half4(half4 inBase, unsigned int x) {
+    half4 inExponent = rsGetElementAt_half4(gAllocInExponent, x);
+    return native_powr(inBase, inExponent);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRecip.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRecip.java
index c78885b..c33d5ba 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRecip.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRecip.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeRecipHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xee148533l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeRecipHalfHalf(inV, out);
+            verifyResultsNativeRecipHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRecipHalfHalf(inV, out);
+            verifyResultsNativeRecipHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRecipHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeRecip(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeRecipHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeRecipHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x396d1b7dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeRecipHalf2Half2(inV, out);
+            verifyResultsNativeRecipHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRecipHalf2Half2(inV, out);
+            verifyResultsNativeRecipHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRecipHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeRecip(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeRecipHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeRecipHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x9874e071l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeRecipHalf3Half3(inV, out);
+            verifyResultsNativeRecipHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRecipHalf3Half3(inV, out);
+            verifyResultsNativeRecipHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRecipHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeRecip(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeRecipHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeRecipHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xf77ca565l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeRecipHalf4Half4(inV, out);
+            verifyResultsNativeRecipHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRecipHalf4Half4(inV, out);
+            verifyResultsNativeRecipHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRecipHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRecipHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeRecip(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeRecipHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeRecip() {
         checkNativeRecipFloatFloat();
         checkNativeRecipFloat2Float2();
         checkNativeRecipFloat3Float3();
         checkNativeRecipFloat4Float4();
+        checkNativeRecipHalfHalf();
+        checkNativeRecipHalf2Half2();
+        checkNativeRecipHalf3Half3();
+        checkNativeRecipHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRecip.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRecip.rs
index b47bafa..bde315b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRecip.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRecip.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeRecipFloat4Float4(float4 inV) {
     return native_recip(inV);
 }
+
+half __attribute__((kernel)) testNativeRecipHalfHalf(half inV) {
+    return native_recip(inV);
+}
+
+half2 __attribute__((kernel)) testNativeRecipHalf2Half2(half2 inV) {
+    return native_recip(inV);
+}
+
+half3 __attribute__((kernel)) testNativeRecipHalf3Half3(half3 inV) {
+    return native_recip(inV);
+}
+
+half4 __attribute__((kernel)) testNativeRecipHalf4Half4(half4 inV) {
+    return native_recip(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRsqrt.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRsqrt.java
index 6e7389d..9989598b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRsqrt.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRsqrt.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeRsqrtHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x3e331e90l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeRsqrtHalfHalf(inV, out);
+            verifyResultsNativeRsqrtHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRsqrtHalfHalf(inV, out);
+            verifyResultsNativeRsqrtHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRsqrtHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeRsqrtHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeRsqrtHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xe66ecc32l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeRsqrtHalf2Half2(inV, out);
+            verifyResultsNativeRsqrtHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRsqrtHalf2Half2(inV, out);
+            verifyResultsNativeRsqrtHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRsqrtHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeRsqrtHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeRsqrtHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x45769126l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeRsqrtHalf3Half3(inV, out);
+            verifyResultsNativeRsqrtHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRsqrtHalf3Half3(inV, out);
+            verifyResultsNativeRsqrtHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRsqrtHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeRsqrtHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeRsqrtHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xa47e561al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeRsqrtHalf4Half4(inV, out);
+            verifyResultsNativeRsqrtHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeRsqrtHalf4Half4(inV, out);
+            verifyResultsNativeRsqrtHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeRsqrtHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeRsqrtHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeRsqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeRsqrtHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeRsqrt() {
         checkNativeRsqrtFloatFloat();
         checkNativeRsqrtFloat2Float2();
         checkNativeRsqrtFloat3Float3();
         checkNativeRsqrtFloat4Float4();
+        checkNativeRsqrtHalfHalf();
+        checkNativeRsqrtHalf2Half2();
+        checkNativeRsqrtHalf3Half3();
+        checkNativeRsqrtHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRsqrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRsqrt.rs
index 7455ea3..420e283 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRsqrt.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeRsqrt.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeRsqrtFloat4Float4(float4 inV) {
     return native_rsqrt(inV);
 }
+
+half __attribute__((kernel)) testNativeRsqrtHalfHalf(half inV) {
+    return native_rsqrt(inV);
+}
+
+half2 __attribute__((kernel)) testNativeRsqrtHalf2Half2(half2 inV) {
+    return native_rsqrt(inV);
+}
+
+half3 __attribute__((kernel)) testNativeRsqrtHalf3Half3(half3 inV) {
+    return native_rsqrt(inV);
+}
+
+half4 __attribute__((kernel)) testNativeRsqrtHalf4Half4(half4 inV) {
+    return native_rsqrt(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSin.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSin.java
index 0f6d59e..ede56bc 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSin.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSin.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeSinHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xd39c78f2l, -314, 314);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeSinHalfHalf(inV, out);
+            verifyResultsNativeSinHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinHalfHalf(inV, out);
+            verifyResultsNativeSinHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSinHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSinHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xc5c9a04l, -314, 314);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeSinHalf2Half2(inV, out);
+            verifyResultsNativeSinHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinHalf2Half2(inV, out);
+            verifyResultsNativeSinHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSinHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSinHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x6b645ef8l, -314, 314);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeSinHalf3Half3(inV, out);
+            verifyResultsNativeSinHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinHalf3Half3(inV, out);
+            verifyResultsNativeSinHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSinHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSinHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xca6c23ecl, -314, 314);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeSinHalf4Half4(inV, out);
+            verifyResultsNativeSinHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinHalf4Half4(inV, out);
+            verifyResultsNativeSinHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSinHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeSin() {
         checkNativeSinFloatFloat();
         checkNativeSinFloat2Float2();
         checkNativeSinFloat3Float3();
         checkNativeSinFloat4Float4();
+        checkNativeSinHalfHalf();
+        checkNativeSinHalf2Half2();
+        checkNativeSinHalf3Half3();
+        checkNativeSinHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSin.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSin.rs
index 968e947..9850518 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSin.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSin.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeSinFloat4Float4(float4 inV) {
     return native_sin(inV);
 }
+
+half __attribute__((kernel)) testNativeSinHalfHalf(half inV) {
+    return native_sin(inV);
+}
+
+half2 __attribute__((kernel)) testNativeSinHalf2Half2(half2 inV) {
+    return native_sin(inV);
+}
+
+half3 __attribute__((kernel)) testNativeSinHalf3Half3(half3 inV) {
+    return native_sin(inV);
+}
+
+half4 __attribute__((kernel)) testNativeSinHalf4Half4(half4 inV) {
+    return native_sin(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSincos.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSincos.java
index 50776e3..6a1c5b5 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSincos.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSincos.java
@@ -395,10 +395,401 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty outCos;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeSincosHalfHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x75ce8c9al, false);
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocOutCos(outCos);
+            script.forEach_testNativeSincosHalfHalfHalf(inV, out);
+            verifyResultsNativeSincosHalfHalfHalf(inV, outCos, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCos(outCos);
+            scriptRelaxed.forEach_testNativeSincosHalfHalfHalf(inV, out);
+            verifyResultsNativeSincosHalfHalfHalf(inV, outCos, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSincosHalfHalfHalf(Allocation inV, Allocation outCos, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOutCos = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOutCos, (short) 42);
+        outCos.copyTo(arrayOutCos);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 1 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output outCos: ");
+                        appendVariableToMessage(message, args.outCos);
+                        message.append("\n");
+                        message.append("Actual   output outCos: ");
+                        appendVariableToMessage(message, arrayOutCos[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output outCos (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 1 + j]));
+                        if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 1 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSincosHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSincosHalf2Half2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x9b1d1008l, false);
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocOutCos(outCos);
+            script.forEach_testNativeSincosHalf2Half2Half2(inV, out);
+            verifyResultsNativeSincosHalf2Half2Half2(inV, outCos, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCos(outCos);
+            scriptRelaxed.forEach_testNativeSincosHalf2Half2Half2(inV, out);
+            verifyResultsNativeSincosHalf2Half2Half2(inV, outCos, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSincosHalf2Half2Half2(Allocation inV, Allocation outCos, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOutCos = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOutCos, (short) 42);
+        outCos.copyTo(arrayOutCos);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 2 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output outCos: ");
+                        appendVariableToMessage(message, args.outCos);
+                        message.append("\n");
+                        message.append("Actual   output outCos: ");
+                        appendVariableToMessage(message, arrayOutCos[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output outCos (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 2 + j]));
+                        if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 2 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSincosHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSincosHalf3Half3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xf9bc20d7l, false);
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocOutCos(outCos);
+            script.forEach_testNativeSincosHalf3Half3Half3(inV, out);
+            verifyResultsNativeSincosHalf3Half3Half3(inV, outCos, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCos(outCos);
+            scriptRelaxed.forEach_testNativeSincosHalf3Half3Half3(inV, out);
+            verifyResultsNativeSincosHalf3Half3Half3(inV, outCos, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSincosHalf3Half3Half3(Allocation inV, Allocation outCos, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOutCos = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOutCos, (short) 42);
+        outCos.copyTo(arrayOutCos);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output outCos: ");
+                        appendVariableToMessage(message, args.outCos);
+                        message.append("\n");
+                        message.append("Actual   output outCos: ");
+                        appendVariableToMessage(message, arrayOutCos[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output outCos (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 4 + j]));
+                        if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSincosHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSincosHalf4Half4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x585b31a6l, false);
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocOutCos(outCos);
+            script.forEach_testNativeSincosHalf4Half4Half4(inV, out);
+            verifyResultsNativeSincosHalf4Half4Half4(inV, outCos, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCos(outCos);
+            scriptRelaxed.forEach_testNativeSincosHalf4Half4Half4(inV, out);
+            verifyResultsNativeSincosHalf4Half4Half4(inV, outCos, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSincosHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSincosHalf4Half4Half4(Allocation inV, Allocation outCos, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOutCos = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOutCos, (short) 42);
+        outCos.copyTo(arrayOutCos);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output outCos: ");
+                        appendVariableToMessage(message, args.outCos);
+                        message.append("\n");
+                        message.append("Actual   output outCos: ");
+                        appendVariableToMessage(message, arrayOutCos[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output outCos (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 4 + j]));
+                        if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSincosHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeSincos() {
         checkNativeSincosFloatFloatFloat();
         checkNativeSincosFloat2Float2Float2();
         checkNativeSincosFloat3Float3Float3();
         checkNativeSincosFloat4Float4Float4();
+        checkNativeSincosHalfHalfHalf();
+        checkNativeSincosHalf2Half2Half2();
+        checkNativeSincosHalf3Half3Half3();
+        checkNativeSincosHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSincos.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSincos.rs
index 30fe05b..80fc27e 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSincos.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSincos.rs
@@ -48,3 +48,31 @@
     rsSetElementAt_float4(gAllocOutCos, outCos, x);
     return out;
 }
+
+half __attribute__((kernel)) testNativeSincosHalfHalfHalf(half inV, unsigned int x) {
+    half outCos = 0;
+    half out = native_sincos(inV, &outCos);
+    rsSetElementAt_half(gAllocOutCos, outCos, x);
+    return out;
+}
+
+half2 __attribute__((kernel)) testNativeSincosHalf2Half2Half2(half2 inV, unsigned int x) {
+    half2 outCos = 0;
+    half2 out = native_sincos(inV, &outCos);
+    rsSetElementAt_half2(gAllocOutCos, outCos, x);
+    return out;
+}
+
+half3 __attribute__((kernel)) testNativeSincosHalf3Half3Half3(half3 inV, unsigned int x) {
+    half3 outCos = 0;
+    half3 out = native_sincos(inV, &outCos);
+    rsSetElementAt_half3(gAllocOutCos, outCos, x);
+    return out;
+}
+
+half4 __attribute__((kernel)) testNativeSincosHalf4Half4Half4(half4 inV, unsigned int x) {
+    half4 outCos = 0;
+    half4 out = native_sincos(inV, &outCos);
+    rsSetElementAt_half4(gAllocOutCos, outCos, x);
+    return out;
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinh.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinh.java
index 99b8c44..4d7cca1 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinh.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinh.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeSinhHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x5ff5eda0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeSinhHalfHalf(inV, out);
+            verifyResultsNativeSinhHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinhHalfHalf(inV, out);
+            verifyResultsNativeSinhHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinhHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSinhHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSinhHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xbe7856c2l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeSinhHalf2Half2(inV, out);
+            verifyResultsNativeSinhHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinhHalf2Half2(inV, out);
+            verifyResultsNativeSinhHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinhHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSinhHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSinhHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x1d801bb6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeSinhHalf3Half3(inV, out);
+            verifyResultsNativeSinhHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinhHalf3Half3(inV, out);
+            verifyResultsNativeSinhHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinhHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSinhHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSinhHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x7c87e0aal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeSinhHalf4Half4(inV, out);
+            verifyResultsNativeSinhHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinhHalf4Half4(inV, out);
+            verifyResultsNativeSinhHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinhHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinhHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSinhHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeSinh() {
         checkNativeSinhFloatFloat();
         checkNativeSinhFloat2Float2();
         checkNativeSinhFloat3Float3();
         checkNativeSinhFloat4Float4();
+        checkNativeSinhHalfHalf();
+        checkNativeSinhHalf2Half2();
+        checkNativeSinhHalf3Half3();
+        checkNativeSinhHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinh.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinh.rs
index 4acaafe..6ffca22 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinh.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinh.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeSinhFloat4Float4(float4 inV) {
     return native_sinh(inV);
 }
+
+half __attribute__((kernel)) testNativeSinhHalfHalf(half inV) {
+    return native_sinh(inV);
+}
+
+half2 __attribute__((kernel)) testNativeSinhHalf2Half2(half2 inV) {
+    return native_sinh(inV);
+}
+
+half3 __attribute__((kernel)) testNativeSinhHalf3Half3(half3 inV) {
+    return native_sinh(inV);
+}
+
+half4 __attribute__((kernel)) testNativeSinhHalf4Half4(half4 inV) {
+    return native_sinh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinpi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinpi.java
index 6d6b552..2d7a10d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinpi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinpi.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeSinpiHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x8ec9715l, -100, 100);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeSinpiHalfHalf(inV, out);
+            verifyResultsNativeSinpiHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinpiHalfHalf(inV, out);
+            verifyResultsNativeSinpiHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinpiHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSinpiHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSinpiHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x1c0644cfl, -100, 100);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeSinpiHalf2Half2(inV, out);
+            verifyResultsNativeSinpiHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinpiHalf2Half2(inV, out);
+            verifyResultsNativeSinpiHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinpiHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSinpiHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSinpiHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x7b0e09c3l, -100, 100);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeSinpiHalf3Half3(inV, out);
+            verifyResultsNativeSinpiHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinpiHalf3Half3(inV, out);
+            verifyResultsNativeSinpiHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinpiHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSinpiHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSinpiHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xda15ceb7l, -100, 100);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeSinpiHalf4Half4(inV, out);
+            verifyResultsNativeSinpiHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSinpiHalf4Half4(inV, out);
+            verifyResultsNativeSinpiHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSinpiHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSinpiHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]), 0.00048828125)) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSinpiHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeSinpi() {
         checkNativeSinpiFloatFloat();
         checkNativeSinpiFloat2Float2();
         checkNativeSinpiFloat3Float3();
         checkNativeSinpiFloat4Float4();
+        checkNativeSinpiHalfHalf();
+        checkNativeSinpiHalf2Half2();
+        checkNativeSinpiHalf3Half3();
+        checkNativeSinpiHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinpi.rs
index 56fdc67..eb66c65 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinpi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSinpi.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeSinpiFloat4Float4(float4 inV) {
     return native_sinpi(inV);
 }
+
+half __attribute__((kernel)) testNativeSinpiHalfHalf(half inV) {
+    return native_sinpi(inV);
+}
+
+half2 __attribute__((kernel)) testNativeSinpiHalf2Half2(half2 inV) {
+    return native_sinpi(inV);
+}
+
+half3 __attribute__((kernel)) testNativeSinpiHalf3Half3(half3 inV) {
+    return native_sinpi(inV);
+}
+
+half4 __attribute__((kernel)) testNativeSinpiHalf4Half4(half4 inV) {
+    return native_sinpi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSqrt.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSqrt.java
index b280792..a513ba6 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSqrt.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSqrt.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeSqrtHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x35305520l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeSqrtHalfHalf(inV, out);
+            verifyResultsNativeSqrtHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSqrtHalfHalf(inV, out);
+            verifyResultsNativeSqrtHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSqrtHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSqrtHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSqrtHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xd14de242l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeSqrtHalf2Half2(inV, out);
+            verifyResultsNativeSqrtHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSqrtHalf2Half2(inV, out);
+            verifyResultsNativeSqrtHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSqrtHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSqrtHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSqrtHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x3055a736l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeSqrtHalf3Half3(inV, out);
+            verifyResultsNativeSqrtHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSqrtHalf3Half3(inV, out);
+            verifyResultsNativeSqrtHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSqrtHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSqrtHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeSqrtHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x8f5d6c2al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeSqrtHalf4Half4(inV, out);
+            verifyResultsNativeSqrtHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeSqrtHalf4Half4(inV, out);
+            verifyResultsNativeSqrtHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeSqrtHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeSqrtHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeSqrtHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeSqrt() {
         checkNativeSqrtFloatFloat();
         checkNativeSqrtFloat2Float2();
         checkNativeSqrtFloat3Float3();
         checkNativeSqrtFloat4Float4();
+        checkNativeSqrtHalfHalf();
+        checkNativeSqrtHalf2Half2();
+        checkNativeSqrtHalf3Half3();
+        checkNativeSqrtHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSqrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSqrt.rs
index 9584dda..74d4960 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSqrt.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeSqrt.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeSqrtFloat4Float4(float4 inV) {
     return native_sqrt(inV);
 }
+
+half __attribute__((kernel)) testNativeSqrtHalfHalf(half inV) {
+    return native_sqrt(inV);
+}
+
+half2 __attribute__((kernel)) testNativeSqrtHalf2Half2(half2 inV) {
+    return native_sqrt(inV);
+}
+
+half3 __attribute__((kernel)) testNativeSqrtHalf3Half3(half3 inV) {
+    return native_sqrt(inV);
+}
+
+half4 __attribute__((kernel)) testNativeSqrtHalf4Half4(half4 inV) {
+    return native_sqrt(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTan.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTan.java
index c6c32b6..b43ff71 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTan.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTan.java
@@ -318,10 +318,293 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public short out;
+        public double outDouble;
+    }
+
+    private void checkNativeTanHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x3e70ec45l, -314, 314);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeTanHalfHalf(inV, out);
+            verifyResultsNativeTanHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanHalfHalf(inV, out);
+            verifyResultsNativeTanHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Extract the outputs.
+                args.out = arrayOut[i * 1 + j];
+                args.outDouble = Float16Utils.convertFloat16ToDouble(args.out);
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                String errorMessage = CoreMathVerifier.verifyNativeTan(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("\n");
+                        message.append("Output out (in double): ");
+                        appendVariableToMessage(message, args.outDouble);
+                        message.append("\n");
+                        message.append(errorMessage);
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeTanHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeTanHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xa4d18c7fl, -314, 314);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeTanHalf2Half2(inV, out);
+            verifyResultsNativeTanHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanHalf2Half2(inV, out);
+            verifyResultsNativeTanHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Extract the outputs.
+                args.out = arrayOut[i * 2 + j];
+                args.outDouble = Float16Utils.convertFloat16ToDouble(args.out);
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                String errorMessage = CoreMathVerifier.verifyNativeTan(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("\n");
+                        message.append("Output out (in double): ");
+                        appendVariableToMessage(message, args.outDouble);
+                        message.append("\n");
+                        message.append(errorMessage);
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeTanHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeTanHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x3d95173l, -314, 314);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeTanHalf3Half3(inV, out);
+            verifyResultsNativeTanHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanHalf3Half3(inV, out);
+            verifyResultsNativeTanHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Extract the outputs.
+                args.out = arrayOut[i * 4 + j];
+                args.outDouble = Float16Utils.convertFloat16ToDouble(args.out);
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                String errorMessage = CoreMathVerifier.verifyNativeTan(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("\n");
+                        message.append("Output out (in double): ");
+                        appendVariableToMessage(message, args.outDouble);
+                        message.append("\n");
+                        message.append(errorMessage);
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeTanHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeTanHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x62e11667l, -314, 314);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeTanHalf4Half4(inV, out);
+            verifyResultsNativeTanHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanHalf4Half4(inV, out);
+            verifyResultsNativeTanHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Extract the outputs.
+                args.out = arrayOut[i * 4 + j];
+                args.outDouble = Float16Utils.convertFloat16ToDouble(args.out);
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                String errorMessage = CoreMathVerifier.verifyNativeTan(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("\n");
+                        message.append("Output out (in double): ");
+                        appendVariableToMessage(message, args.outDouble);
+                        message.append("\n");
+                        message.append(errorMessage);
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeTanHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeTan() {
         checkNativeTanFloatFloat();
         checkNativeTanFloat2Float2();
         checkNativeTanFloat3Float3();
         checkNativeTanFloat4Float4();
+        checkNativeTanHalfHalf();
+        checkNativeTanHalf2Half2();
+        checkNativeTanHalf3Half3();
+        checkNativeTanHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTan.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTan.rs
index cbe930b..f28a852 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTan.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTan.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeTanFloat4Float4(float4 inV) {
     return native_tan(inV);
 }
+
+half __attribute__((kernel)) testNativeTanHalfHalf(half inV) {
+    return native_tan(inV);
+}
+
+half2 __attribute__((kernel)) testNativeTanHalf2Half2(half2 inV) {
+    return native_tan(inV);
+}
+
+half3 __attribute__((kernel)) testNativeTanHalf3Half3(half3 inV) {
+    return native_tan(inV);
+}
+
+half4 __attribute__((kernel)) testNativeTanHalf4Half4(half4 inV) {
+    return native_tan(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanh.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanh.java
index 2898543..6b2348b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanh.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanh.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkNativeTanhHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x51a54c91l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeTanhHalfHalf(inV, out);
+            verifyResultsNativeTanhHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanhHalfHalf(inV, out);
+            verifyResultsNativeTanhHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanhHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeTanhHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeTanhHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x5a1d116bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeTanhHalf2Half2(inV, out);
+            verifyResultsNativeTanhHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanhHalf2Half2(inV, out);
+            verifyResultsNativeTanhHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanhHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeTanhHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeTanhHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb924d65fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeTanhHalf3Half3(inV, out);
+            verifyResultsNativeTanhHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanhHalf3Half3(inV, out);
+            verifyResultsNativeTanhHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanhHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeTanhHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeTanhHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x182c9b53l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeTanhHalf4Half4(inV, out);
+            verifyResultsNativeTanhHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanhHalf4Half4(inV, out);
+            verifyResultsNativeTanhHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanhHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanhHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeNativeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeTanhHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeTanh() {
         checkNativeTanhFloatFloat();
         checkNativeTanhFloat2Float2();
         checkNativeTanhFloat3Float3();
         checkNativeTanhFloat4Float4();
+        checkNativeTanhHalfHalf();
+        checkNativeTanhHalf2Half2();
+        checkNativeTanhHalf3Half3();
+        checkNativeTanhHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanh.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanh.rs
index ead507f..a857d88 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanh.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanh.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeTanhFloat4Float4(float4 inV) {
     return native_tanh(inV);
 }
+
+half __attribute__((kernel)) testNativeTanhHalfHalf(half inV) {
+    return native_tanh(inV);
+}
+
+half2 __attribute__((kernel)) testNativeTanhHalf2Half2(half2 inV) {
+    return native_tanh(inV);
+}
+
+half3 __attribute__((kernel)) testNativeTanhHalf3Half3(half3 inV) {
+    return native_tanh(inV);
+}
+
+half4 __attribute__((kernel)) testNativeTanhHalf4Half4(half4 inV) {
+    return native_tanh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanpi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanpi.java
index 90afaa9..4104851 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanpi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanpi.java
@@ -318,10 +318,293 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public short out;
+        public double outDouble;
+    }
+
+    private void checkNativeTanpiHalfHalf() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xa1618990l, -100, 100);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testNativeTanpiHalfHalf(inV, out);
+            verifyResultsNativeTanpiHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanpiHalfHalf(inV, out);
+            verifyResultsNativeTanpiHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanpiHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Extract the outputs.
+                args.out = arrayOut[i * 1 + j];
+                args.outDouble = Float16Utils.convertFloat16ToDouble(args.out);
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                String errorMessage = CoreMathVerifier.verifyNativeTanpi(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("\n");
+                        message.append("Output out (in double): ");
+                        appendVariableToMessage(message, args.outDouble);
+                        message.append("\n");
+                        message.append(errorMessage);
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeTanpiHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeTanpiHalf2Half2() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x40b19f32l, -100, 100);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testNativeTanpiHalf2Half2(inV, out);
+            verifyResultsNativeTanpiHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanpiHalf2Half2(inV, out);
+            verifyResultsNativeTanpiHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanpiHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Extract the outputs.
+                args.out = arrayOut[i * 2 + j];
+                args.outDouble = Float16Utils.convertFloat16ToDouble(args.out);
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                String errorMessage = CoreMathVerifier.verifyNativeTanpi(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("\n");
+                        message.append("Output out (in double): ");
+                        appendVariableToMessage(message, args.outDouble);
+                        message.append("\n");
+                        message.append(errorMessage);
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeTanpiHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeTanpiHalf3Half3() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x9fb96426l, -100, 100);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testNativeTanpiHalf3Half3(inV, out);
+            verifyResultsNativeTanpiHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanpiHalf3Half3(inV, out);
+            verifyResultsNativeTanpiHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanpiHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Extract the outputs.
+                args.out = arrayOut[i * 4 + j];
+                args.outDouble = Float16Utils.convertFloat16ToDouble(args.out);
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                String errorMessage = CoreMathVerifier.verifyNativeTanpi(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("\n");
+                        message.append("Output out (in double): ");
+                        appendVariableToMessage(message, args.outDouble);
+                        message.append("\n");
+                        message.append(errorMessage);
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeTanpiHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkNativeTanpiHalf4Half4() {
+        Allocation inV = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xfec1291al, -100, 100);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testNativeTanpiHalf4Half4(inV, out);
+            verifyResultsNativeTanpiHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testNativeTanpiHalf4Half4(inV, out);
+            verifyResultsNativeTanpiHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testNativeTanpiHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsNativeTanpiHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Extract the outputs.
+                args.out = arrayOut[i * 4 + j];
+                args.outDouble = Float16Utils.convertFloat16ToDouble(args.out);
+                // Ask the CoreMathVerifier to validate.
+                Target target = new Target(Target.FunctionType.NATIVE, Target.ReturnType.HALF, relaxed);
+                String errorMessage = CoreMathVerifier.verifyNativeTanpi(args, target);
+                boolean valid = errorMessage == null;
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("\n");
+                        message.append("Output out (in double): ");
+                        appendVariableToMessage(message, args.outDouble);
+                        message.append("\n");
+                        message.append(errorMessage);
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkNativeTanpiHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testNativeTanpi() {
         checkNativeTanpiFloatFloat();
         checkNativeTanpiFloat2Float2();
         checkNativeTanpiFloat3Float3();
         checkNativeTanpiFloat4Float4();
+        checkNativeTanpiHalfHalf();
+        checkNativeTanpiHalf2Half2();
+        checkNativeTanpiHalf3Half3();
+        checkNativeTanpiHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanpi.rs
index 21e0b15..902cda2 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanpi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestNativeTanpi.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testNativeTanpiFloat4Float4(float4 inV) {
     return native_tanpi(inV);
 }
+
+half __attribute__((kernel)) testNativeTanpiHalfHalf(half inV) {
+    return native_tanpi(inV);
+}
+
+half2 __attribute__((kernel)) testNativeTanpiHalf2Half2(half2 inV) {
+    return native_tanpi(inV);
+}
+
+half3 __attribute__((kernel)) testNativeTanpiHalf3Half3(half3 inV) {
+    return native_tanpi(inV);
+}
+
+half4 __attribute__((kernel)) testNativeTanpiHalf4Half4(half4 inV) {
+    return native_tanpi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPow.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPow.java
index 660df1b..2aa4e99 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPow.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPow.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inBase;
+        public double inBaseDouble;
+        public short inExponent;
+        public double inExponentDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkPowHalfHalfHalf() {
+        Allocation inBase = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe2a33d87l, false);
+        Allocation inExponent = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x999eb5fdl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testPowHalfHalfHalf(inBase, out);
+            verifyResultsPowHalfHalfHalf(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testPowHalfHalfHalf(inBase, out);
+            verifyResultsPowHalfHalfHalf(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowHalfHalfHalf(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        short[] arrayInExponent = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInExponent, (short) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inBase = arrayInBase[i];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i];
+                args.inExponentDouble = Float16Utils.convertFloat16ToDouble(args.inExponent);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computePow(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkPowHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkPowHalf2Half2Half2() {
+        Allocation inBase = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xbeaf459dl, false);
+        Allocation inExponent = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x5bbbe933l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testPowHalf2Half2Half2(inBase, out);
+            verifyResultsPowHalf2Half2Half2(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testPowHalf2Half2Half2(inBase, out);
+            verifyResultsPowHalf2Half2Half2(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowHalf2Half2Half2(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        short[] arrayInExponent = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInExponent, (short) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inBase = arrayInBase[i * 2 + j];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i * 2 + j];
+                args.inExponentDouble = Float16Utils.convertFloat16ToDouble(args.inExponent);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computePow(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkPowHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkPowHalf3Half3Half3() {
+        Allocation inBase = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb260967al, false);
+        Allocation inExponent = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x5d7d1400l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testPowHalf3Half3Half3(inBase, out);
+            verifyResultsPowHalf3Half3Half3(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testPowHalf3Half3Half3(inBase, out);
+            verifyResultsPowHalf3Half3Half3(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowHalf3Half3Half3(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        short[] arrayInExponent = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInExponent, (short) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inBase = arrayInBase[i * 4 + j];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i * 4 + j];
+                args.inExponentDouble = Float16Utils.convertFloat16ToDouble(args.inExponent);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computePow(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkPowHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkPowHalf4Half4Half4() {
+        Allocation inBase = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xa611e757l, false);
+        Allocation inExponent = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x5f3e3ecdl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testPowHalf4Half4Half4(inBase, out);
+            verifyResultsPowHalf4Half4Half4(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testPowHalf4Half4Half4(inBase, out);
+            verifyResultsPowHalf4Half4Half4(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowHalf4Half4Half4(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        short[] arrayInExponent = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInExponent, (short) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inBase = arrayInBase[i * 4 + j];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i * 4 + j];
+                args.inExponentDouble = Float16Utils.convertFloat16ToDouble(args.inExponent);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computePow(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkPowHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testPow() {
         checkPowFloatFloatFloat();
         checkPowFloat2Float2Float2();
         checkPowFloat3Float3Float3();
         checkPowFloat4Float4Float4();
+        checkPowHalfHalfHalf();
+        checkPowHalf2Half2Half2();
+        checkPowHalf3Half3Half3();
+        checkPowHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPow.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPow.rs
index 2ec97e2..651b41c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPow.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPow.rs
@@ -40,3 +40,23 @@
     float4 inExponent = rsGetElementAt_float4(gAllocInExponent, x);
     return pow(inBase, inExponent);
 }
+
+half __attribute__((kernel)) testPowHalfHalfHalf(half inBase, unsigned int x) {
+    half inExponent = rsGetElementAt_half(gAllocInExponent, x);
+    return pow(inBase, inExponent);
+}
+
+half2 __attribute__((kernel)) testPowHalf2Half2Half2(half2 inBase, unsigned int x) {
+    half2 inExponent = rsGetElementAt_half2(gAllocInExponent, x);
+    return pow(inBase, inExponent);
+}
+
+half3 __attribute__((kernel)) testPowHalf3Half3Half3(half3 inBase, unsigned int x) {
+    half3 inExponent = rsGetElementAt_half3(gAllocInExponent, x);
+    return pow(inBase, inExponent);
+}
+
+half4 __attribute__((kernel)) testPowHalf4Half4Half4(half4 inBase, unsigned int x) {
+    half4 inExponent = rsGetElementAt_half4(gAllocInExponent, x);
+    return pow(inBase, inExponent);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPown.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPown.java
index 2e16f21..51233de 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPown.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPown.java
@@ -359,10 +359,353 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfIntHalf {
+        public short inBase;
+        public double inBaseDouble;
+        public int inExponent;
+        public Target.Floaty out;
+    }
+
+    private void checkPownHalfIntHalf() {
+        Allocation inBase = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x858a42bbl, false);
+        Allocation inExponent = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 1, 0x30c3d6f1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testPownHalfIntHalf(inBase, out);
+            verifyResultsPownHalfIntHalf(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownHalfIntHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testPownHalfIntHalf(inBase, out);
+            verifyResultsPownHalfIntHalf(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownHalfIntHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPownHalfIntHalf(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        int[] arrayInExponent = new int[INPUTSIZE * 1];
+        Arrays.fill(arrayInExponent, (int) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfIntHalf args = new ArgumentsHalfIntHalf();
+                args.inBase = arrayInBase[i];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computePown(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkPownHalfIntHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkPownHalf2Int2Half2() {
+        Allocation inBase = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x29ccb2d5l, false);
+        Allocation inExponent = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 2, 0x6e5f9cebl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testPownHalf2Int2Half2(inBase, out);
+            verifyResultsPownHalf2Int2Half2(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownHalf2Int2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testPownHalf2Int2Half2(inBase, out);
+            verifyResultsPownHalf2Int2Half2(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownHalf2Int2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPownHalf2Int2Half2(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        int[] arrayInExponent = new int[INPUTSIZE * 2];
+        Arrays.fill(arrayInExponent, (int) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfIntHalf args = new ArgumentsHalfIntHalf();
+                args.inBase = arrayInBase[i * 2 + j];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i * 2 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computePown(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkPownHalf2Int2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkPownHalf3Int3Half3() {
+        Allocation inBase = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x2f8523b4l, false);
+        Allocation inExponent = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 3, 0x92b63d1al, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testPownHalf3Int3Half3(inBase, out);
+            verifyResultsPownHalf3Int3Half3(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownHalf3Int3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testPownHalf3Int3Half3(inBase, out);
+            verifyResultsPownHalf3Int3Half3(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownHalf3Int3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPownHalf3Int3Half3(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        int[] arrayInExponent = new int[INPUTSIZE * 4];
+        Arrays.fill(arrayInExponent, (int) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfIntHalf args = new ArgumentsHalfIntHalf();
+                args.inBase = arrayInBase[i * 4 + j];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computePown(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkPownHalf3Int3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkPownHalf4Int4Half4() {
+        Allocation inBase = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x353d9493l, false);
+        Allocation inExponent = createRandomAllocation(mRS, Element.DataType.SIGNED_32, 4, 0xb70cdd49l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testPownHalf4Int4Half4(inBase, out);
+            verifyResultsPownHalf4Int4Half4(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownHalf4Int4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testPownHalf4Int4Half4(inBase, out);
+            verifyResultsPownHalf4Int4Half4(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPownHalf4Int4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPownHalf4Int4Half4(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        int[] arrayInExponent = new int[INPUTSIZE * 4];
+        Arrays.fill(arrayInExponent, (int) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfIntHalf args = new ArgumentsHalfIntHalf();
+                args.inBase = arrayInBase[i * 4 + j];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i * 4 + j];
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computePown(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkPownHalf4Int4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testPown() {
         checkPownFloatIntFloat();
         checkPownFloat2Int2Float2();
         checkPownFloat3Int3Float3();
         checkPownFloat4Int4Float4();
+        checkPownHalfIntHalf();
+        checkPownHalf2Int2Half2();
+        checkPownHalf3Int3Half3();
+        checkPownHalf4Int4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPown.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPown.rs
index 29b2715..febc71b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPown.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPown.rs
@@ -40,3 +40,23 @@
     int4 inExponent = rsGetElementAt_int4(gAllocInExponent, x);
     return pown(inBase, inExponent);
 }
+
+half __attribute__((kernel)) testPownHalfIntHalf(half inBase, unsigned int x) {
+    int inExponent = rsGetElementAt_int(gAllocInExponent, x);
+    return pown(inBase, inExponent);
+}
+
+half2 __attribute__((kernel)) testPownHalf2Int2Half2(half2 inBase, unsigned int x) {
+    int2 inExponent = rsGetElementAt_int2(gAllocInExponent, x);
+    return pown(inBase, inExponent);
+}
+
+half3 __attribute__((kernel)) testPownHalf3Int3Half3(half3 inBase, unsigned int x) {
+    int3 inExponent = rsGetElementAt_int3(gAllocInExponent, x);
+    return pown(inBase, inExponent);
+}
+
+half4 __attribute__((kernel)) testPownHalf4Int4Half4(half4 inBase, unsigned int x) {
+    int4 inExponent = rsGetElementAt_int4(gAllocInExponent, x);
+    return pown(inBase, inExponent);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPowr.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPowr.java
index 557e293..71b0500 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPowr.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPowr.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inBase;
+        public double inBaseDouble;
+        public short inExponent;
+        public double inExponentDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkPowrHalfHalfHalf() {
+        Allocation inBase = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x752063b9l, 0, 300);
+        Allocation inExponent = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x2c92528fl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testPowrHalfHalfHalf(inBase, out);
+            verifyResultsPowrHalfHalfHalf(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testPowrHalfHalfHalf(inBase, out);
+            verifyResultsPowrHalfHalfHalf(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowrHalfHalfHalf(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        short[] arrayInExponent = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInExponent, (short) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inBase = arrayInBase[i];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i];
+                args.inExponentDouble = Float16Utils.convertFloat16ToDouble(args.inExponent);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkPowrHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkPowrHalf2Half2Half2() {
+        Allocation inBase = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x68ccc053l, 0, 300);
+        Allocation inExponent = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xbd379d09l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testPowrHalf2Half2Half2(inBase, out);
+            verifyResultsPowrHalf2Half2Half2(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testPowrHalf2Half2Half2(inBase, out);
+            verifyResultsPowrHalf2Half2Half2(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowrHalf2Half2Half2(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        short[] arrayInExponent = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInExponent, (short) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inBase = arrayInBase[i * 2 + j];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i * 2 + j];
+                args.inExponentDouble = Float16Utils.convertFloat16ToDouble(args.inExponent);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkPowrHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkPowrHalf3Half3Half3() {
+        Allocation inBase = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x5c7e1130l, 0, 300);
+        Allocation inExponent = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xbef8c7d6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testPowrHalf3Half3Half3(inBase, out);
+            verifyResultsPowrHalf3Half3Half3(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testPowrHalf3Half3Half3(inBase, out);
+            verifyResultsPowrHalf3Half3Half3(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowrHalf3Half3Half3(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        short[] arrayInExponent = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInExponent, (short) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inBase = arrayInBase[i * 4 + j];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i * 4 + j];
+                args.inExponentDouble = Float16Utils.convertFloat16ToDouble(args.inExponent);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkPowrHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkPowrHalf4Half4Half4() {
+        Allocation inBase = createRandomFloatAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x502f620dl, 0, 300);
+        Allocation inExponent = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xc0b9f2a3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInExponent(inExponent);
+            script.forEach_testPowrHalf4Half4Half4(inBase, out);
+            verifyResultsPowrHalf4Half4Half4(inBase, inExponent, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInExponent(inExponent);
+            scriptRelaxed.forEach_testPowrHalf4Half4Half4(inBase, out);
+            verifyResultsPowrHalf4Half4Half4(inBase, inExponent, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testPowrHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsPowrHalf4Half4Half4(Allocation inBase, Allocation inExponent, Allocation out, boolean relaxed) {
+        short[] arrayInBase = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInBase, (short) 42);
+        inBase.copyTo(arrayInBase);
+        short[] arrayInExponent = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInExponent, (short) 42);
+        inExponent.copyTo(arrayInExponent);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inBase = arrayInBase[i * 4 + j];
+                args.inBaseDouble = Float16Utils.convertFloat16ToDouble(args.inBase);
+                args.inExponent = arrayInExponent[i * 4 + j];
+                args.inExponentDouble = Float16Utils.convertFloat16ToDouble(args.inExponent);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computePowr(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inBase: ");
+                        appendVariableToMessage(message, args.inBase);
+                        message.append("\n");
+                        message.append("Input inExponent: ");
+                        appendVariableToMessage(message, args.inExponent);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkPowrHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testPowr() {
         checkPowrFloatFloatFloat();
         checkPowrFloat2Float2Float2();
         checkPowrFloat3Float3Float3();
         checkPowrFloat4Float4Float4();
+        checkPowrHalfHalfHalf();
+        checkPowrHalf2Half2Half2();
+        checkPowrHalf3Half3Half3();
+        checkPowrHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPowr.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPowr.rs
index 6ba51b7..0fdf69d 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPowr.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestPowr.rs
@@ -40,3 +40,23 @@
     float4 inExponent = rsGetElementAt_float4(gAllocInExponent, x);
     return powr(inBase, inExponent);
 }
+
+half __attribute__((kernel)) testPowrHalfHalfHalf(half inBase, unsigned int x) {
+    half inExponent = rsGetElementAt_half(gAllocInExponent, x);
+    return powr(inBase, inExponent);
+}
+
+half2 __attribute__((kernel)) testPowrHalf2Half2Half2(half2 inBase, unsigned int x) {
+    half2 inExponent = rsGetElementAt_half2(gAllocInExponent, x);
+    return powr(inBase, inExponent);
+}
+
+half3 __attribute__((kernel)) testPowrHalf3Half3Half3(half3 inBase, unsigned int x) {
+    half3 inExponent = rsGetElementAt_half3(gAllocInExponent, x);
+    return powr(inBase, inExponent);
+}
+
+half4 __attribute__((kernel)) testPowrHalf4Half4Half4(half4 inBase, unsigned int x) {
+    half4 inExponent = rsGetElementAt_half4(gAllocInExponent, x);
+    return powr(inBase, inExponent);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRadians.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRadians.java
index 8eeaea0..7d7bf2f 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRadians.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRadians.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkRadiansHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x3875b1edl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testRadiansHalfHalf(inV, out);
+            verifyResultsRadiansHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testRadiansHalfHalf(inV, out);
+            verifyResultsRadiansHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRadiansHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRadians(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRadiansHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRadiansHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x714926e7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testRadiansHalf2Half2(inV, out);
+            verifyResultsRadiansHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testRadiansHalf2Half2(inV, out);
+            verifyResultsRadiansHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRadiansHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRadians(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRadiansHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRadiansHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xd050ebdbl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testRadiansHalf3Half3(inV, out);
+            verifyResultsRadiansHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testRadiansHalf3Half3(inV, out);
+            verifyResultsRadiansHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRadiansHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRadians(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRadiansHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRadiansHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x2f58b0cfl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testRadiansHalf4Half4(inV, out);
+            verifyResultsRadiansHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testRadiansHalf4Half4(inV, out);
+            verifyResultsRadiansHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRadiansHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRadiansHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRadians(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRadiansHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testRadians() {
         checkRadiansFloatFloat();
         checkRadiansFloat2Float2();
         checkRadiansFloat3Float3();
         checkRadiansFloat4Float4();
+        checkRadiansHalfHalf();
+        checkRadiansHalf2Half2();
+        checkRadiansHalf3Half3();
+        checkRadiansHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRadians.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRadians.rs
index 1d881bd..5ada9b9 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRadians.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRadians.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testRadiansFloat4Float4(float4 inV) {
     return radians(inV);
 }
+
+half __attribute__((kernel)) testRadiansHalfHalf(half inV) {
+    return radians(inV);
+}
+
+half2 __attribute__((kernel)) testRadiansHalf2Half2(half2 inV) {
+    return radians(inV);
+}
+
+half3 __attribute__((kernel)) testRadiansHalf3Half3(half3 inV) {
+    return radians(inV);
+}
+
+half4 __attribute__((kernel)) testRadiansHalf4Half4(half4 inV) {
+    return radians(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRemainder.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRemainder.java
index f921c5b..a8c3c07 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRemainder.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRemainder.java
@@ -359,10 +359,358 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inNumerator;
+        public double inNumeratorDouble;
+        public short inDenominator;
+        public double inDenominatorDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkRemainderHalfHalfHalf() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xcd987ebel, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x59b61387l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testRemainderHalfHalfHalf(inNumerator, out);
+            verifyResultsRemainderHalfHalfHalf(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testRemainderHalfHalfHalf(inNumerator, out);
+            verifyResultsRemainderHalfHalfHalf(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRemainderHalfHalfHalf(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRemainder(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRemainderHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRemainderHalf2Half2Half2() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x3b2e47fel, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xd890a2c7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testRemainderHalf2Half2Half2(inNumerator, out);
+            verifyResultsRemainderHalf2Half2Half2(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testRemainderHalf2Half2Half2(inNumerator, out);
+            verifyResultsRemainderHalf2Half2Half2(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRemainderHalf2Half2Half2(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 2 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 2 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRemainder(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRemainderHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRemainderHalf3Half3Half3() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x86a0786dl, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xc450747el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testRemainderHalf3Half3Half3(inNumerator, out);
+            verifyResultsRemainderHalf3Half3Half3(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testRemainderHalf3Half3Half3(inNumerator, out);
+            verifyResultsRemainderHalf3Half3Half3(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRemainderHalf3Half3Half3(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 4 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 4 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRemainder(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRemainderHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRemainderHalf4Half4Half4() {
+        Allocation inNumerator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xd212a8dcl, false);
+        Allocation inDenominator = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xb0104635l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInDenominator(inDenominator);
+            script.forEach_testRemainderHalf4Half4Half4(inNumerator, out);
+            verifyResultsRemainderHalf4Half4Half4(inNumerator, inDenominator, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInDenominator(inDenominator);
+            scriptRelaxed.forEach_testRemainderHalf4Half4Half4(inNumerator, out);
+            verifyResultsRemainderHalf4Half4Half4(inNumerator, inDenominator, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRemainderHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRemainderHalf4Half4Half4(Allocation inNumerator, Allocation inDenominator, Allocation out, boolean relaxed) {
+        short[] arrayInNumerator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInNumerator, (short) 42);
+        inNumerator.copyTo(arrayInNumerator);
+        short[] arrayInDenominator = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInDenominator, (short) 42);
+        inDenominator.copyTo(arrayInDenominator);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inNumerator = arrayInNumerator[i * 4 + j];
+                args.inNumeratorDouble = Float16Utils.convertFloat16ToDouble(args.inNumerator);
+                args.inDenominator = arrayInDenominator[i * 4 + j];
+                args.inDenominatorDouble = Float16Utils.convertFloat16ToDouble(args.inDenominator);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRemainder(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inNumerator: ");
+                        appendVariableToMessage(message, args.inNumerator);
+                        message.append("\n");
+                        message.append("Input inDenominator: ");
+                        appendVariableToMessage(message, args.inDenominator);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRemainderHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testRemainder() {
         checkRemainderFloatFloatFloat();
         checkRemainderFloat2Float2Float2();
         checkRemainderFloat3Float3Float3();
         checkRemainderFloat4Float4Float4();
+        checkRemainderHalfHalfHalf();
+        checkRemainderHalf2Half2Half2();
+        checkRemainderHalf3Half3Half3();
+        checkRemainderHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRemainder.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRemainder.rs
index ddd6ae7..60590f6 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRemainder.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRemainder.rs
@@ -40,3 +40,23 @@
     float4 inDenominator = rsGetElementAt_float4(gAllocInDenominator, x);
     return remainder(inNumerator, inDenominator);
 }
+
+half __attribute__((kernel)) testRemainderHalfHalfHalf(half inNumerator, unsigned int x) {
+    half inDenominator = rsGetElementAt_half(gAllocInDenominator, x);
+    return remainder(inNumerator, inDenominator);
+}
+
+half2 __attribute__((kernel)) testRemainderHalf2Half2Half2(half2 inNumerator, unsigned int x) {
+    half2 inDenominator = rsGetElementAt_half2(gAllocInDenominator, x);
+    return remainder(inNumerator, inDenominator);
+}
+
+half3 __attribute__((kernel)) testRemainderHalf3Half3Half3(half3 inNumerator, unsigned int x) {
+    half3 inDenominator = rsGetElementAt_half3(gAllocInDenominator, x);
+    return remainder(inNumerator, inDenominator);
+}
+
+half4 __attribute__((kernel)) testRemainderHalf4Half4Half4(half4 inNumerator, unsigned int x) {
+    half4 inDenominator = rsGetElementAt_half4(gAllocInDenominator, x);
+    return remainder(inNumerator, inDenominator);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRint.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRint.java
index f829798..89dc0e8 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRint.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRint.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkRintHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xec6959del, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testRintHalfHalf(inV, out);
+            verifyResultsRintHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testRintHalfHalf(inV, out);
+            verifyResultsRintHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRintHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRint(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRintHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRintHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x2c212290l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testRintHalf2Half2(inV, out);
+            verifyResultsRintHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testRintHalf2Half2(inV, out);
+            verifyResultsRintHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRintHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRint(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRintHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRintHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x8b28e784l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testRintHalf3Half3(inV, out);
+            verifyResultsRintHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testRintHalf3Half3(inV, out);
+            verifyResultsRintHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRintHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRint(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRintHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRintHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xea30ac78l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testRintHalf4Half4(inV, out);
+            verifyResultsRintHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testRintHalf4Half4(inV, out);
+            verifyResultsRintHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRintHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRintHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRint(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRintHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testRint() {
         checkRintFloatFloat();
         checkRintFloat2Float2();
         checkRintFloat3Float3();
         checkRintFloat4Float4();
+        checkRintHalfHalf();
+        checkRintHalf2Half2();
+        checkRintHalf3Half3();
+        checkRintHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRint.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRint.rs
index fb0d9a1..3c0d0f1 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRint.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRint.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testRintFloat4Float4(float4 inV) {
     return rint(inV);
 }
+
+half __attribute__((kernel)) testRintHalfHalf(half inV) {
+    return rint(inV);
+}
+
+half2 __attribute__((kernel)) testRintHalf2Half2(half2 inV) {
+    return rint(inV);
+}
+
+half3 __attribute__((kernel)) testRintHalf3Half3(half3 inV) {
+    return rint(inV);
+}
+
+half4 __attribute__((kernel)) testRintHalf4Half4(half4 inV) {
+    return rint(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRound.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRound.java
index 55f16f5..c13b7c0 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRound.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRound.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkRoundHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe9b639c5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testRoundHalfHalf(inV, out);
+            verifyResultsRoundHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testRoundHalfHalf(inV, out);
+            verifyResultsRoundHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRoundHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRound(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRoundHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRoundHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xac5e4dffl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testRoundHalf2Half2(inV, out);
+            verifyResultsRoundHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testRoundHalf2Half2(inV, out);
+            verifyResultsRoundHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRoundHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRound(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRoundHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRoundHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb6612f3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testRoundHalf3Half3(inV, out);
+            verifyResultsRoundHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testRoundHalf3Half3(inV, out);
+            verifyResultsRoundHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRoundHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRound(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRoundHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkRoundHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x6a6dd7e7l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testRoundHalf4Half4(inV, out);
+            verifyResultsRoundHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testRoundHalf4Half4(inV, out);
+            verifyResultsRoundHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testRoundHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsRoundHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeRound(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkRoundHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testRound() {
         checkRoundFloatFloat();
         checkRoundFloat2Float2();
         checkRoundFloat3Float3();
         checkRoundFloat4Float4();
+        checkRoundHalfHalf();
+        checkRoundHalf2Half2();
+        checkRoundHalf3Half3();
+        checkRoundHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRound.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRound.rs
index 002dd19..1966eaf 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRound.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestRound.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testRoundFloat4Float4(float4 inV) {
     return round(inV);
 }
+
+half __attribute__((kernel)) testRoundHalfHalf(half inV) {
+    return round(inV);
+}
+
+half2 __attribute__((kernel)) testRoundHalf2Half2(half2 inV) {
+    return round(inV);
+}
+
+half3 __attribute__((kernel)) testRoundHalf3Half3(half3 inV) {
+    return round(inV);
+}
+
+half4 __attribute__((kernel)) testRoundHalf4Half4(half4 inV) {
+    return round(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSign.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSign.java
index 2a002df..ae4ce6a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSign.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSign.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkSignHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xf1994bfel, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testSignHalfHalf(inV, out);
+            verifyResultsSignHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testSignHalfHalf(inV, out);
+            verifyResultsSignHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSignHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSignHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSignHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xa36cebb0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testSignHalf2Half2(inV, out);
+            verifyResultsSignHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testSignHalf2Half2(inV, out);
+            verifyResultsSignHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSignHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSignHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSignHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x274b0a4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testSignHalf3Half3(inV, out);
+            verifyResultsSignHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testSignHalf3Half3(inV, out);
+            verifyResultsSignHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSignHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSignHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSignHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x617c7598l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testSignHalf4Half4(inV, out);
+            verifyResultsSignHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testSignHalf4Half4(inV, out);
+            verifyResultsSignHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSignHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSignHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSign(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSignHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testSign() {
         checkSignFloatFloat();
         checkSignFloat2Float2();
         checkSignFloat3Float3();
         checkSignFloat4Float4();
+        checkSignHalfHalf();
+        checkSignHalf2Half2();
+        checkSignHalf3Half3();
+        checkSignHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSign.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSign.rs
index 06f8362..3f2ef9b 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSign.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSign.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testSignFloat4Float4(float4 inV) {
     return sign(inV);
 }
+
+half __attribute__((kernel)) testSignHalfHalf(half inV) {
+    return sign(inV);
+}
+
+half2 __attribute__((kernel)) testSignHalf2Half2(half2 inV) {
+    return sign(inV);
+}
+
+half3 __attribute__((kernel)) testSignHalf3Half3(half3 inV) {
+    return sign(inV);
+}
+
+half4 __attribute__((kernel)) testSignHalf4Half4(half4 inV) {
+    return sign(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSin.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSin.java
index 1eeca79..e11ba7a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSin.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSin.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkSinHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x591ded5bl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testSinHalfHalf(inV, out);
+            verifyResultsSinHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testSinHalfHalf(inV, out);
+            verifyResultsSinHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSinHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSinHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x505e6465l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testSinHalf2Half2(inV, out);
+            verifyResultsSinHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testSinHalf2Half2(inV, out);
+            verifyResultsSinHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSinHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSinHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xaf662959l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testSinHalf3Half3(inV, out);
+            verifyResultsSinHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testSinHalf3Half3(inV, out);
+            verifyResultsSinHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSinHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSinHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xe6dee4dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testSinHalf4Half4(inV, out);
+            verifyResultsSinHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testSinHalf4Half4(inV, out);
+            verifyResultsSinHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSin(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSinHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testSin() {
         checkSinFloatFloat();
         checkSinFloat2Float2();
         checkSinFloat3Float3();
         checkSinFloat4Float4();
+        checkSinHalfHalf();
+        checkSinHalf2Half2();
+        checkSinHalf3Half3();
+        checkSinHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSin.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSin.rs
index 90b573b..4692ec1 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSin.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSin.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testSinFloat4Float4(float4 inV) {
     return sin(inV);
 }
+
+half __attribute__((kernel)) testSinHalfHalf(half inV) {
+    return sin(inV);
+}
+
+half2 __attribute__((kernel)) testSinHalf2Half2(half2 inV) {
+    return sin(inV);
+}
+
+half3 __attribute__((kernel)) testSinHalf3Half3(half3 inV) {
+    return sin(inV);
+}
+
+half4 __attribute__((kernel)) testSinHalf4Half4(half4 inV) {
+    return sin(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSincos.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSincos.java
index 0b0d0d1..f2e2e16 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSincos.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSincos.java
@@ -395,10 +395,401 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty outCos;
+        public Target.Floaty out;
+    }
+
+    private void checkSincosHalfHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x9ffeac75l, false);
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocOutCos(outCos);
+            script.forEach_testSincosHalfHalfHalf(inV, out);
+            verifyResultsSincosHalfHalfHalf(inV, outCos, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCos(outCos);
+            scriptRelaxed.forEach_testSincosHalfHalfHalf(inV, out);
+            verifyResultsSincosHalfHalfHalf(inV, outCos, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSincosHalfHalfHalf(Allocation inV, Allocation outCos, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOutCos = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOutCos, (short) 42);
+        outCos.copyTo(arrayOutCos);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output outCos: ");
+                        appendVariableToMessage(message, args.outCos);
+                        message.append("\n");
+                        message.append("Actual   output outCos: ");
+                        appendVariableToMessage(message, arrayOutCos[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output outCos (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 1 + j]));
+                        if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSincosHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSincosHalf2Half2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x1b528cc9l, false);
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocOutCos(outCos);
+            script.forEach_testSincosHalf2Half2Half2(inV, out);
+            verifyResultsSincosHalf2Half2Half2(inV, outCos, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCos(outCos);
+            scriptRelaxed.forEach_testSincosHalf2Half2Half2(inV, out);
+            verifyResultsSincosHalf2Half2Half2(inV, outCos, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSincosHalf2Half2Half2(Allocation inV, Allocation outCos, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOutCos = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOutCos, (short) 42);
+        outCos.copyTo(arrayOutCos);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output outCos: ");
+                        appendVariableToMessage(message, args.outCos);
+                        message.append("\n");
+                        message.append("Actual   output outCos: ");
+                        appendVariableToMessage(message, arrayOutCos[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output outCos (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 2 + j]));
+                        if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSincosHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSincosHalf3Half3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x79f19d98l, false);
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocOutCos(outCos);
+            script.forEach_testSincosHalf3Half3Half3(inV, out);
+            verifyResultsSincosHalf3Half3Half3(inV, outCos, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCos(outCos);
+            scriptRelaxed.forEach_testSincosHalf3Half3Half3(inV, out);
+            verifyResultsSincosHalf3Half3Half3(inV, outCos, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSincosHalf3Half3Half3(Allocation inV, Allocation outCos, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOutCos = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOutCos, (short) 42);
+        outCos.copyTo(arrayOutCos);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output outCos: ");
+                        appendVariableToMessage(message, args.outCos);
+                        message.append("\n");
+                        message.append("Actual   output outCos: ");
+                        appendVariableToMessage(message, arrayOutCos[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output outCos (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 4 + j]));
+                        if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSincosHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSincosHalf4Half4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xd890ae67l, false);
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocOutCos(outCos);
+            script.forEach_testSincosHalf4Half4Half4(inV, out);
+            verifyResultsSincosHalf4Half4Half4(inV, outCos, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation outCos = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocOutCos(outCos);
+            scriptRelaxed.forEach_testSincosHalf4Half4Half4(inV, out);
+            verifyResultsSincosHalf4Half4Half4(inV, outCos, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSincosHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSincosHalf4Half4Half4(Allocation inV, Allocation outCos, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOutCos = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOutCos, (short) 42);
+        outCos.copyTo(arrayOutCos);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSincos(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output outCos: ");
+                        appendVariableToMessage(message, args.outCos);
+                        message.append("\n");
+                        message.append("Actual   output outCos: ");
+                        appendVariableToMessage(message, arrayOutCos[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output outCos (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 4 + j]));
+                        if (!args.outCos.couldBe(Float16Utils.convertFloat16ToDouble(arrayOutCos[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSincosHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testSincos() {
         checkSincosFloatFloatFloat();
         checkSincosFloat2Float2Float2();
         checkSincosFloat3Float3Float3();
         checkSincosFloat4Float4Float4();
+        checkSincosHalfHalfHalf();
+        checkSincosHalf2Half2Half2();
+        checkSincosHalf3Half3Half3();
+        checkSincosHalf4Half4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSincos.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSincos.rs
index af5da10..d7b1c67 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSincos.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSincos.rs
@@ -48,3 +48,31 @@
     rsSetElementAt_float4(gAllocOutCos, outCos, x);
     return out;
 }
+
+half __attribute__((kernel)) testSincosHalfHalfHalf(half inV, unsigned int x) {
+    half outCos = 0;
+    half out = sincos(inV, &outCos);
+    rsSetElementAt_half(gAllocOutCos, outCos, x);
+    return out;
+}
+
+half2 __attribute__((kernel)) testSincosHalf2Half2Half2(half2 inV, unsigned int x) {
+    half2 outCos = 0;
+    half2 out = sincos(inV, &outCos);
+    rsSetElementAt_half2(gAllocOutCos, outCos, x);
+    return out;
+}
+
+half3 __attribute__((kernel)) testSincosHalf3Half3Half3(half3 inV, unsigned int x) {
+    half3 outCos = 0;
+    half3 out = sincos(inV, &outCos);
+    rsSetElementAt_half3(gAllocOutCos, outCos, x);
+    return out;
+}
+
+half4 __attribute__((kernel)) testSincosHalf4Half4Half4(half4 inV, unsigned int x) {
+    half4 outCos = 0;
+    half4 out = sincos(inV, &outCos);
+    rsSetElementAt_half4(gAllocOutCos, outCos, x);
+    return out;
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinh.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinh.java
index 8d77970..82105e1 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinh.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinh.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkSinhHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xccb47b43l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testSinhHalfHalf(inV, out);
+            verifyResultsSinhHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testSinhHalfHalf(inV, out);
+            verifyResultsSinhHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinhHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSinhHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSinhHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x2ac5550dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testSinhHalf2Half2(inV, out);
+            verifyResultsSinhHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testSinhHalf2Half2(inV, out);
+            verifyResultsSinhHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinhHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSinhHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSinhHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x89cd1a01l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testSinhHalf3Half3(inV, out);
+            verifyResultsSinhHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testSinhHalf3Half3(inV, out);
+            verifyResultsSinhHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinhHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSinhHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSinhHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xe8d4def5l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testSinhHalf4Half4(inV, out);
+            verifyResultsSinhHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testSinhHalf4Half4(inV, out);
+            verifyResultsSinhHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinhHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinhHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSinh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSinhHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testSinh() {
         checkSinhFloatFloat();
         checkSinhFloat2Float2();
         checkSinhFloat3Float3();
         checkSinhFloat4Float4();
+        checkSinhHalfHalf();
+        checkSinhHalf2Half2();
+        checkSinhHalf3Half3();
+        checkSinhHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinh.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinh.rs
index f6caee3..f3201f2 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinh.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinh.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testSinhFloat4Float4(float4 inV) {
     return sinh(inV);
 }
+
+half __attribute__((kernel)) testSinhHalfHalf(half inV) {
+    return sinh(inV);
+}
+
+half2 __attribute__((kernel)) testSinhHalf2Half2(half2 inV) {
+    return sinh(inV);
+}
+
+half3 __attribute__((kernel)) testSinhHalf3Half3(half3 inV) {
+    return sinh(inV);
+}
+
+half4 __attribute__((kernel)) testSinhHalf4Half4(half4 inV) {
+    return sinh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinpi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinpi.java
index a5d983e..2de4c4c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinpi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinpi.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkSinpiHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x4cee6176l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testSinpiHalfHalf(inV, out);
+            verifyResultsSinpiHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testSinpiHalfHalf(inV, out);
+            verifyResultsSinpiHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinpiHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSinpiHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSinpiHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x4cf4fb68l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testSinpiHalf2Half2(inV, out);
+            verifyResultsSinpiHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testSinpiHalf2Half2(inV, out);
+            verifyResultsSinpiHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinpiHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSinpiHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSinpiHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xabfcc05cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testSinpiHalf3Half3(inV, out);
+            verifyResultsSinpiHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testSinpiHalf3Half3(inV, out);
+            verifyResultsSinpiHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinpiHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSinpiHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSinpiHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xb048550l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testSinpiHalf4Half4(inV, out);
+            verifyResultsSinpiHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testSinpiHalf4Half4(inV, out);
+            verifyResultsSinpiHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSinpiHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSinpiHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSinpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSinpiHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testSinpi() {
         checkSinpiFloatFloat();
         checkSinpiFloat2Float2();
         checkSinpiFloat3Float3();
         checkSinpiFloat4Float4();
+        checkSinpiHalfHalf();
+        checkSinpiHalf2Half2();
+        checkSinpiHalf3Half3();
+        checkSinpiHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinpi.rs
index 446aaba..e391d41 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinpi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSinpi.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testSinpiFloat4Float4(float4 inV) {
     return sinpi(inV);
 }
+
+half __attribute__((kernel)) testSinpiHalfHalf(half inV) {
+    return sinpi(inV);
+}
+
+half2 __attribute__((kernel)) testSinpiHalf2Half2(half2 inV) {
+    return sinpi(inV);
+}
+
+half3 __attribute__((kernel)) testSinpiHalf3Half3(half3 inV) {
+    return sinpi(inV);
+}
+
+half4 __attribute__((kernel)) testSinpiHalf4Half4(half4 inV) {
+    return sinpi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSqrt.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSqrt.java
index e9ac826..c7736c5 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSqrt.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSqrt.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkSqrtHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xa1eee2c3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testSqrtHalfHalf(inV, out);
+            verifyResultsSqrtHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testSqrtHalfHalf(inV, out);
+            verifyResultsSqrtHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSqrtHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSqrtHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSqrtHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x3d9ae08dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testSqrtHalf2Half2(inV, out);
+            verifyResultsSqrtHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testSqrtHalf2Half2(inV, out);
+            verifyResultsSqrtHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSqrtHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSqrtHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSqrtHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x9ca2a581l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testSqrtHalf3Half3(inV, out);
+            verifyResultsSqrtHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testSqrtHalf3Half3(inV, out);
+            verifyResultsSqrtHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSqrtHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSqrtHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkSqrtHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xfbaa6a75l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testSqrtHalf4Half4(inV, out);
+            verifyResultsSqrtHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testSqrtHalf4Half4(inV, out);
+            verifyResultsSqrtHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testSqrtHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsSqrtHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeSqrt(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkSqrtHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testSqrt() {
         checkSqrtFloatFloat();
         checkSqrtFloat2Float2();
         checkSqrtFloat3Float3();
         checkSqrtFloat4Float4();
+        checkSqrtHalfHalf();
+        checkSqrtHalf2Half2();
+        checkSqrtHalf3Half3();
+        checkSqrtHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSqrt.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSqrt.rs
index 3010b0d..84e59cb 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSqrt.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestSqrt.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testSqrtFloat4Float4(float4 inV) {
     return sqrt(inV);
 }
+
+half __attribute__((kernel)) testSqrtHalfHalf(half inV) {
+    return sqrt(inV);
+}
+
+half2 __attribute__((kernel)) testSqrtHalf2Half2(half2 inV) {
+    return sqrt(inV);
+}
+
+half3 __attribute__((kernel)) testSqrtHalf3Half3(half3 inV) {
+    return sqrt(inV);
+}
+
+half4 __attribute__((kernel)) testSqrtHalf4Half4(half4 inV) {
+    return sqrt(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestStep.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestStep.java
index a8e4fb9..55d6bbb 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestStep.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestStep.java
@@ -359,6 +359,350 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalfHalf {
+        public short inEdge;
+        public double inEdgeDouble;
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkStepHalfHalfHalf() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe2c3f577l, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x3240702cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepHalfHalfHalf(inEdge, out);
+            verifyResultsStepHalfHalfHalf(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalfHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepHalfHalfHalf(inEdge, out);
+            verifyResultsStepHalfHalfHalf(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalfHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepHalfHalfHalf(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInEdge = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInEdge, (short) 42);
+        inEdge.copyTo(arrayInEdge);
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inEdge = arrayInEdge[i];
+                args.inEdgeDouble = Float16Utils.convertFloat16ToDouble(args.inEdge);
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inEdge: ");
+                        appendVariableToMessage(message, args.inEdge);
+                        message.append("\n");
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkStepHalfHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkStepHalf2Half2Half2() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xee08afadl, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xba1588del, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepHalf2Half2Half2(inEdge, out);
+            verifyResultsStepHalf2Half2Half2(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalf2Half2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepHalf2Half2Half2(inEdge, out);
+            verifyResultsStepHalf2Half2Half2(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalf2Half2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepHalf2Half2Half2(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInEdge = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInEdge, (short) 42);
+        inEdge.copyTo(arrayInEdge);
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inEdge = arrayInEdge[i * 2 + j];
+                args.inEdgeDouble = Float16Utils.convertFloat16ToDouble(args.inEdge);
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inEdge: ");
+                        appendVariableToMessage(message, args.inEdge);
+                        message.append("\n");
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkStepHalf2Half2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkStepHalf3Half3Half3() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xe1ba008al, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x18b499adl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepHalf3Half3Half3(inEdge, out);
+            verifyResultsStepHalf3Half3Half3(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalf3Half3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepHalf3Half3Half3(inEdge, out);
+            verifyResultsStepHalf3Half3Half3(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalf3Half3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepHalf3Half3Half3(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInEdge = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInEdge, (short) 42);
+        inEdge.copyTo(arrayInEdge);
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inEdge = arrayInEdge[i * 4 + j];
+                args.inEdgeDouble = Float16Utils.convertFloat16ToDouble(args.inEdge);
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inEdge: ");
+                        appendVariableToMessage(message, args.inEdge);
+                        message.append("\n");
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkStepHalf3Half3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkStepHalf4Half4Half4() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xd56b5167l, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x7753aa7cl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepHalf4Half4Half4(inEdge, out);
+            verifyResultsStepHalf4Half4Half4(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalf4Half4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepHalf4Half4Half4(inEdge, out);
+            verifyResultsStepHalf4Half4Half4(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalf4Half4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepHalf4Half4Half4(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInEdge = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInEdge, (short) 42);
+        inEdge.copyTo(arrayInEdge);
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inEdge = arrayInEdge[i * 4 + j];
+                args.inEdgeDouble = Float16Utils.convertFloat16ToDouble(args.inEdge);
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inEdge: ");
+                        appendVariableToMessage(message, args.inEdge);
+                        message.append("\n");
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkStepHalf4Half4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     private void checkStepFloat2FloatFloat2() {
         Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x5b3d8b26l, false);
         Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0xb6d48a21l, false);
@@ -596,6 +940,258 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    private void checkStepHalf2HalfHalf2() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x2f4438d3l, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x2d7ce0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepHalf2HalfHalf2(inEdge, out);
+            verifyResultsStepHalf2HalfHalf2(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalf2HalfHalf2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepHalf2HalfHalf2(inEdge, out);
+            verifyResultsStepHalf2HalfHalf2(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalf2HalfHalf2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepHalf2HalfHalf2(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInEdge = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInEdge, (short) 42);
+        inEdge.copyTo(arrayInEdge);
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inEdge = arrayInEdge[i * 2 + j];
+                args.inEdgeDouble = Float16Utils.convertFloat16ToDouble(args.inEdge);
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inEdge: ");
+                        appendVariableToMessage(message, args.inEdge);
+                        message.append("\n");
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkStepHalf2HalfHalf2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkStepHalf3HalfHalf3() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb3cf71ffl, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xb2c70e84l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepHalf3HalfHalf3(inEdge, out);
+            verifyResultsStepHalf3HalfHalf3(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalf3HalfHalf3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepHalf3HalfHalf3(inEdge, out);
+            verifyResultsStepHalf3HalfHalf3(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalf3HalfHalf3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepHalf3HalfHalf3(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInEdge = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInEdge, (short) 42);
+        inEdge.copyTo(arrayInEdge);
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inEdge = arrayInEdge[i * 4 + j];
+                args.inEdgeDouble = Float16Utils.convertFloat16ToDouble(args.inEdge);
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inEdge: ");
+                        appendVariableToMessage(message, args.inEdge);
+                        message.append("\n");
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkStepHalf3HalfHalf3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkStepHalf4HalfHalf4() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x385aab2bl, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x6560a028l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepHalf4HalfHalf4(inEdge, out);
+            verifyResultsStepHalf4HalfHalf4(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalf4HalfHalf4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepHalf4HalfHalf4(inEdge, out);
+            verifyResultsStepHalf4HalfHalf4(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalf4HalfHalf4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepHalf4HalfHalf4(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInEdge = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInEdge, (short) 42);
+        inEdge.copyTo(arrayInEdge);
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inEdge = arrayInEdge[i * 4 + j];
+                args.inEdgeDouble = Float16Utils.convertFloat16ToDouble(args.inEdge);
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inEdge: ");
+                        appendVariableToMessage(message, args.inEdge);
+                        message.append("\n");
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkStepHalf4HalfHalf4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     private void checkStepFloatFloat2Float2() {
         Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 1, 0x664b1852l, false);
         Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_32, 2, 0x44e2f7c5l, false);
@@ -833,16 +1429,278 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    private void checkStepHalfHalf2Half2() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x915e1ddl, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x9aa13beel, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepHalfHalf2Half2(inEdge, out);
+            verifyResultsStepHalfHalf2Half2(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalfHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepHalfHalf2Half2(inEdge, out);
+            verifyResultsStepHalfHalf2Half2(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalfHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepHalfHalf2Half2(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInEdge = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInEdge, (short) 42);
+        inEdge.copyTo(arrayInEdge);
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inEdge = arrayInEdge[i];
+                args.inEdgeDouble = Float16Utils.convertFloat16ToDouble(args.inEdge);
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inEdge: ");
+                        appendVariableToMessage(message, args.inEdge);
+                        message.append("\n");
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkStepHalfHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkStepHalfHalf3Half3() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x30b71f9l, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xf9a900e2l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepHalfHalf3Half3(inEdge, out);
+            verifyResultsStepHalfHalf3Half3(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalfHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepHalfHalf3Half3(inEdge, out);
+            verifyResultsStepHalfHalf3Half3(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalfHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepHalfHalf3Half3(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInEdge = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInEdge, (short) 42);
+        inEdge.copyTo(arrayInEdge);
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inEdge = arrayInEdge[i];
+                args.inEdgeDouble = Float16Utils.convertFloat16ToDouble(args.inEdge);
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inEdge: ");
+                        appendVariableToMessage(message, args.inEdge);
+                        message.append("\n");
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkStepHalfHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkStepHalfHalf4Half4() {
+        Allocation inEdge = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xfd010215l, false);
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x58b0c5d6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.set_gAllocInV(inV);
+            script.forEach_testStepHalfHalf4Half4(inEdge, out);
+            verifyResultsStepHalfHalf4Half4(inEdge, inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalfHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.set_gAllocInV(inV);
+            scriptRelaxed.forEach_testStepHalfHalf4Half4(inEdge, out);
+            verifyResultsStepHalfHalf4Half4(inEdge, inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testStepHalfHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsStepHalfHalf4Half4(Allocation inEdge, Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInEdge = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInEdge, (short) 42);
+        inEdge.copyTo(arrayInEdge);
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalfHalf args = new ArgumentsHalfHalfHalf();
+                args.inEdge = arrayInEdge[i];
+                args.inEdgeDouble = Float16Utils.convertFloat16ToDouble(args.inEdge);
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeStep(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inEdge: ");
+                        appendVariableToMessage(message, args.inEdge);
+                        message.append("\n");
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkStepHalfHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testStep() {
         checkStepFloatFloatFloat();
         checkStepFloat2Float2Float2();
         checkStepFloat3Float3Float3();
         checkStepFloat4Float4Float4();
+        checkStepHalfHalfHalf();
+        checkStepHalf2Half2Half2();
+        checkStepHalf3Half3Half3();
+        checkStepHalf4Half4Half4();
         checkStepFloat2FloatFloat2();
         checkStepFloat3FloatFloat3();
         checkStepFloat4FloatFloat4();
+        checkStepHalf2HalfHalf2();
+        checkStepHalf3HalfHalf3();
+        checkStepHalf4HalfHalf4();
         checkStepFloatFloat2Float2();
         checkStepFloatFloat3Float3();
         checkStepFloatFloat4Float4();
+        checkStepHalfHalf2Half2();
+        checkStepHalfHalf3Half3();
+        checkStepHalfHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestStep.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestStep.rs
index c3fc4b0..92b874c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestStep.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestStep.rs
@@ -41,6 +41,26 @@
     return step(inEdge, inV);
 }
 
+half __attribute__((kernel)) testStepHalfHalfHalf(half inEdge, unsigned int x) {
+    half inV = rsGetElementAt_half(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+half2 __attribute__((kernel)) testStepHalf2Half2Half2(half2 inEdge, unsigned int x) {
+    half2 inV = rsGetElementAt_half2(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+half3 __attribute__((kernel)) testStepHalf3Half3Half3(half3 inEdge, unsigned int x) {
+    half3 inV = rsGetElementAt_half3(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+half4 __attribute__((kernel)) testStepHalf4Half4Half4(half4 inEdge, unsigned int x) {
+    half4 inV = rsGetElementAt_half4(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);
@@ -56,6 +76,21 @@
     return step(inEdge, inV);
 }
 
+half2 __attribute__((kernel)) testStepHalf2HalfHalf2(half2 inEdge, unsigned int x) {
+    half inV = rsGetElementAt_half(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+half3 __attribute__((kernel)) testStepHalf3HalfHalf3(half3 inEdge, unsigned int x) {
+    half inV = rsGetElementAt_half(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+half4 __attribute__((kernel)) testStepHalf4HalfHalf4(half4 inEdge, unsigned int x) {
+    half inV = rsGetElementAt_half(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);
@@ -70,3 +105,18 @@
     float4 inV = rsGetElementAt_float4(gAllocInV, x);
     return step(inEdge, inV);
 }
+
+half2 __attribute__((kernel)) testStepHalfHalf2Half2(half inEdge, unsigned int x) {
+    half2 inV = rsGetElementAt_half2(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+half3 __attribute__((kernel)) testStepHalfHalf3Half3(half inEdge, unsigned int x) {
+    half3 inV = rsGetElementAt_half3(gAllocInV, x);
+    return step(inEdge, inV);
+}
+
+half4 __attribute__((kernel)) testStepHalfHalf4Half4(half inEdge, unsigned int x) {
+    half4 inV = rsGetElementAt_half4(gAllocInV, x);
+    return step(inEdge, inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTan.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTan.java
index 72f0a0b..de7c016 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTan.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTan.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkTanHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xc3f260ael, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testTanHalfHalf(inV, out);
+            verifyResultsTanHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testTanHalfHalf(inV, out);
+            verifyResultsTanHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTanHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTanHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xe8d356e0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testTanHalf2Half2(inV, out);
+            verifyResultsTanHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testTanHalf2Half2(inV, out);
+            verifyResultsTanHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTanHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTanHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x47db1bd4l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testTanHalf3Half3(inV, out);
+            verifyResultsTanHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testTanHalf3Half3(inV, out);
+            verifyResultsTanHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTanHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTanHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0xa6e2e0c8l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testTanHalf4Half4(inV, out);
+            verifyResultsTanHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testTanHalf4Half4(inV, out);
+            verifyResultsTanHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTan(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTanHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testTan() {
         checkTanFloatFloat();
         checkTanFloat2Float2();
         checkTanFloat3Float3();
         checkTanFloat4Float4();
+        checkTanHalfHalf();
+        checkTanHalf2Half2();
+        checkTanHalf3Half3();
+        checkTanHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTan.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTan.rs
index fcfa15b4..4f99d13 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTan.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTan.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testTanFloat4Float4(float4 inV) {
     return tan(inV);
 }
+
+half __attribute__((kernel)) testTanHalfHalf(half inV) {
+    return tan(inV);
+}
+
+half2 __attribute__((kernel)) testTanHalf2Half2(half2 inV) {
+    return tan(inV);
+}
+
+half3 __attribute__((kernel)) testTanHalf3Half3(half3 inV) {
+    return tan(inV);
+}
+
+half4 __attribute__((kernel)) testTanHalf4Half4(half4 inV) {
+    return tan(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanh.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanh.java
index 7d1e96c..e325ab1 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanh.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanh.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkTanhHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xbe63da34l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testTanhHalfHalf(inV, out);
+            verifyResultsTanhHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testTanhHalfHalf(inV, out);
+            verifyResultsTanhHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanhHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTanhHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTanhHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0xc66a0fb6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testTanhHalf2Half2(inV, out);
+            verifyResultsTanhHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testTanhHalf2Half2(inV, out);
+            verifyResultsTanhHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanhHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTanhHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTanhHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0x2571d4aal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testTanhHalf3Half3(inV, out);
+            verifyResultsTanhHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testTanhHalf3Half3(inV, out);
+            verifyResultsTanhHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanhHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTanhHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTanhHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x8479999el, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testTanhHalf4Half4(inV, out);
+            verifyResultsTanhHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testTanhHalf4Half4(inV, out);
+            verifyResultsTanhHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanhHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanhHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTanh(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTanhHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testTanh() {
         checkTanhFloatFloat();
         checkTanhFloat2Float2();
         checkTanhFloat3Float3();
         checkTanhFloat4Float4();
+        checkTanhHalfHalf();
+        checkTanhHalf2Half2();
+        checkTanhHalf3Half3();
+        checkTanhHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanh.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanh.rs
index 6932963..82643c1 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanh.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanh.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testTanhFloat4Float4(float4 inV) {
     return tanh(inV);
 }
+
+half __attribute__((kernel)) testTanhHalfHalf(half inV) {
+    return tanh(inV);
+}
+
+half2 __attribute__((kernel)) testTanhHalf2Half2(half2 inV) {
+    return tanh(inV);
+}
+
+half3 __attribute__((kernel)) testTanhHalf3Half3(half3 inV) {
+    return tanh(inV);
+}
+
+half4 __attribute__((kernel)) testTanhHalf4Half4(half4 inV) {
+    return tanh(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanpi.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanpi.java
index e5b9af6..0702bc1 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanpi.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanpi.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkTanpiHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xe56353f1l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testTanpiHalfHalf(inV, out);
+            verifyResultsTanpiHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testTanpiHalfHalf(inV, out);
+            verifyResultsTanpiHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanpiHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTanpiHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTanpiHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x71a055cbl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testTanpiHalf2Half2(inV, out);
+            verifyResultsTanpiHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testTanpiHalf2Half2(inV, out);
+            verifyResultsTanpiHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanpiHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTanpiHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTanpiHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xd0a81abfl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testTanpiHalf3Half3(inV, out);
+            verifyResultsTanpiHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testTanpiHalf3Half3(inV, out);
+            verifyResultsTanpiHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanpiHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTanpiHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTanpiHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x2fafdfb3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testTanpiHalf4Half4(inV, out);
+            verifyResultsTanpiHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testTanpiHalf4Half4(inV, out);
+            verifyResultsTanpiHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTanpiHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTanpiHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTanpi(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTanpiHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testTanpi() {
         checkTanpiFloatFloat();
         checkTanpiFloat2Float2();
         checkTanpiFloat3Float3();
         checkTanpiFloat4Float4();
+        checkTanpiHalfHalf();
+        checkTanpiHalf2Half2();
+        checkTanpiHalf3Half3();
+        checkTanpiHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanpi.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanpi.rs
index 509e7fd..ae7701a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanpi.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTanpi.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testTanpiFloat4Float4(float4 inV) {
     return tanpi(inV);
 }
+
+half __attribute__((kernel)) testTanpiHalfHalf(half inV) {
+    return tanpi(inV);
+}
+
+half2 __attribute__((kernel)) testTanpiHalf2Half2(half2 inV) {
+    return tanpi(inV);
+}
+
+half3 __attribute__((kernel)) testTanpiHalf3Half3(half3 inV) {
+    return tanpi(inV);
+}
+
+half4 __attribute__((kernel)) testTanpiHalf4Half4(half4 inV) {
+    return tanpi(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTgamma.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTgamma.java
index fe2b832..4d277f0 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTgamma.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTgamma.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkTgammaHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0xcaee5aa0l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testTgammaHalfHalf(inV, out);
+            verifyResultsTgammaHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testTgammaHalfHalf(inV, out);
+            verifyResultsTgammaHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTgammaHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTgamma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTgammaHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTgammaHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x5ac39bc2l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testTgammaHalf2Half2(inV, out);
+            verifyResultsTgammaHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testTgammaHalf2Half2(inV, out);
+            verifyResultsTgammaHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTgammaHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTgamma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTgammaHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTgammaHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xb9cb60b6l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testTgammaHalf3Half3(inV, out);
+            verifyResultsTgammaHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testTgammaHalf3Half3(inV, out);
+            verifyResultsTgammaHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTgammaHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTgamma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTgammaHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTgammaHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x18d325aal, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testTgammaHalf4Half4(inV, out);
+            verifyResultsTgammaHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testTgammaHalf4Half4(inV, out);
+            verifyResultsTgammaHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTgammaHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTgammaHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTgamma(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTgammaHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testTgamma() {
         checkTgammaFloatFloat();
         checkTgammaFloat2Float2();
         checkTgammaFloat3Float3();
         checkTgammaFloat4Float4();
+        checkTgammaHalfHalf();
+        checkTgammaHalf2Half2();
+        checkTgammaHalf3Half3();
+        checkTgammaHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTgamma.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTgamma.rs
index a7ad412..5455d0c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTgamma.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTgamma.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testTgammaFloat4Float4(float4 inV) {
     return tgamma(inV);
 }
+
+half __attribute__((kernel)) testTgammaHalfHalf(half inV) {
+    return tgamma(inV);
+}
+
+half2 __attribute__((kernel)) testTgammaHalf2Half2(half2 inV) {
+    return tgamma(inV);
+}
+
+half3 __attribute__((kernel)) testTgammaHalf3Half3(half3 inV) {
+    return tgamma(inV);
+}
+
+half4 __attribute__((kernel)) testTgammaHalf4Half4(half4 inV) {
+    return tgamma(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTrunc.java b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTrunc.java
index 6b6075e..0293b96 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTrunc.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTrunc.java
@@ -318,10 +318,312 @@
                 (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
     }
 
+    public class ArgumentsHalfHalf {
+        public short inV;
+        public double inVDouble;
+        public Target.Floaty out;
+    }
+
+    private void checkTruncHalfHalf() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 1, 0x4b4bfcf3l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            script.forEach_testTruncHalfHalf(inV, out);
+            verifyResultsTruncHalfHalf(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncHalfHalf: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 1), INPUTSIZE);
+            scriptRelaxed.forEach_testTruncHalfHalf(inV, out);
+            verifyResultsTruncHalfHalf(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncHalfHalf: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTruncHalfHalf(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 1];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 1 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTrunc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 1 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 1 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTruncHalfHalf" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTruncHalf2Half2() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 2, 0x7f0d053dl, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            script.forEach_testTruncHalf2Half2(inV, out);
+            verifyResultsTruncHalf2Half2(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncHalf2Half2: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 2), INPUTSIZE);
+            scriptRelaxed.forEach_testTruncHalf2Half2(inV, out);
+            verifyResultsTruncHalf2Half2(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncHalf2Half2: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTruncHalf2Half2(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 2];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 2 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 2 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTrunc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 2 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 2 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTruncHalf2Half2" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTruncHalf3Half3() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 3, 0xde14ca31l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            script.forEach_testTruncHalf3Half3(inV, out);
+            verifyResultsTruncHalf3Half3(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncHalf3Half3: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 3), INPUTSIZE);
+            scriptRelaxed.forEach_testTruncHalf3Half3(inV, out);
+            verifyResultsTruncHalf3Half3(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncHalf3Half3: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTruncHalf3Half3(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 3 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTrunc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTruncHalf3Half3" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
+    private void checkTruncHalf4Half4() {
+        Allocation inV = createRandomAllocation(mRS, Element.DataType.FLOAT_16, 4, 0x3d1c8f25l, false);
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            script.forEach_testTruncHalf4Half4(inV, out);
+            verifyResultsTruncHalf4Half4(inV, out, false);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncHalf4Half4: " + e.toString());
+        }
+        try {
+            Allocation out = Allocation.createSized(mRS, getElement(mRS, Element.DataType.FLOAT_16, 4), INPUTSIZE);
+            scriptRelaxed.forEach_testTruncHalf4Half4(inV, out);
+            verifyResultsTruncHalf4Half4(inV, out, true);
+        } catch (Exception e) {
+            throw new RSRuntimeException("RenderScript. Can't invoke forEach_testTruncHalf4Half4: " + e.toString());
+        }
+    }
+
+    private void verifyResultsTruncHalf4Half4(Allocation inV, Allocation out, boolean relaxed) {
+        short[] arrayInV = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayInV, (short) 42);
+        inV.copyTo(arrayInV);
+        short[] arrayOut = new short[INPUTSIZE * 4];
+        Arrays.fill(arrayOut, (short) 42);
+        out.copyTo(arrayOut);
+        StringBuilder message = new StringBuilder();
+        boolean errorFound = false;
+        for (int i = 0; i < INPUTSIZE; i++) {
+            for (int j = 0; j < 4 ; j++) {
+                // Extract the inputs.
+                ArgumentsHalfHalf args = new ArgumentsHalfHalf();
+                args.inV = arrayInV[i * 4 + j];
+                args.inVDouble = Float16Utils.convertFloat16ToDouble(args.inV);
+                // Figure out what the outputs should have been.
+                Target target = new Target(Target.FunctionType.NORMAL, Target.ReturnType.HALF, relaxed);
+                CoreMathVerifier.computeTrunc(args, target);
+                // Validate the outputs.
+                boolean valid = true;
+                if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                    valid = false;
+                }
+                if (!valid) {
+                    if (!errorFound) {
+                        errorFound = true;
+                        message.append("Input inV: ");
+                        appendVariableToMessage(message, args.inV);
+                        message.append("\n");
+                        message.append("Expected output out: ");
+                        appendVariableToMessage(message, args.out);
+                        message.append("\n");
+                        message.append("Actual   output out: ");
+                        appendVariableToMessage(message, arrayOut[i * 4 + j]);
+                        message.append("\n");
+                        message.append("Actual   output out (in double): ");
+                        appendVariableToMessage(message, Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]));
+                        if (!args.out.couldBe(Float16Utils.convertFloat16ToDouble(arrayOut[i * 4 + j]))) {
+                            message.append(" FAIL");
+                        }
+                        message.append("\n");
+                        message.append("Errors at");
+                    }
+                    message.append(" [");
+                    message.append(Integer.toString(i));
+                    message.append(", ");
+                    message.append(Integer.toString(j));
+                    message.append("]");
+                }
+            }
+        }
+        assertFalse("Incorrect output for checkTruncHalf4Half4" +
+                (relaxed ? "_relaxed" : "") + ":\n" + message.toString(), errorFound);
+    }
+
     public void testTrunc() {
         checkTruncFloatFloat();
         checkTruncFloat2Float2();
         checkTruncFloat3Float3();
         checkTruncFloat4Float4();
+        checkTruncHalfHalf();
+        checkTruncHalf2Half2();
+        checkTruncHalf3Half3();
+        checkTruncHalf4Half4();
     }
 }
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTrunc.rs b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTrunc.rs
index 3f3ef0e..7dd6620 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTrunc.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/generated/TestTrunc.rs
@@ -35,3 +35,19 @@
 float4 __attribute__((kernel)) testTruncFloat4Float4(float4 inV) {
     return trunc(inV);
 }
+
+half __attribute__((kernel)) testTruncHalfHalf(half inV) {
+    return trunc(inV);
+}
+
+half2 __attribute__((kernel)) testTruncHalf2Half2(half2 inV) {
+    return trunc(inV);
+}
+
+half3 __attribute__((kernel)) testTruncHalf3Half3(half3 inV) {
+    return trunc(inV);
+}
+
+half4 __attribute__((kernel)) testTruncHalf4Half4(half4 inV) {
+    return trunc(inV);
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/get_allocation.rs b/tests/tests/renderscript/src/android/renderscript/cts/get_allocation.rs
index 01cb47c..ae7d3e6 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/get_allocation.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/get_allocation.rs
@@ -2,7 +2,6 @@
 #pragma rs java_package_name(android.renderscript.cts)
 
 const int* pointer;
-rs_script script;
 rs_allocation alloc_in;
 rs_allocation alloc_out;
 
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs b/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
index 6d7870d..c30cb9c 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/reduce.rs
@@ -75,8 +75,10 @@
 
 static void fMMCombiner(MinAndMax *accum,
                         const MinAndMax *val) {
-  fMMAccumulator(accum, val->min.val, val->min.idx);
-  fMMAccumulator(accum, val->max.val, val->max.idx);
+  if (val->min.val < accum->min.val)
+    accum->min = val->min;
+  if (val->max.val > accum->max.val)
+    accum->max = val->max;
 }
 
 static void fMMOutConverter(int2 *result,
@@ -113,8 +115,8 @@
 
 static void fMMHalfCombiner(MinAndMaxHalf *accum,
                             const MinAndMaxHalf *val) {
-  fMMHalfAccumulator(accum, val->min);
-  fMMHalfAccumulator(accum, val->max);
+  accum->min = fmin(accum->min, val->min);
+  accum->max = fmax(accum->max, val->max);
 }
 
 static void fMMHalfOutConverter(half2 *result,
@@ -190,8 +192,10 @@
 
 static void fMMHalf2Combiner(MinAndMaxHalf2 *accum,
                             const MinAndMaxHalf2 *val) {
-  fMMHalf2Accumulator(accum, val->min);
-  fMMHalf2Accumulator(accum, val->max);
+  accum->min.x = fmin(accum->min.x, val->min.x);
+  accum->min.y = fmin(accum->min.y, val->min.y);
+  accum->max.x = fmax(accum->max.x, val->max.x);
+  accum->max.y = fmax(accum->max.y, val->max.y);
 }
 
 typedef half2 ArrayOf2Half2[2];
@@ -281,19 +285,26 @@
       const float valElt = rsMatrixGet(&val, i, j);
 
       const float minElt = rsMatrixGet(&(*accum)[MPE_Min], i, j);
-      if (valElt < minElt)
-        rsMatrixSet(&(*accum)[MPE_Min], i, j, valElt);
+      rsMatrixSet(&(*accum)[MPE_Min], i, j, fmin(minElt, valElt));
 
       const float maxElt = rsMatrixGet(&(*accum)[MPE_Max], i, j);
-      if (valElt > maxElt)
-        rsMatrixSet(&(*accum)[MPE_Max], i, j, valElt);
+      rsMatrixSet(&(*accum)[MPE_Max], i, j, fmax(maxElt, valElt));
     }
   }
 }
 
 static void fMinMaxMatCombiner(MatrixPair *accum, const MatrixPair *other) {
-  fMinMaxMatAccumulator(accum, (*other)[MPE_Min]);
-  fMinMaxMatAccumulator(accum, (*other)[MPE_Max]);
+  for (int i = 0; i < 2; ++i) {
+    for (int j = 0; j < 2; ++j) {
+      const float minElt = rsMatrixGet(&(*accum)[MPE_Min], i, j);
+      const float minEltOther = rsMatrixGet(&(*other)[MPE_Min], i, j);
+      rsMatrixSet(&(*accum)[MPE_Min], i, j, fmin(minElt, minEltOther));
+
+      const float maxElt = rsMatrixGet(&(*accum)[MPE_Max], i, j);
+      const float maxEltOther = rsMatrixGet(&(*other)[MPE_Max], i, j);
+      rsMatrixSet(&(*accum)[MPE_Max], i, j, fmax(maxElt, maxEltOther));
+    }
+  }
 }
 
 // reduction does not support matrix result, so use array instead
diff --git a/tests/tests/security/Android.mk b/tests/tests/security/Android.mk
index d2899f9..6d728da 100644
--- a/tests/tests/security/Android.mk
+++ b/tests/tests/security/Android.mk
@@ -33,7 +33,6 @@
 		libselinux \
 		libcutils \
 		libcrypto \
-		libstagefright_foundation \
 		libc++ \
 		libbacktrace \
 		libui \
@@ -52,7 +51,8 @@
 		libsync \
 		libcamera_metadata \
 		libspeexresampler \
-		liblzma
+		liblzma \
+		libstagefright_foundation
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)\
                    src/android/security/cts/activity/ISecureRandomService.aidl
diff --git a/tests/tests/security/jni/Android.mk b/tests/tests/security/jni/Android.mk
index f578018..cc182b3 100644
--- a/tests/tests/security/jni/Android.mk
+++ b/tests/tests/security/jni/Android.mk
@@ -35,7 +35,6 @@
 		android_security_cts_AudioFlingerBinderTest.cpp \
 		android_security_cts_AudioEffectBinderTest.cpp \
 		android_security_cts_MediaPlayerInfoLeakTest.cpp \
-		android_security_cts_StagefrightFoundationTest.cpp \
 		android_security_cts_GraphicBufferInfoLeakTest.cpp
 
 LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) \
@@ -50,7 +49,6 @@
 		libdl \
 		libcutils \
 		libcrypto \
-		libstagefright_foundation \
 		libc++ \
 		libbacktrace \
 		libui \
@@ -69,7 +67,8 @@
 		libsync \
 		libcamera_metadata \
 		libspeexresampler \
-		liblzma
+		liblzma \
+		libstagefright_foundation
 
 LOCAL_C_INCLUDES += ndk/sources/cpufeatures
 LOCAL_STATIC_LIBRARIES := cpufeatures
diff --git a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
index 072f59e..24c87b1 100644
--- a/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
+++ b/tests/tests/security/jni/CtsSecurityJniOnLoad.cpp
@@ -29,7 +29,6 @@
 extern int register_android_security_cts_EncryptionTest(JNIEnv* env);
 extern int register_android_security_cts_AudioEffectBinderTest(JNIEnv* env);
 extern int register_android_security_cts_MediaPlayerInfoLeakTest(JNIEnv* env);
-extern int register_android_security_cts_StagefrightFoundationTest(JNIEnv* env);
 extern int register_android_security_cts_GraphicBufferInfoLeakTest(JNIEnv* env);
 
 jint JNI_OnLoad(JavaVM *vm, void *reserved) {
@@ -91,10 +90,6 @@
         return JNI_ERR;
     }
 
-    if (register_android_security_cts_StagefrightFoundationTest(env)) {
-        return JNI_ERR;
-    }
-
     if (register_android_security_cts_GraphicBufferInfoLeakTest(env)) {
         return JNI_ERR;
     }
diff --git a/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp b/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp
deleted file mode 100644
index d16bd38..0000000
--- a/tests/tests/security/jni/android_security_cts_StagefrightFoundationTest.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "AudioEffectBinderTest-JNI"
-
-#include <cstdio>
-#include <jni.h>
-#include <binder/Parcel.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-using namespace android;
-
-/*
- * Native methods used by
- * cts/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
- */
-
-static jboolean android_security_cts_StagefrightFoundation_test_aMessageFromParcel(
-        JNIEnv* env __unused, jobject thiz __unused)
-{
-    const int kMaxNumItems = 64;
-    const int kNumItems = kMaxNumItems + 1 + 1000;
-    char name[128];
-
-    Parcel data;
-    data.writeInt32(0);  // what
-    data.writeInt32(kNumItems);  // numItems
-    for (int i = 0; i < kMaxNumItems; ++i) {
-        snprintf(name, sizeof(name), "item-%d", i);
-        data.writeCString(name);  // name
-        data.writeInt32(0);  // kTypeInt32
-        data.writeInt32(i);  // value
-    }
-    data.writeCString("evil");  // name
-    data.writeInt32(0);  // kTypeInt32
-    data.writeInt32(0);  // value
-    // NOTE: This could overwrite mNumItems!
-
-    for (int i = 0; i < 1000; ++i) {
-        snprintf(name, sizeof(name), "evil-%d", i);
-        data.writeCString(name);  // name
-        data.writeInt32(0);  // kTypeInt32
-        data.writeInt32(0);  // value
-    }
-
-    data.setDataPosition(0);
-    sp<AMessage> msg = AMessage::FromParcel(data);
-
-    for (int i = 0; i < kMaxNumItems; ++i) {
-        snprintf(name, sizeof(name), "item-%d", i);
-        int32_t value;
-        if (!msg->findInt32(name, &value)) {
-            ALOGE("cannot find value for %s", name);
-            return JNI_FALSE;
-        }
-        if (value != i) {
-            ALOGE("value is changed: expected %d actual %d", i, value);
-            return JNI_FALSE;
-        }
-    }
-    return JNI_TRUE;
-}
-
-int register_android_security_cts_StagefrightFoundationTest(JNIEnv *env)
-{
-    static JNINativeMethod methods[] = {
-        { "native_test_aMessageFromParcel", "()Z",
-                (void *) android_security_cts_StagefrightFoundation_test_aMessageFromParcel},
-    };
-
-    jclass clazz = env->FindClass("android/security/cts/StagefrightFoundationTest");
-    return env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]));
-}
diff --git a/tests/tests/security/src/android/security/cts/BrowserTest.java b/tests/tests/security/src/android/security/cts/BrowserTest.java
index 223f83f..0948713 100644
--- a/tests/tests/security/src/android/security/cts/BrowserTest.java
+++ b/tests/tests/security/src/android/security/cts/BrowserTest.java
@@ -16,23 +16,22 @@
 
 package android.security.cts;
 
-import android.content.ComponentName;
-import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
+import android.os.StrictMode;
 import android.test.AndroidTestCase;
 import android.webkit.cts.CtsTestServer;
 
+import org.apache.http.HttpEntity;
+
+import java.io.File;
 import java.io.FileOutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
 
-import org.apache.http.HttpEntity;
 /**
  * Test file for browser security issues.
  */
@@ -138,6 +137,8 @@
      * See Bug 6212665 for detailed information about this issue.
      */
     public void testBrowserPrivateDataAccess() throws Throwable {
+        // Yucky workaround to let us launch file:// Uris
+        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().build());
 
         // Create a list of all intents for http display. This includes all browsers.
         List<Intent> intents = createAllIntents(Uri.parse("http://www.google.com"));
@@ -146,8 +147,10 @@
         for (Intent intent : intents) {
             // reset state
             mWebServer.resetRequestState();
+
             // define target file, which is supposedly protected from this app
-            String targetFile = "file://" + getTargetFilePath();
+            final File secretFile = exposeFile(stageFile("target.txt", "SECRETS!"));
+
             String html =
                 "<html><body>\n" +
                 "  <form name=\"myform\" action=" + action + " method=\"post\">\n" +
@@ -155,7 +158,7 @@
                 "  <a href=\"javascript :submitform()\">Search</a></form>\n" +
                 "<script>\n" +
                 "  var client = new XMLHttpRequest();\n" +
-                "  client.open('GET', '" + targetFile + "');\n" +
+                "  client.open('GET', '" + Uri.fromFile(secretFile) + "');\n" +
                 "  client.onreadystatechange = function() {\n" +
                 "  if(client.readyState == 4) {\n" +
                 "    myform.val.value = client.responseText;\n" +
@@ -163,20 +166,14 @@
                 "  }}\n" +
                 "  client.send();\n" +
                 "</script></body></html>\n";
-            String filename = "jsfileaccess.html";
-            // create a local HTML to access protected file
-            FileOutputStream out = mContext.openFileOutput(filename,
-                                                           mContext.MODE_WORLD_READABLE);
-            Writer writer = new OutputStreamWriter(out, "UTF-8");
-            writer.write(html);
-            writer.flush();
-            writer.close();
 
-            String filepath = mContext.getFileStreamPath(filename).getAbsolutePath();
-            Uri uri = Uri.parse("file://" + filepath);
+            // create a local HTML to access protected file
+            final File htmlFile = exposeFile(stageFile("jsfileaccess.html", html));
+
             // do a file request
-            intent.setData(uri);
+            intent.setData(Uri.fromFile(htmlFile));
             mContext.startActivity(intent);
+
             /*
              * Wait 5 seconds for the browser to contact the server, but
              * fail fast if we detect the bug
@@ -199,14 +196,26 @@
         }
     }
 
-    private String getTargetFilePath() throws Exception {
-        FileOutputStream out = mContext.openFileOutput("target.txt",
-                                                       mContext.MODE_WORLD_READABLE);
-        Writer writer = new OutputStreamWriter(out, "UTF-8");
-        writer.write("testing");
-        writer.flush();
-        writer.close();
-        return mContext.getFileStreamPath("target.txt").getAbsolutePath();
+    private File stageFile(String name, String contents) throws Exception {
+        final File file = mContext.getFileStreamPath(name);
+        try (FileOutputStream out = new FileOutputStream(file)) {
+            out.write(contents.getBytes(StandardCharsets.UTF_8));
+        }
+        return file;
+    }
+
+    private File exposeFile(File file) throws Exception {
+        file.setReadable(true, false);
+        file.setReadable(true, true);
+
+        File dir = file.getParentFile();
+        do {
+            dir.setExecutable(true, false);
+            dir.setExecutable(true, true);
+            dir = dir.getParentFile();
+        } while (dir != null);
+
+        return file;
     }
 
     /**
diff --git a/tests/tests/security/src/android/security/cts/CertificateTest.java b/tests/tests/security/src/android/security/cts/CertificateTest.java
index 3db7aca..5d2a04f 100644
--- a/tests/tests/security/src/android/security/cts/CertificateTest.java
+++ b/tests/tests/security/src/android/security/cts/CertificateTest.java
@@ -16,19 +16,13 @@
 
 package android.security.cts;
 
-import android.content.res.AssetManager;
-import android.test.InstrumentationTestCase;
-
-import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.Collections;
@@ -36,7 +30,9 @@
 import java.util.List;
 import java.util.Set;
 
-public class CertificateTest extends InstrumentationTestCase {
+import junit.framework.TestCase;
+
+public class CertificateTest extends TestCase {
 
     public void testNoRemovedCertificates() throws Exception {
         Set<String> expectedCertificates = new HashSet<String>(
@@ -50,55 +46,25 @@
      * If you fail CTS as a result of adding a root CA that is not part of the Android root CA
      * store, please see the following.
      *
-     * First, this test exists because adding untrustworthy root CAs to a device has a very
-     * significant security impact. In the worst case, adding a rogue CA can permanently compromise
-     * the confidentiality and integrity of your users' network traffic. Because of this risk,
-     * adding new certificates should be done sparingly and as a last resort -- never as a first
-     * response or short term fix. Before attempting to modify this test, please consider whether
-     * adding a new certificate authority is in your users' best interests.
+     * <p>This test exists because adding root CAs to a device has a very significant security
+     * impact. Whoever has access to the signing keys of that CA can compromise secure network
+     * traffic from affected Android devices, putting users at risk.
      *
-     * Second, because the addition of a new root CA by an OEM can have such dire consequences for
-     * so many people it is imperative that it be done transparently and in the open. Any request to
-     * modify the certificate list used by this test must have a corresponding change in AOSP
-     * (one certificate per change) authored by the OEM in question and including:
+     * <p>If you have a CA certificate which needs to be trusted by a particular app/service,
+     * ask the developer of the app/service to modify it to trust this CA (e.g., using Network
+     * Security Config feature). This avoids compromising the security of network traffic of other
+     * apps on the device.
      *
-     *     - the certificate in question:
-     *       - The certificate must be in a file under
-     *         cts/tests/tests/security/assets/oem_cacerts, in PEM (Privacy-enhanced Electronic
-     *         Mail) format, with the textual representation of the certificate following the PEM
-     *         section.
-     *       - The file name must be in the format of <hash>.<n> where "hash" is the subject hash
-     *         produced by:
-     *           openssl x509 -in cert_file -subject_hash -noout
-     *         and the "n" is a unique integer identifier starting at 0 to deal with collisions.
-     *         See OpenSSL's c_rehash manpage for details.
-     *       - cts/tests/tests/security/tools/format_cert.sh helps meet the above requirements.
+     * <p>If you have a CA certificate that you believe should be present on all Android devices,
+     * please file a public bug at https://code.google.com/p/android/issues/entry.
      *
-     *     - information about who created and maintains both the certificate and the corresponding
-     *       keypair.
-     *
-     *     - information about what the certificate is to be used for and why the certificate is
-     *       appropriate for inclusion.
-     *
-     *     - a statement from the OEM indicating that they have sufficient confidence in the
-     *       security of the key, the security practices of the issuer, and the validity of the
-     *       intended use that they believe adding the certificate is not detrimental to the
-     *       security of the user.
-     *
-     * Finally, please note that this is not the usual process for adding root CAs to Android. If
-     * you have a certificate that you believe should be present on all Android devices, please file
-     * a public bug at https://code.google.com/p/android/issues/entry or http://b.android.com to
-     * seek resolution.
-     *
-     * For questions, comments, and code reviews please contact security@android.com.
+     * <p>For questions, comments, and code reviews please contact security@android.com.
      */
     public void testNoAddedCertificates() throws Exception {
-        Set<String> oemWhitelistedCertificates = getOemWhitelistedCertificates();
         Set<String> expectedCertificates = new HashSet<String>(
                 Arrays.asList(CertificateData.CERTIFICATE_DATA));
         Set<String> deviceCertificates = getDeviceCertificates();
         deviceCertificates.removeAll(expectedCertificates);
-        deviceCertificates.removeAll(oemWhitelistedCertificates);
         assertEquals("Unknown CA certificates", Collections.EMPTY_SET, deviceCertificates);
     }
 
@@ -132,30 +98,6 @@
         return certificates;
     }
 
-    private static final String ASSETS_DIR_OEM_CERTS = "oem_cacerts";
-
-    private Set<String> getOemWhitelistedCertificates() throws Exception {
-        Set<String> certificates = new HashSet<String>();
-        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
-        AssetManager assetManager = getInstrumentation().getContext().getAssets();
-        for (String path : assetManager.list(ASSETS_DIR_OEM_CERTS)) {
-            File certAssetFile = new File(ASSETS_DIR_OEM_CERTS, path);
-            InputStream in = null;
-            try {
-                in = assetManager.open(certAssetFile.toString());
-                X509Certificate certificate = (X509Certificate) certFactory.generateCertificate(in);
-                certificates.add(getFingerprint(certificate));
-            } catch (Exception e) {
-                throw new Exception("Failed to load certificate from asset: " + certAssetFile, e);
-            } finally {
-                if (in != null) {
-                    in.close();
-                }
-            }
-        }
-        return certificates;
-    }
-
     private String getFingerprint(X509Certificate certificate) throws CertificateEncodingException,
             NoSuchAlgorithmException {
         MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
diff --git a/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java b/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
deleted file mode 100644
index 9999d88..0000000
--- a/tests/tests/security/src/android/security/cts/StagefrightFoundationTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts;
-
-import junit.framework.TestCase;
-
-public class StagefrightFoundationTest extends TestCase {
-
-    static {
-        System.loadLibrary("ctssecurity_jni");
-    }
-
-    /**
-     * Checks that IEffect::command() cannot leak data.
-     */
-    public void test_aMessageFromParcel() throws Exception {
-        assertTrue(native_test_aMessageFromParcel());
-    }
-
-    private static native boolean native_test_aMessageFromParcel();
-}
diff --git a/tests/tests/text/AndroidManifest.xml b/tests/tests/text/AndroidManifest.xml
index 27bab8d..1ff9b4f 100644
--- a/tests/tests/text/AndroidManifest.xml
+++ b/tests/tests/text/AndroidManifest.xml
@@ -34,7 +34,9 @@
 
         <activity android:name="android.text.method.cts.KeyListenerCtsActivity"
             android:label="KeyListenerCtsActivity"
-            android:screenOrientation="nosensor"/>
+            android:screenOrientation="nosensor"
+            android:windowSoftInputMode="stateAlwaysHidden"
+        />
 
         <activity android:name="android.text.method.cts.CtsActivity"
             android:label="CtsActivity"
diff --git a/tests/tests/text/src/android/text/cts/BoringLayoutTest.java b/tests/tests/text/src/android/text/cts/BoringLayoutTest.java
index 714fc33..36d2f93 100644
--- a/tests/tests/text/src/android/text/cts/BoringLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/BoringLayoutTest.java
@@ -22,6 +22,7 @@
 import android.graphics.Bitmap.Config;
 import android.test.AndroidTestCase;
 import android.text.BoringLayout;
+import android.text.BoringLayout.Metrics;
 import android.text.Layout;
 import android.text.TextPaint;
 import android.text.TextUtils;
@@ -41,7 +42,7 @@
     private static final CharSequence DEFAULT_CHAR_SEQUENCE = "default";
     private static final TextPaint DEFAULT_PAINT = new TextPaint();
     private static final Layout.Alignment DEFAULT_ALIGN = Layout.Alignment.ALIGN_CENTER;
-    private static final BoringLayout.Metrics DEFAULT_METRICS = createMetrics(
+    private static final Metrics DEFAULT_METRICS = createMetrics(
             METRICS_TOP,
             METRICS_ASCENT,
             METRICS_DESCENT,
@@ -216,7 +217,7 @@
         TextPaint paint = new TextPaint();
         assertNotNull(BoringLayout.isBoring("hello android", paint));
 
-        BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+        Metrics metrics = new Metrics();
         metrics.width = 100;
         assertNotNull(BoringLayout.isBoring("hello android", paint, metrics));
 
@@ -228,6 +229,31 @@
         assertNull(BoringLayout.isBoring("hello android\n\n\n", paint));
     }
 
+    public void testIsBoring_resetsFontMetrics() {
+        int someInt = 100;
+        String text = "some text";
+
+        TextPaint paint = new TextPaint();
+        Paint.FontMetricsInt paintMetrics = paint.getFontMetricsInt();
+        Metrics changedMetrics = new Metrics();
+        changedMetrics.top = paintMetrics.top - someInt;
+        changedMetrics.ascent = paintMetrics.ascent - someInt;
+        changedMetrics.bottom = paintMetrics.bottom + someInt;
+        changedMetrics.descent = paintMetrics.descent + someInt;
+        changedMetrics.leading = paintMetrics.leading + someInt;
+
+        Metrics expectedMetrics = BoringLayout.isBoring(text, paint, (Metrics) null);
+        Metrics actualMetrics = BoringLayout.isBoring(text, paint, changedMetrics);
+
+        assertNotNull(actualMetrics);
+        assertNotNull(expectedMetrics);
+        assertEquals(expectedMetrics.top, actualMetrics.top);
+        assertEquals(expectedMetrics.ascent, actualMetrics.ascent);
+        assertEquals(expectedMetrics.bottom, actualMetrics.bottom);
+        assertEquals(expectedMetrics.descent, actualMetrics.descent);
+        assertEquals(expectedMetrics.leading, actualMetrics.leading);
+    }
+
     public void testGetLineDirections() {
         assertNotNull(mBoringLayout.getLineDirections(0));
         assertNotNull(mBoringLayout.getLineDirections(2));
@@ -288,7 +314,7 @@
         }
     }
 
-    private static BoringLayout.Metrics createMetrics(
+    private static Metrics createMetrics(
             final int top,
             final int ascent,
             final int descent,
@@ -296,7 +322,7 @@
             final int width,
             final int leading) {
 
-        final BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+        final Metrics metrics = new Metrics();
 
         metrics.top = top;
         metrics.ascent = ascent;
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 313d380..ec9c48b 100644
--- a/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
+++ b/tests/tests/text/src/android/text/method/cts/KeyListenerTestCase.java
@@ -21,10 +21,8 @@
 import android.app.Instrumentation;
 import android.test.ActivityInstrumentationTestCase2;
 import android.text.format.DateUtils;
-import android.text.method.cts.KeyListenerCtsActivity;
 import android.text.method.KeyListener;
 import android.view.KeyEvent;
-import android.view.WindowManager;
 import android.widget.EditText;
 
 /**
@@ -71,7 +69,7 @@
                 mTextView.setKeepScreenOn(true);
             }
         });
-
+        mInstrumentation.waitForIdleSync();
         assertTrue(mActivity.waitForWindowFocus(5 * DateUtils.SECOND_IN_MILLIS));
     }
 
diff --git a/tests/tests/view/res/layout/view_layout.xml b/tests/tests/view/res/layout/view_layout.xml
index c576350..df1fae9 100644
--- a/tests/tests/view/res/layout/view_layout.xml
+++ b/tests/tests/view/res/layout/view_layout.xml
@@ -133,4 +133,19 @@
             android:layout_height="10px" />
     </FrameLayout>
 
+    <View
+            android:id="@+id/overlapping_rendering_unset"
+            android:layout_width="10px"
+            android:layout_height="10px" />
+    <View
+            android:id="@+id/overlapping_rendering_false"
+            android:forceHasOverlappingRendering="false"
+            android:layout_width="10px"
+            android:layout_height="10px" />
+    <View
+            android:id="@+id/overlapping_rendering_true"
+            android:forceHasOverlappingRendering="true"
+            android:layout_width="10px"
+            android:layout_height="10px" />
+
 </LinearLayout>
diff --git a/tests/tests/view/src/android/view/cts/KeyboardShortcutGroupTest.java b/tests/tests/view/src/android/view/cts/KeyboardShortcutGroupTest.java
new file mode 100644
index 0000000..067f0bb
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/KeyboardShortcutGroupTest.java
@@ -0,0 +1,97 @@
+package android.view.cts;
+
+import android.os.Parcel;
+import android.test.InstrumentationTestCase;
+import android.view.KeyEvent;
+import android.view.KeyboardShortcutGroup;
+import android.view.KeyboardShortcutInfo;
+
+import com.google.android.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for {@link android.view.KeyboardShortcutGroup}.
+ */
+public class KeyboardShortcutGroupTest extends InstrumentationTestCase {
+    private static final CharSequence TEST_LABEL = "Test Group Label";
+    private final List<KeyboardShortcutInfo> TEST_ITEMS = Lists.newArrayList(
+            new KeyboardShortcutInfo("Item 1", KeyEvent.KEYCODE_U, KeyEvent.META_CTRL_ON),
+            new KeyboardShortcutInfo("Item 2", KeyEvent.KEYCODE_F, KeyEvent.META_CTRL_ON));
+
+    public void testConstructor() {
+        KeyboardShortcutGroup group = new KeyboardShortcutGroup(TEST_LABEL, TEST_ITEMS);
+
+        assertEquals(TEST_LABEL, group.getLabel());
+        assertEquals(TEST_ITEMS, group.getItems());
+        assertFalse(group.isSystemGroup());
+        assertEquals(0, group.describeContents());
+    }
+
+    public void testShortConstructor() {
+        KeyboardShortcutGroup group = new KeyboardShortcutGroup(TEST_LABEL);
+
+        assertEquals(TEST_LABEL, group.getLabel());
+        assertNotNull(group.getItems());
+        assertFalse(group.isSystemGroup());
+        assertEquals(0, group.describeContents());
+    }
+
+    public void testSystemConstructor() {
+        KeyboardShortcutGroup group = new KeyboardShortcutGroup(TEST_LABEL, TEST_ITEMS, true);
+
+        assertEquals(TEST_LABEL, group.getLabel());
+        assertEquals(TEST_ITEMS, group.getItems());
+        assertTrue(group.isSystemGroup());
+        assertEquals(0, group.describeContents());
+    }
+
+    public void testSystemShortConstructor() {
+        KeyboardShortcutGroup group = new KeyboardShortcutGroup(TEST_LABEL, true);
+
+        assertEquals(TEST_LABEL, group.getLabel());
+        assertNotNull(group.getItems());
+        assertTrue(group.isSystemGroup());
+        assertEquals(0, group.describeContents());
+    }
+
+    public void testConstructorChecksList() {
+        try {
+            KeyboardShortcutGroup group = new KeyboardShortcutGroup(TEST_LABEL, null);
+        } catch (NullPointerException expected) {
+            return;
+        }
+        fail();
+    }
+
+    public void testAddItem() {
+        KeyboardShortcutGroup group = new KeyboardShortcutGroup(TEST_LABEL, TEST_ITEMS);
+
+        group.addItem(new KeyboardShortcutInfo(
+                "Additional item", KeyEvent.KEYCODE_P, KeyEvent.META_CTRL_ON));
+
+        final int newSize = group.getItems().size();
+        assertEquals(TEST_ITEMS.size() + 1, newSize);
+        assertEquals("Additional item", group.getItems().get(newSize - 1).getLabel());
+    }
+
+    public void testWriteToParcelAndRead() {
+        Parcel dest = Parcel.obtain();
+        KeyboardShortcutGroup group = new KeyboardShortcutGroup(TEST_LABEL, TEST_ITEMS, true);
+        group.writeToParcel(dest, 0);
+
+        dest.setDataPosition(0);
+        KeyboardShortcutGroup result = KeyboardShortcutGroup.CREATOR.createFromParcel(dest);
+
+        assertEquals(TEST_LABEL, result.getLabel());
+        assertEquals(TEST_ITEMS.size(), result.getItems().size());
+        assertEquals(TEST_ITEMS.get(0).getLabel(), result.getItems().get(0).getLabel());
+        assertEquals(TEST_ITEMS.get(1).getLabel(), result.getItems().get(1).getLabel());
+        assertEquals(TEST_ITEMS.get(0).getKeycode(), result.getItems().get(0).getKeycode());
+        assertEquals(TEST_ITEMS.get(1).getKeycode(), result.getItems().get(1).getKeycode());
+        assertEquals(TEST_ITEMS.get(0).getModifiers(), result.getItems().get(0).getModifiers());
+        assertEquals(TEST_ITEMS.get(1).getModifiers(), result.getItems().get(1).getModifiers());
+        assertTrue(result.isSystemGroup());
+    }
+}
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 2082973..426a20f 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -80,7 +80,6 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
-import android.view.cts.R;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
@@ -4014,7 +4013,40 @@
         assertTrue(mv.getLastAggregatedVisibility());
     }
 
-    private void setVisibilityOnUiThread(final View view, int visibility) throws Throwable {
+    public void testOverlappingRendering() {
+        View overlappingUnsetView = mActivity.findViewById(R.id.overlapping_rendering_unset);
+        View overlappingFalseView = mActivity.findViewById(R.id.overlapping_rendering_false);
+        View overlappingTrueView = mActivity.findViewById(R.id.overlapping_rendering_true);
+
+        assertTrue(overlappingUnsetView.hasOverlappingRendering());
+        assertTrue(overlappingUnsetView.getHasOverlappingRendering());
+        overlappingUnsetView.forceHasOverlappingRendering(false);
+        assertTrue(overlappingUnsetView.hasOverlappingRendering());
+        assertFalse(overlappingUnsetView.getHasOverlappingRendering());
+        overlappingUnsetView.forceHasOverlappingRendering(true);
+        assertTrue(overlappingUnsetView.hasOverlappingRendering());
+        assertTrue(overlappingUnsetView.getHasOverlappingRendering());
+
+        assertTrue(overlappingTrueView.hasOverlappingRendering());
+        assertTrue(overlappingTrueView.getHasOverlappingRendering());
+
+        assertTrue(overlappingFalseView.hasOverlappingRendering());
+        assertFalse(overlappingFalseView.getHasOverlappingRendering());
+
+        View overridingView = new MockOverlappingRenderingSubclass(mActivity, false);
+        assertFalse(overridingView.hasOverlappingRendering());
+
+        overridingView = new MockOverlappingRenderingSubclass(mActivity, true);
+        assertTrue(overridingView.hasOverlappingRendering());
+        overridingView.forceHasOverlappingRendering(false);
+        assertFalse(overridingView.getHasOverlappingRendering());
+        assertTrue(overridingView.hasOverlappingRendering());
+        overridingView.forceHasOverlappingRendering(true);
+        assertTrue(overridingView.getHasOverlappingRendering());
+        assertTrue(overridingView.hasOverlappingRendering());
+    }
+
+    private void setVisibilityOnUiThread(final View view, final int visibility) throws Throwable {
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -4023,6 +4055,20 @@
         });
     }
 
+    private static class MockOverlappingRenderingSubclass extends View {
+        boolean mOverlap;
+
+        public MockOverlappingRenderingSubclass(Context context, boolean overlap) {
+            super(context);
+            mOverlap = overlap;
+        }
+
+        @Override
+        public boolean hasOverlappingRendering() {
+            return mOverlap;
+        }
+    }
+
     private static class MockViewGroup extends ViewGroup {
         boolean isStartActionModeForChildCalled = false;
         int startActionModeForChildType = ActionMode.TYPE_PRIMARY;
diff --git a/tests/tests/view/src/android/view/cts/WindowTest.java b/tests/tests/view/src/android/view/cts/WindowTest.java
index bfeb137..439eda5 100644
--- a/tests/tests/view/src/android/view/cts/WindowTest.java
+++ b/tests/tests/view/src/android/view/cts/WindowTest.java
@@ -1046,7 +1046,7 @@
         }
 
         @Override
-        public void onMultiWindowChanged() {
+        public void onMultiWindowModeChanged() {
         }
 
         @Override
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 b939346..1ddfd2b 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputConnectionWrapperTest.java
@@ -89,6 +89,8 @@
         assertTrue(inputConnection.isSetComposingRegionCalled);
         wrapper.requestCursorUpdates(InputConnection.CURSOR_UPDATE_IMMEDIATE);
         assertTrue(inputConnection.isRequestCursorUpdatesCalled);
+        wrapper.closeConnection();
+        assertTrue(inputConnection.isCloseConnectionCalled);
         assertFalse(inputConnection.isGetHandlerCalled);
         assertNull(inputConnection.getHandler());
         assertTrue(inputConnection.isGetHandlerCalled);
@@ -119,6 +121,7 @@
         public boolean isSetSelectionCalled;
         public boolean isRequestCursorUpdatesCalled;
         public boolean isGetHandlerCalled;
+        public boolean isCloseConnectionCalled;
 
         public boolean beginBatchEdit() {
             isBeginBatchEditCalled = true;
@@ -239,5 +242,9 @@
             isGetHandlerCalled = true;
             return null;
         }
+
+        public void closeConnection() {
+            isCloseConnectionCalled = true;
+        }
     }
 }
diff --git a/tests/tests/widget/res/drawable-xxhdpi/ic_search.png b/tests/tests/widget/res/drawable-xxhdpi/ic_search.png
new file mode 100644
index 0000000..3ae490e
--- /dev/null
+++ b/tests/tests/widget/res/drawable-xxhdpi/ic_search.png
Binary files differ
diff --git a/tests/tests/widget/res/menu/toolbar_menu_search.xml b/tests/tests/widget/res/menu/toolbar_menu_search.xml
new file mode 100644
index 0000000..2321554
--- /dev/null
+++ b/tests/tests/widget/res/menu/toolbar_menu_search.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 Google Inc.
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/action_search"
+          android:title="@string/popup_menu_search"
+          android:icon="@drawable/ic_search"
+          android:showAsAction="always|collapseActionView"
+          android:actionViewClass="android.widget.SearchView" />
+</menu>
diff --git a/tests/tests/widget/res/values/strings.xml b/tests/tests/widget/res/values/strings.xml
index 303da53..63ceffa 100644
--- a/tests/tests/widget/res/values/strings.xml
+++ b/tests/tests/widget/res/values/strings.xml
@@ -187,7 +187,10 @@
     <string name="popup_menu_share_email">Via email</string>
     <string name="popup_menu_share_circles">To my circles</string>
     <string name="popup_menu_print">Print</string>
+    <string name="popup_menu_search">Search</string>
 
     <string name="toolbar_title">Toolbar title</string>
     <string name="toolbar_subtitle">Toolbar subtitle</string>
+    <string name="toolbar_navigation">Toolbar navigation</string>
+    <string name="toolbar_logo">Toolbar logo</string>
 </resources>
diff --git a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
index 1149d3b..afdc869 100644
--- a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewTest.java
@@ -16,6 +16,7 @@
 
 package android.widget.cts;
 
+import android.widget.FrameLayout;
 import android.widget.cts.R;
 
 
@@ -30,14 +31,14 @@
 import android.test.UiThreadTest;
 import android.util.AttributeSet;
 import android.util.Xml;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.View.MeasureSpec;
-import android.view.ViewGroup.LayoutParams;
 import android.widget.HorizontalScrollView;
 import android.widget.TextView;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 
 /**
  * Test {@link HorizontalScrollView}.
@@ -332,6 +333,182 @@
         assertEquals(30, child.getMeasuredWidth());
     }
 
+    public void testMeasureSpecs() {
+        MyView child = spy(new MyView(mActivity));
+        MyHorizontalScrollView scrollView = new MyHorizontalScrollView(mActivity);
+        scrollView.addView(child);
+
+        scrollView.measureChild(child, MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY));
+        verify(child).onMeasure(
+                eq(MeasureSpec.makeMeasureSpec(100, MeasureSpec.UNSPECIFIED)),
+                eq(MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY)));
+    }
+
+    public void testMeasureSpecsWithPadding() {
+        MyView child = spy(new MyView(mActivity));
+        MyHorizontalScrollView scrollView = new MyHorizontalScrollView(mActivity);
+        scrollView.setPadding(3, 5, 7, 11);
+        scrollView.addView(child);
+
+        scrollView.measureChild(child, MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY));
+        verify(child).onMeasure(
+                eq(MeasureSpec.makeMeasureSpec(90, MeasureSpec.UNSPECIFIED)),
+                eq(MeasureSpec.makeMeasureSpec(134, MeasureSpec.EXACTLY)));
+    }
+
+    public void testMeasureSpecsWithMargins() {
+        MyView child = spy(new MyView(mActivity));
+        MyHorizontalScrollView scrollView = new MyHorizontalScrollView(mActivity);
+        scrollView.addView(child);
+
+        scrollView.measureChildWithMargins(child,
+                MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 15,
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY), 20);
+        verify(child).onMeasure(
+                eq(MeasureSpec.makeMeasureSpec(85, MeasureSpec.UNSPECIFIED)),
+                eq(MeasureSpec.makeMeasureSpec(130, MeasureSpec.EXACTLY)));
+    }
+
+    public void testMeasureSpecsWithMarginsAndPadding() {
+        MyView child = spy(new MyView(mActivity));
+        MyHorizontalScrollView scrollView = new MyHorizontalScrollView(mActivity);
+        scrollView.setPadding(3, 5, 7, 11);
+        scrollView.addView(child);
+
+        scrollView.measureChildWithMargins(child,
+                MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 15,
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY), 20);
+        verify(child).onMeasure(
+                eq(MeasureSpec.makeMeasureSpec(75, MeasureSpec.UNSPECIFIED)),
+                eq(MeasureSpec.makeMeasureSpec(114, MeasureSpec.EXACTLY)));
+    }
+
+    public void testMeasureSpecsWithMarginsAndNoHintWidth() {
+        MyView child = spy(new MyView(mActivity));
+        MyHorizontalScrollView scrollView = new MyHorizontalScrollView(mActivity);
+        scrollView.addView(child);
+
+        scrollView.measureChildWithMargins(child,
+                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 15,
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY), 20);
+        verify(child).onMeasure(
+                eq(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)),
+                eq(MeasureSpec.makeMeasureSpec(130, MeasureSpec.EXACTLY)));
+    }
+
+    public void testFillViewport() {
+        MyHorizontalScrollView scrollView = new MyHorizontalScrollView(mActivity);
+
+        MyView child = new MyView(mActivity);
+        scrollView.setFillViewport(true);
+        child.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT
+        ));
+
+        scrollView.addView(child);
+        scrollView.measure(MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY));
+
+        assertEquals(150, child.getMeasuredWidth());
+        assertEquals(100, child.getMeasuredHeight());
+
+        scrollView.layout(0, 0, 150, 100);
+        assertEquals(0, child.getLeft());
+    }
+
+    public void testFillViewportWithScrollViewPadding() {
+        MyHorizontalScrollView scrollView = new MyHorizontalScrollView(mActivity);
+        scrollView.setFillViewport(true);
+        scrollView.setPadding(3, 10, 5, 7);
+
+        MyView child = new MyView(mActivity);
+        child.setLayoutParams(new ViewGroup.LayoutParams(10,10));
+        child.setDesiredWidth(30);
+
+        scrollView.addView(child);
+        scrollView.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY));
+
+        assertEquals(92, child.getMeasuredWidth());
+        assertEquals(10, child.getMeasuredHeight());
+
+        scrollView.layout(0, 0, 100, 150);
+        assertEquals(3, child.getLeft());
+    }
+
+    public void testFillViewportWithChildMargins() {
+        MyHorizontalScrollView scrollView = new MyHorizontalScrollView(mActivity);
+        scrollView.setFillViewport(true);
+
+        MyView child = new MyView(mActivity);
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(10, 10);
+        lp.leftMargin = 3;
+        lp.topMargin = 10;
+        lp.rightMargin = 5;
+        lp.bottomMargin = 7;
+        child.setDesiredWidth(30);
+        child.setLayoutParams(lp);
+
+        scrollView.addView(child);
+        scrollView.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY));
+
+        assertEquals(92, child.getMeasuredWidth());
+        assertEquals(10, child.getMeasuredHeight());
+
+        scrollView.layout(0, 0, 100, 150);
+        assertEquals(3, child.getLeft());
+    }
+
+    public void testFillViewportWithScrollViewPaddingAlreadyFills() {
+        MyHorizontalScrollView scrollView = new MyHorizontalScrollView(mActivity);
+        scrollView.setFillViewport(true);
+        scrollView.setPadding(3, 10, 5, 7);
+
+        MyView child = new MyView(mActivity);
+        child.setDesiredWidth(175);
+
+        scrollView.addView(child);
+        scrollView.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY));
+
+
+        assertEquals(175, child.getMeasuredWidth());
+        assertEquals(133, child.getMeasuredHeight());
+
+        scrollView.layout(0, 0, 100, 150);
+        assertEquals(3, child.getLeft());
+    }
+
+    public void testFillViewportWithChildMarginsAlreadyFills() {
+        MyHorizontalScrollView scrollView = new MyHorizontalScrollView(mActivity);
+        scrollView.setFillViewport(true);
+        MyView child = new MyView(mActivity);
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+
+        lp.leftMargin = 3;
+        lp.topMargin = 10;
+        lp.rightMargin = 5;
+        lp.bottomMargin = 7;
+        child.setLayoutParams(lp);
+        child.setDesiredWidth(175);
+
+        scrollView.addView(child);
+        scrollView.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY));
+
+        assertEquals(175, child.getMeasuredWidth());
+        assertEquals(133, child.getMeasuredHeight());
+
+        scrollView.layout(0, 0, 100, 150);
+        assertEquals(3, child.getLeft());
+    }
+
     @UiThreadTest
     public void testPageScroll() {
         mScrollView.setSmoothScrollingEnabled(false);
@@ -462,9 +639,9 @@
         assertTrue(mScrollView.getChildCount() > 0);
         assertEquals(ITEM_WIDTH * ITEM_COUNT, mScrollView.computeHorizontalScrollRange());
 
-        MyScrollView myScrollView = new MyScrollView(mActivity);
-        assertEquals(0, myScrollView.getChildCount());
-        assertEquals(0, myScrollView.computeVerticalScrollRange());
+        MyHorizontalScrollView scrollView = new MyHorizontalScrollView(mActivity);
+        assertEquals(0, scrollView.getChildCount());
+        assertEquals(0, scrollView.computeHorizontalScrollRange());
     }
 
     @UiThreadTest
@@ -564,7 +741,7 @@
         assertTrue(mScrollView.getRightFadingEdgeStrength() <= 1.0f);
         assertTrue(mScrollView.getRightFadingEdgeStrength() >= 0.0f);
 
-        MyScrollView myScrollView = new MyScrollView(mActivity);
+        MyHorizontalScrollView myScrollView = new MyHorizontalScrollView(mActivity);
         assertEquals(0, myScrollView.getChildCount());
         assertTrue(mScrollView.getLeftFadingEdgeStrength() <= 1.0f);
         assertTrue(mScrollView.getLeftFadingEdgeStrength() >= 0.0f);
@@ -674,9 +851,31 @@
         }.run();
     }
 
-    private static class MyView extends View {
+    public static class MyView extends View {
+        // measure in this height if set
+        private Integer mDesiredWidth;
         public MyView(Context context) {
             super(context);
         }
+
+        public void setDesiredWidth(Integer desiredWidth) {
+            mDesiredWidth = desiredWidth;
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            if (mDesiredWidth != null) {
+                int mode = MeasureSpec.getMode(widthMeasureSpec);
+                int size = MeasureSpec.getSize(widthMeasureSpec);
+                int newWidth = size;
+                if (mode == MeasureSpec.AT_MOST) {
+                    newWidth = Math.max(size, mDesiredWidth);
+                } else if (mode == MeasureSpec.UNSPECIFIED) {
+                    newWidth = mDesiredWidth;
+                }
+                setMeasuredDimension(newWidth, getMeasuredHeight());
+            }
+        }
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/MyHorizontalScrollView.java b/tests/tests/widget/src/android/widget/cts/MyHorizontalScrollView.java
index 639193a..a5a0150 100644
--- a/tests/tests/widget/src/android/widget/cts/MyHorizontalScrollView.java
+++ b/tests/tests/widget/src/android/widget/cts/MyHorizontalScrollView.java
@@ -67,4 +67,19 @@
         super.measureChildWithMargins(child, parentWidthMeasureSpec,
                 widthUsed, parentHeightMeasureSpec, heightUsed);
     }
+
+    @Override
+    public int computeVerticalScrollRange() {
+        return super.computeVerticalScrollRange();
+    }
+
+    @Override
+    public int computeVerticalScrollOffset() {
+        return super.computeVerticalScrollOffset();
+    }
+
+    @Override
+    public int computeVerticalScrollExtent() {
+        return super.computeVerticalScrollExtent();
+    }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
index 2d58263..3054bab 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupMenuTest.java
@@ -246,8 +246,10 @@
 
         runTestOnUiThread(() -> mPopupMenu.getMenu().performIdentifierAction(R.id.action_share, 0));
         // Verify that our menu item click listener has been called on "share" action
+        // and that the dismiss listener hasn't been called just as a result of opening the submenu.
         verify(mBuilder.mOnMenuItemClickListener, times(1)).onMenuItemClick(
                 mPopupMenu.getMenu().findItem(R.id.action_share));
+        verify(mBuilder.mOnDismissListener, never()).onDismiss(mPopupMenu);
 
         runTestOnUiThread(() -> mPopupMenu.getMenu().findItem(R.id.action_share).getSubMenu().
                         performIdentifierAction(R.id.action_share_email, 0));
@@ -358,4 +360,4 @@
             mPopupMenu.show();
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
index 7f5f6e7..658307a 100644
--- a/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/PopupWindowTest.java
@@ -16,11 +16,6 @@
 
 package android.widget.cts;
 
-import static org.mockito.Mockito.*;
-
-import android.util.AttributeSet;
-import org.mockito.InOrder;
-
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
@@ -33,6 +28,7 @@
 import android.transition.Transition;
 import android.transition.Transition.TransitionListener;
 import android.transition.TransitionValues;
+import android.util.AttributeSet;
 import android.view.Display;
 import android.view.Gravity;
 import android.view.MotionEvent;
@@ -42,12 +38,18 @@
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
 import android.widget.ImageView;
-import android.widget.PopupWindow.OnDismissListener;
 import android.widget.PopupWindow;
+import android.widget.PopupWindow.OnDismissListener;
 import android.widget.TextView;
-
 import android.widget.cts.R;
 
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
 public class PopupWindowTest extends
         ActivityInstrumentationTestCase2<MockPopupWindowCtsActivity> {
     private Instrumentation mInstrumentation;
@@ -166,6 +168,7 @@
 
         // This constructor is needed for reflection-based creation of a transition when
         // the transition is defined in layout XML via attribute.
+        @SuppressWarnings("unused")
         public CustomTransition(Context context, AttributeSet attrs) {
             super(context, attrs);
         }
@@ -301,11 +304,7 @@
         mPopupWindow = createPopupWindow(createPopupContent());
         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.showAsDropDown(upperAnchor);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(upperAnchor));
         mInstrumentation.waitForIdleSync();
 
         assertTrue(mPopupWindow.isShowing());
@@ -336,11 +335,8 @@
         assertEquals(0, popupContentViewInWindowXY[0]);
         assertEquals(0, popupContentViewInWindowXY[1]);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.showAtLocation(upperAnchor, Gravity.NO_GRAVITY, xOff, yOff);
-            }
-        });
+        mInstrumentation.runOnMainSync(
+                () -> mPopupWindow.showAtLocation(upperAnchor, Gravity.NO_GRAVITY, xOff, yOff));
         mInstrumentation.waitForIdleSync();
 
         assertTrue(mPopupWindow.isShowing());
@@ -367,11 +363,7 @@
         final int xOff = 11;
         final int yOff = 12;
 
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.showAsDropDown(upperAnchor, xOff, yOff);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(upperAnchor, xOff, yOff));
         mInstrumentation.waitForIdleSync();
 
         mPopupWindow.getContentView().getLocationOnScreen(viewOnScreenXY);
@@ -395,11 +387,7 @@
         mPopupWindow.setOverlapAnchor(true);
         assertTrue(mPopupWindow.getOverlapAnchor());
 
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.showAsDropDown(upperAnchor, 0, 0);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(upperAnchor, 0, 0));
         mInstrumentation.waitForIdleSync();
 
         mPopupWindow.getContentView().getLocationOnScreen(viewOnScreenXY);
@@ -514,11 +502,7 @@
         assertEquals(0, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS & p.flags);
         assertEquals(0, WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM & p.flags);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.update();
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.update());
         mInstrumentation.waitForIdleSync();
 
         assertEquals(WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES,
@@ -554,21 +538,13 @@
         verify(dismissListener, never()).onDismiss();
 
         final View anchorView = mActivity.findViewById(R.id.anchor_upper);
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.showAsDropDown(anchorView, 0, 0);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(anchorView, 0, 0));
         mInstrumentation.waitForIdleSync();
         verify(enterListener, times(1)).onTransitionStart(any(Transition.class));
         verify(exitListener, never()).onTransitionStart(any(Transition.class));
         verify(dismissListener, never()).onDismiss();
 
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.dismiss();
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.dismiss());
         mInstrumentation.waitForIdleSync();
         verify(enterListener, times(1)).onTransitionStart(any(Transition.class));
         verify(exitListener, times(1)).onTransitionStart(any(Transition.class));
@@ -580,13 +556,11 @@
         int[] sndXY = new int[2];
         int[] viewInWindowXY = new int[2];
 
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow = createPopupWindow(createPopupContent());
-                // Do not attach within the decor; we will be measuring location
-                // with regard to screen coordinates.
-                mPopupWindow.setAttachedInDecor(false);
-            }
+        mInstrumentation.runOnMainSync(() -> {
+            mPopupWindow = createPopupWindow(createPopupContent());
+            // Do not attach within the decor; we will be measuring location
+            // with regard to screen coordinates.
+            mPopupWindow.setAttachedInDecor(false);
         });
 
         mInstrumentation.waitForIdleSync();
@@ -599,11 +573,7 @@
         mPopupWindow.getContentView().getLocationInWindow(viewInWindowXY);
 
         // update if it is not shown
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.update(20, 50, 50, 50);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.update(20, 50, 50, 50));
 
         mInstrumentation.waitForIdleSync();
         assertTrue(mPopupWindow.isShowing());
@@ -615,11 +585,7 @@
         assertEquals(viewInWindowXY[1] + 50, fstXY[1]);
 
         // ignore if width or height is -1
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.update(4, 0, -1, -1, true);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.update(4, 0, -1, -1, true));
         mInstrumentation.waitForIdleSync();
 
         assertTrue(mPopupWindow.isShowing());
@@ -634,11 +600,8 @@
     }
 
     public void testUpdateDimensionAndAlignAnchorView() {
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow = createPopupWindow(createPopupContent());
-            }
-        });
+        mInstrumentation.runOnMainSync(
+                () -> mPopupWindow = createPopupWindow(createPopupContent()));
         mInstrumentation.waitForIdleSync();
 
         final View anchorView = mActivity.findViewById(R.id.anchor_upper);
@@ -648,39 +611,23 @@
         assertEquals(100, mPopupWindow.getWidth());
         assertEquals(100, mPopupWindow.getHeight());
 
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.showAsDropDown(anchorView);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(anchorView));
         mInstrumentation.waitForIdleSync();
         // update if it is shown
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.update(anchorView, 50, 50);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> 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
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.update(anchorView, -1, -1);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anchorView, -1, -1));
         mInstrumentation.waitForIdleSync();
         assertTrue(mPopupWindow.isShowing());
         assertEquals(50, mPopupWindow.getWidth());
         assertEquals(50, mPopupWindow.getHeight());
 
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.dismiss();
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.dismiss());
         mInstrumentation.waitForIdleSync();
     }
 
@@ -701,11 +648,7 @@
         mPopupWindow.getContentView().getLocationInWindow(viewInWindowOff);
 
         // update if it is not shown
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.update(anchorView, 20, 50, 50, 50);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anchorView, 20, 50, 50, 50));
 
         mInstrumentation.waitForIdleSync();
 
@@ -720,11 +663,7 @@
         assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
 
         // ignore width and height but change location
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.update(anchorView, 10, 50, -1, -1);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anchorView, 10, 50, -1, -1));
         mInstrumentation.waitForIdleSync();
 
         assertTrue(mPopupWindow.isShowing());
@@ -738,11 +677,7 @@
         assertEquals(anchorXY[1] + anchorView.getHeight() + 50 + viewInWindowOff[1], viewXY[1]);
 
         final View anotherView = mActivity.findViewById(R.id.anchor_middle_left);
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.update(anotherView, 0, 0, 60, 60);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.update(anotherView, 0, 0, 60, 60));
         mInstrumentation.waitForIdleSync();
 
         assertTrue(mPopupWindow.isShowing());
@@ -802,19 +737,11 @@
     }
 
     public void testIsAboveAnchor() {
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow = createPopupWindow(createPopupContent());
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow = createPopupWindow(createPopupContent()));
         mInstrumentation.waitForIdleSync();
         final View upperAnchor = mActivity.findViewById(R.id.anchor_upper);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.showAsDropDown(upperAnchor);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(upperAnchor));
         mInstrumentation.waitForIdleSync();
         assertFalse(mPopupWindow.isAboveAnchor());
         dismissPopup();
@@ -822,11 +749,7 @@
         mPopupWindow = createPopupWindow(createPopupContent());
         final View lowerAnchor = mActivity.findViewById(R.id.anchor_lower);
 
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.showAsDropDown(lowerAnchor, 0, 0);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.showAsDropDown(lowerAnchor, 0, 0));
         mInstrumentation.waitForIdleSync();
         assertTrue(mPopupWindow.isAboveAnchor());
         dismissPopup();
@@ -882,11 +805,7 @@
         assertEquals(0, p.height);
 
         mPopupWindow.setWindowLayoutMode(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                mPopupWindow.update(20, 50, 50, 50);
-            }
-        });
+        mInstrumentation.runOnMainSync(() -> mPopupWindow.update(20, 50, 50, 50));
 
         assertEquals(LayoutParams.WRAP_CONTENT, p.width);
         assertEquals(LayoutParams.MATCH_PARENT, p.height);
@@ -922,27 +841,23 @@
     }
 
     private void showPopup() {
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                if (mPopupWindow == null || mPopupWindow.isShowing()) {
-                    return;
-                }
-                View anchor = mActivity.findViewById(R.id.anchor_upper);
-                mPopupWindow.showAsDropDown(anchor);
-                assertTrue(mPopupWindow.isShowing());
+        mInstrumentation.runOnMainSync(() -> {
+            if (mPopupWindow == null || mPopupWindow.isShowing()) {
+                return;
             }
+            View anchor = mActivity.findViewById(R.id.anchor_upper);
+            mPopupWindow.showAsDropDown(anchor);
+            assertTrue(mPopupWindow.isShowing());
         });
         mInstrumentation.waitForIdleSync();
     }
 
     private void dismissPopup() {
-        mInstrumentation.runOnMainSync(new Runnable() {
-            public void run() {
-                if (mPopupWindow == null || !mPopupWindow.isShowing()) {
-                    return;
-                }
-                mPopupWindow.dismiss();
+        mInstrumentation.runOnMainSync(() -> {
+            if (mPopupWindow == null || !mPopupWindow.isShowing()) {
+                return;
             }
+            mPopupWindow.dismiss();
         });
         mInstrumentation.waitForIdleSync();
     }
diff --git a/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java b/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
index 0119cc0..26510f27 100644
--- a/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ScrollViewTest.java
@@ -16,6 +16,11 @@
 
 package android.widget.cts;
 
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.widget.FrameLayout;
 import android.widget.cts.R;
 
 
@@ -34,7 +39,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.View.MeasureSpec;
-import android.view.ViewGroup.LayoutParams;
 import android.widget.ScrollView;
 import android.widget.TextView;
 
@@ -351,6 +355,179 @@
         assertEquals(100, child.getMeasuredWidth());
     }
 
+    public void testMeasureSpecs() {
+        MyView child = spy(new MyView(mActivity));
+        MyScrollView scrollView = new MyScrollView(mActivity);
+        scrollView.addView(child);
+
+        scrollView.measureChild(child, MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY));
+        verify(child).onMeasure(
+                eq(MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY)),
+                eq(MeasureSpec.makeMeasureSpec(100, MeasureSpec.UNSPECIFIED)));
+    }
+
+    public void testMeasureSpecsWithPadding() {
+        MyView child = spy(new MyView(mActivity));
+        MyScrollView scrollView = new MyScrollView(mActivity);
+        scrollView.setPadding(3, 5, 7, 11);
+        scrollView.addView(child);
+
+        scrollView.measureChild(child, MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY));
+        verify(child).onMeasure(
+                eq(MeasureSpec.makeMeasureSpec(140, MeasureSpec.EXACTLY)),
+                eq(MeasureSpec.makeMeasureSpec(84, MeasureSpec.UNSPECIFIED)));
+    }
+
+    public void testMeasureSpecsWithMargins() {
+        MyView child = spy(new MyView(mActivity));
+        MyScrollView scrollView = new MyScrollView(mActivity);
+        scrollView.addView(child);
+
+        scrollView.measureChildWithMargins(child,
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY), 20,
+                MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 15);
+        verify(child).onMeasure(
+                eq(MeasureSpec.makeMeasureSpec(130, MeasureSpec.EXACTLY)),
+                eq(MeasureSpec.makeMeasureSpec(85, MeasureSpec.UNSPECIFIED)));
+    }
+
+    public void testMeasureSpecsWithMarginsAndPadding() {
+        MyView child = spy(new MyView(mActivity));
+        MyScrollView scrollView = new MyScrollView(mActivity);
+        scrollView.setPadding(3, 5, 7, 11);
+        scrollView.addView(child);
+
+        scrollView.measureChildWithMargins(child,
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY), 20,
+                MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY), 15);
+        verify(child).onMeasure(
+                eq(MeasureSpec.makeMeasureSpec(120, MeasureSpec.EXACTLY)),
+                eq(MeasureSpec.makeMeasureSpec(69, MeasureSpec.UNSPECIFIED)));
+    }
+
+    public void testMeasureSpecsWithMarginsAndNoHintWidth() {
+        MyView child = spy(new MyView(mActivity));
+        MyScrollView scrollView = new MyScrollView(mActivity);
+        scrollView.addView(child);
+
+        scrollView.measureChildWithMargins(child,
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY), 20,
+                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 15);
+        verify(child).onMeasure(
+                eq(MeasureSpec.makeMeasureSpec(130, MeasureSpec.EXACTLY)),
+                eq(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)));
+    }
+
+    public void testFillViewport() {
+        MyScrollView scrollView = new MyScrollView(mActivity);
+        scrollView.setFillViewport(true);
+
+        MyView child = new MyView(mActivity);
+        child.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
+
+        scrollView.addView(child);
+        scrollView.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY));
+
+        assertEquals(150, child.getMeasuredHeight());
+        assertEquals(100, child.getMeasuredWidth());
+
+        scrollView.layout(0, 0, 100, 150);
+        assertEquals(0, child.getTop());
+    }
+
+    public void testFillViewportWithScrollViewPadding() {
+        MyScrollView scrollView = new MyScrollView(mActivity);
+        scrollView.setFillViewport(true);
+        scrollView.setPadding(3, 10, 5, 7);
+
+        MyView child = new MyView(mActivity);
+        child.setLayoutParams(new ViewGroup.LayoutParams(10,10));
+        child.setDesiredHeight(30);
+
+        scrollView.addView(child);
+        scrollView.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY));
+
+        assertEquals(133, child.getMeasuredHeight());
+        assertEquals(10, child.getMeasuredWidth());
+
+        scrollView.layout(0, 0, 100, 150);
+        assertEquals(10, child.getTop());
+    }
+
+    public void testFillViewportWithChildMargins() {
+        MyScrollView scrollView = new MyScrollView(mActivity);
+        scrollView.setFillViewport(true);
+
+        MyView child = new MyView(mActivity);
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(10, 10);
+        lp.leftMargin = 3;
+        lp.topMargin = 10;
+        lp.rightMargin = 5;
+        lp.bottomMargin = 7;
+        child.setDesiredHeight(30);
+        child.setLayoutParams(lp);
+
+        scrollView.addView(child);
+        scrollView.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY));
+
+        assertEquals(133, child.getMeasuredHeight());
+        assertEquals(10, child.getMeasuredWidth());
+
+        scrollView.layout(0, 0, 100, 150);
+        assertEquals(10, child.getTop());
+    }
+
+    public void testFillViewportWithScrollViewPaddingAlreadyFills() {
+        MyScrollView scrollView = new MyScrollView(mActivity);
+        scrollView.setFillViewport(true);
+        scrollView.setPadding(3, 10, 5, 7);
+
+        MyView child = new MyView(mActivity);
+        child.setDesiredHeight(175);
+
+        scrollView.addView(child);
+        scrollView.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY));
+
+
+        assertEquals(92, child.getMeasuredWidth());
+        assertEquals(175, child.getMeasuredHeight());
+
+        scrollView.layout(0, 0, 100, 150);
+        assertEquals(10, child.getTop());
+    }
+
+    public void testFillViewportWithChildMarginsAlreadyFills() {
+        MyScrollView scrollView = new MyScrollView(mActivity);
+        scrollView.setFillViewport(true);
+        MyView child = new MyView(mActivity);
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+
+        lp.leftMargin = 3;
+        lp.topMargin = 10;
+        lp.rightMargin = 5;
+        lp.bottomMargin = 7;
+        child.setLayoutParams(lp);
+        child.setDesiredHeight(175);
+
+        scrollView.addView(child);
+        scrollView.measure(MeasureSpec.makeMeasureSpec(100, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(150, MeasureSpec.EXACTLY));
+
+        assertEquals(92, child.getMeasuredWidth());
+        assertEquals(175, child.getMeasuredHeight());
+
+        scrollView.layout(0, 0, 100, 150);
+        assertEquals(10, child.getTop());
+    }
+
     @UiThreadTest
     public void testPageScroll() {
         mScrollView.setSmoothScrollingEnabled(false);
@@ -703,9 +880,31 @@
         }.run();
     }
 
-    private static class MyView extends View {
+    public static class MyView extends View {
+        // measure in this height if set
+        private Integer mDesiredHeight;
         public MyView(Context context) {
             super(context);
         }
+
+        public void setDesiredHeight(Integer desiredHeight) {
+            mDesiredHeight = desiredHeight;
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            if (mDesiredHeight != null) {
+                int mode = MeasureSpec.getMode(heightMeasureSpec);
+                int size = MeasureSpec.getSize(heightMeasureSpec);
+                int newHeight = size;
+                if (mode == MeasureSpec.AT_MOST) {
+                    newHeight = Math.max(size, mDesiredHeight);
+                } else if (mode == MeasureSpec.UNSPECIFIED) {
+                    newHeight = mDesiredHeight;
+                }
+                setMeasuredDimension(getMeasuredWidth(), newHeight);
+            }
+        }
     }
 }
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index a95e43d..40d42a2 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -42,9 +42,9 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.TouchUtils;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.Editable;
-import android.text.Html;
 import android.text.InputFilter;
 import android.text.InputType;
 import android.text.Layout;
@@ -71,6 +71,7 @@
 import android.text.method.TextKeyListener.Capitalize;
 import android.text.method.TimeKeyListener;
 import android.text.method.TransformationMethod;
+import android.text.style.ImageSpan;
 import android.text.style.URLSpan;
 import android.text.style.UnderlineSpan;
 import android.text.util.Linkify;
@@ -1302,20 +1303,69 @@
         }
     }
 
-    @UiThreadTest
-    public void testSetText_setsMovementMethodWhenLinksClickableAndTextContainsClickableSpans() {
-        Spanned text = Html.fromHtml("<a href='http://android.com'>link</a>");
-        mTextView = new TextView(mActivity);
+    @MediumTest
+    public void testSetText_updatesHeightAfterRemovingImageSpan() {
+        // Height calculation had problems when TextView had width: match_parent
+        final int textViewWidth = ViewGroup.LayoutParams.MATCH_PARENT;
+        final Spannable text = new SpannableString("some text");
+        final int spanHeight = 100;
 
-        mTextView.setLinksClickable(false);
-        mTextView.setText(text);
-        assertNull("TextView.setText should not set movement method if linksClickable is false",
-                mTextView.getMovementMethod());
+        // prepare TextView, width: MATCH_PARENT
+        TextView textView = new TextView(getActivity());
+        textView.setSingleLine(true);
+        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 2);
+        textView.setPadding(0, 0, 0, 0);
+        textView.setIncludeFontPadding(false);
+        textView.setText(text);
+        final FrameLayout layout = new FrameLayout(mActivity);
+        final ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(textViewWidth,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+        layout.addView(textView, layoutParams);
+        layout.setLayoutParams(layoutParams);
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getActivity().setContentView(layout);
+            }
+        });
+        getInstrumentation().waitForIdleSync();
 
-        mTextView.setLinksClickable(true);
-        mTextView.setText(text);
-        assertNotNull("TextView.setText should set movement method if linksClickable is true " +
-                "and text contains clickable spans", mTextView.getMovementMethod());
+        // measure height of text with no span
+        final int heightWithoutSpan = textView.getHeight();
+        assertTrue("Text height should be smaller than span height",
+                heightWithoutSpan < spanHeight);
+
+        // add ImageSpan to text
+        Drawable drawable = mInstrumentation.getContext().getDrawable(R.drawable.scenery);
+        drawable.setBounds(0, 0, spanHeight, spanHeight);
+        ImageSpan span = new ImageSpan(drawable);
+        text.setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                textView.setText(text);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        // measure height with span
+        final int heightWithSpan = textView.getHeight();
+        assertTrue("Text height should be greater or equal than span height",
+                heightWithSpan >= spanHeight);
+
+        // remove the span
+        text.removeSpan(span);
+        mActivity.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                textView.setText(text);
+            }
+        });
+        mInstrumentation.waitForIdleSync();
+
+        final int heightAfterRemoveSpan = textView.getHeight();
+        assertEquals("Text height should be same after removing the span",
+                heightWithoutSpan, heightAfterRemoveSpan);
     }
 
     public void testRemoveSelectionWithSelectionHandles() {
@@ -2853,37 +2903,6 @@
     }
 
     @UiThreadTest
-    public void testAppend_setsMovementMethodWhenLinksClickableAndTextContainsClickableSpans() {
-        Spanned text = Html.fromHtml("<a href='http://android.com'>link</a>");
-        mTextView = new TextView(mActivity);
-
-        mTextView.setLinksClickable(false);
-        mTextView.append(text);
-        assertNull("TextView.append should not set movement method if linksClickable is false",
-                mTextView.getMovementMethod());
-
-        mTextView.setText("");
-        mTextView.setLinksClickable(true);
-        mTextView.append(text);
-        assertNotNull("TextView.append should set movement method if linksClickable is true " +
-                "and text contains clickable spans", mTextView.getMovementMethod());
-    }
-
-    @UiThreadTest
-    public void testAppend_setMovementMethodForExistingTextWhenLinksClickableIsTrueDuringAppend() {
-        Spanned text = Html.fromHtml("<a href='http://android.com'>link</a>");
-        mTextView = new TextView(mActivity);
-        mTextView.setLinksClickable(false);
-        mTextView.setText(text);
-
-        mTextView.setLinksClickable(true);
-        mTextView.append("");
-
-        assertNotNull("TextView.append should set movement method if existing text contains " +
-                "links but new text does not", mTextView.getMovementMethod());
-    }
-
-    @UiThreadTest
     public void testAppend_addsLinksWhenTextIsSpannableAndContainsUrlAndAutoLinkIsEnabled() {
         mTextView = new TextView(mActivity);
         mTextView.setAutoLinkMask(Linkify.ALL);
diff --git a/tests/tests/widget/src/android/widget/cts/ToolbarTest.java b/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
index f44a42d..0fd98c0 100644
--- a/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToolbarTest.java
@@ -20,13 +20,17 @@
 import android.graphics.drawable.Drawable;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
+import android.test.suitebuilder.annotation.MediumTest;
 import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
 import android.widget.Toolbar;
 import android.widget.cts.util.TestUtils;
 import android.widget.cts.util.ViewTestUtils;
 
 import static org.mockito.Mockito.*;
 
+@MediumTest
 public class ToolbarTest extends ActivityInstrumentationTestCase2<ToolbarCtsActivity> {
     private Toolbar mMainToolbar;
     private ToolbarCtsActivity mActivity;
@@ -112,6 +116,8 @@
         assertEquals(R.id.action_share, menu.getItem(4).getItemId());
         assertEquals(R.id.action_print, menu.getItem(5).getItemId());
 
+        assertFalse(mMainToolbar.hasExpandedActionView());
+
         Toolbar.OnMenuItemClickListener menuItemClickListener =
                 mock(Toolbar.OnMenuItemClickListener.class);
         mMainToolbar.setOnMenuItemClickListener(menuItemClickListener);
@@ -191,4 +197,133 @@
                 toolbarOverflowIcon.getIntrinsicWidth(), toolbarOverflowIcon.getIntrinsicHeight(),
                 true, 0XFFFF0000, 1, false);
     }
+
+    public void testActionView() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        // Inflate menu and check that we don't have an expanded action view
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+                () -> mMainToolbar.inflateMenu(R.menu.toolbar_menu_search));
+        assertFalse(mMainToolbar.hasExpandedActionView());
+
+        // Expand search menu item's action view and verify that main toolbar has an expanded
+        // action view
+        final MenuItem searchMenuItem = mMainToolbar.getMenu().findItem(R.id.action_search);
+        instrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
+        instrumentation.waitForIdleSync();
+        assertTrue(searchMenuItem.isActionViewExpanded());
+        assertTrue(mMainToolbar.hasExpandedActionView());
+
+        // Collapse search menu item's action view and verify that main toolbar doesn't have an
+        // expanded action view
+        instrumentation.runOnMainSync(() -> searchMenuItem.collapseActionView());
+        instrumentation.waitForIdleSync();
+        assertFalse(searchMenuItem.isActionViewExpanded());
+        assertFalse(mMainToolbar.hasExpandedActionView());
+
+        // Expand search menu item's action view again
+        instrumentation.runOnMainSync(() -> searchMenuItem.expandActionView());
+        instrumentation.waitForIdleSync();
+        assertTrue(searchMenuItem.isActionViewExpanded());
+        assertTrue(mMainToolbar.hasExpandedActionView());
+
+        // Now collapse search menu item's action view via toolbar's API and verify that main
+        // toolbar doesn't have an expanded action view
+        instrumentation.runOnMainSync(() -> mMainToolbar.collapseActionView());
+        instrumentation.waitForIdleSync();
+        assertFalse(searchMenuItem.isActionViewExpanded());
+        assertFalse(mMainToolbar.hasExpandedActionView());
+    }
+
+    public void testNavigationConfiguration() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+                () -> mMainToolbar.setNavigationIcon(R.drawable.icon_green));
+        Drawable toolbarNavigationIcon = mMainToolbar.getNavigationIcon();
+        TestUtils.assertAllPixelsOfColor("Navigation icon is green", toolbarNavigationIcon,
+                toolbarNavigationIcon.getIntrinsicWidth(),
+                toolbarNavigationIcon.getIntrinsicHeight(),
+                true, 0xFF00FF00, 1, false);
+
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+                () -> mMainToolbar.setNavigationIcon(mActivity.getDrawable(R.drawable.icon_blue)));
+        toolbarNavigationIcon = mMainToolbar.getNavigationIcon();
+        TestUtils.assertAllPixelsOfColor("Navigation icon is blue", toolbarNavigationIcon,
+                toolbarNavigationIcon.getIntrinsicWidth(),
+                toolbarNavigationIcon.getIntrinsicHeight(),
+                true, 0xFF0000FF, 1, false);
+
+        instrumentation.runOnMainSync(
+                () -> mMainToolbar.setNavigationContentDescription(R.string.toolbar_navigation));
+        assertEquals(mActivity.getResources().getString(R.string.toolbar_navigation),
+                mMainToolbar.getNavigationContentDescription());
+
+        instrumentation.runOnMainSync(
+                () -> mMainToolbar.setNavigationContentDescription("Navigation legend"));
+        assertEquals("Navigation legend", mMainToolbar.getNavigationContentDescription());
+    }
+
+    public void testLogoConfiguration() {
+        final Instrumentation instrumentation = getInstrumentation();
+
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+                () -> mMainToolbar.setLogo(R.drawable.icon_yellow));
+        Drawable toolbarLogo = mMainToolbar.getLogo();
+        TestUtils.assertAllPixelsOfColor("Logo is yellow", toolbarLogo,
+                toolbarLogo.getIntrinsicWidth(),
+                toolbarLogo.getIntrinsicHeight(),
+                true, 0xFFFFFF00, 1, false);
+
+        ViewTestUtils.runOnMainAndDrawSync(instrumentation, mMainToolbar,
+                () -> mMainToolbar.setLogo(mActivity.getDrawable(R.drawable.icon_red)));
+        toolbarLogo = mMainToolbar.getLogo();
+        TestUtils.assertAllPixelsOfColor("Logo is red", toolbarLogo,
+                toolbarLogo.getIntrinsicWidth(),
+                toolbarLogo.getIntrinsicHeight(),
+                true, 0xFFFF0000, 1, false);
+
+        instrumentation.runOnMainSync(
+                () -> mMainToolbar.setLogoDescription(R.string.toolbar_logo));
+        assertEquals(mActivity.getResources().getString(R.string.toolbar_logo),
+                mMainToolbar.getLogoDescription());
+
+        instrumentation.runOnMainSync(
+                () -> mMainToolbar.setLogoDescription("Logo legend"));
+        assertEquals("Logo legend", mMainToolbar.getLogoDescription());
+    }
+
+    @UiThreadTest
+    public void testContentInsetsLtr() {
+        mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_LTR);
+
+        mMainToolbar.setContentInsetsAbsolute(20, 25);
+        assertEquals(20, mMainToolbar.getContentInsetLeft());
+        assertEquals(20, mMainToolbar.getContentInsetStart());
+        assertEquals(25, mMainToolbar.getContentInsetRight());
+        assertEquals(25, mMainToolbar.getContentInsetEnd());
+
+        mMainToolbar.setContentInsetsRelative(40, 20);
+        assertEquals(40, mMainToolbar.getContentInsetLeft());
+        assertEquals(40, mMainToolbar.getContentInsetStart());
+        assertEquals(20, mMainToolbar.getContentInsetRight());
+        assertEquals(20, mMainToolbar.getContentInsetEnd());
+    }
+
+    @UiThreadTest
+    public void testContentInsetsRtl() {
+        mMainToolbar.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+
+        mMainToolbar.setContentInsetsAbsolute(20, 25);
+        assertEquals(20, mMainToolbar.getContentInsetLeft());
+        assertEquals(25, mMainToolbar.getContentInsetStart());
+        assertEquals(25, mMainToolbar.getContentInsetRight());
+        assertEquals(20, mMainToolbar.getContentInsetEnd());
+
+        mMainToolbar.setContentInsetsRelative(40, 20);
+        assertEquals(20, mMainToolbar.getContentInsetLeft());
+        assertEquals(40, mMainToolbar.getContentInsetStart());
+        assertEquals(40, mMainToolbar.getContentInsetRight());
+        assertEquals(20, mMainToolbar.getContentInsetEnd());
+    }
 }
diff --git a/tests/tvprovider/AndroidManifest.xml b/tests/tvprovider/AndroidManifest.xml
index fcf0ec5..d840eb7 100644
--- a/tests/tvprovider/AndroidManifest.xml
+++ b/tests/tvprovider/AndroidManifest.xml
@@ -20,6 +20,7 @@
     <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" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/tests/uiautomator/Android.mk b/tests/uiautomator/Android.mk
deleted file mode 100644
index d8422e6..0000000
--- a/tests/uiautomator/Android.mk
+++ /dev/null
@@ -1,37 +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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/local/tmp
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := CtsUiAutomatorTestCases
-LOCAL_STATIC_JAVA_LIBRARIES := uiautomator.core
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_CTS_TEST_APK := CtsUiAutomatorTestApp
-LOCAL_CTS_TEST_APP_PACKAGE := com.android.uiautomator.app
-LOCAL_CTS_TEST_PACKAGE := com.android.uiautomator.cts
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-include $(BUILD_CTS_UI_JAVA_LIBRARY)
-
-# Build the test APK using its own makefile, and any other CTS-related packages
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/uiautomator/AndroidTest.xml b/tests/uiautomator/AndroidTest.xml
deleted file mode 100644
index c931f59..0000000
--- a/tests/uiautomator/AndroidTest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<configuration description="Config for CTS UI Automator test cases">
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
-        <option name="cleanup-apks" value="true" />
-        <option name="test-file-name" value="CtsUiAutomatorTestApp.apk" />
-    </target_preparer>
-    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
-        <option name="cleanup" value="true" />
-        <option name="push" value="CtsUiAutomatorTestCases.jar->/data/local/tmp/CtsUiAutomatorTestCases.jar" />
-    </target_preparer>
-    <test class="com.android.tradefed.testtype.UiAutomatorTest" >
-        <option name="jar-path" value="CtsUiAutomatorTestCases.jar" />
-        <option name="capture-logs" value="OFF" />
-    </test>
-</configuration>
diff --git a/tests/uiautomator/app/AndroidManifest.xml b/tests/uiautomator/app/AndroidManifest.xml
deleted file mode 100644
index 25f746b..0000000
--- a/tests/uiautomator/app/AndroidManifest.xml
+++ /dev/null
@@ -1,48 +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.
- -->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.uiautomator.app"
-    android:versionCode="1"
-    android:versionName="1.0" >
-    <uses-sdk
-        android:minSdkVersion="14"
-        android:targetSdkVersion="15" />
-
-    <uses-permission android:name="android.permission.INTERNET"/>
-    <application
-        android:icon="@drawable/ic_launcher"
-        android:label="@string/app_name"
-        android:theme="@style/AppTheme" >
-        <activity
-            android:name=".MainActivity"
-            android:label="@string/title_test_list" >
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
-        <activity
-            android:name=".SinglePaneDetailActivity"
-            android:label="@string/title_test_detail" >
-            <meta-data
-                android:name="android.support.PARENT_ACTIVITY"
-                android:value="FragmentActivity" />
-        </activity>
-     </application>
-
-</manifest>
diff --git a/tests/uiautomator/app/res/drawable-hdpi/ic_action_search.png b/tests/uiautomator/app/res/drawable-hdpi/ic_action_search.png
deleted file mode 100644
index 67de12d..0000000
--- a/tests/uiautomator/app/res/drawable-hdpi/ic_action_search.png
+++ /dev/null
Binary files differ
diff --git a/tests/uiautomator/app/res/drawable-hdpi/ic_launcher.png b/tests/uiautomator/app/res/drawable-hdpi/ic_launcher.png
deleted file mode 100644
index 947dbfc..0000000
--- a/tests/uiautomator/app/res/drawable-hdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/uiautomator/app/res/drawable-ldpi/ic_launcher.png b/tests/uiautomator/app/res/drawable-ldpi/ic_launcher.png
deleted file mode 100644
index e075065..0000000
--- a/tests/uiautomator/app/res/drawable-ldpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/uiautomator/app/res/drawable-mdpi/ic_action_search.png b/tests/uiautomator/app/res/drawable-mdpi/ic_action_search.png
deleted file mode 100644
index 134d549..0000000
--- a/tests/uiautomator/app/res/drawable-mdpi/ic_action_search.png
+++ /dev/null
Binary files differ
diff --git a/tests/uiautomator/app/res/drawable-mdpi/ic_launcher.png b/tests/uiautomator/app/res/drawable-mdpi/ic_launcher.png
deleted file mode 100644
index f91af33..0000000
--- a/tests/uiautomator/app/res/drawable-mdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/uiautomator/app/res/drawable-xhdpi/ic_action_search.png b/tests/uiautomator/app/res/drawable-xhdpi/ic_action_search.png
deleted file mode 100644
index d699c6b..0000000
--- a/tests/uiautomator/app/res/drawable-xhdpi/ic_action_search.png
+++ /dev/null
Binary files differ
diff --git a/tests/uiautomator/app/res/drawable-xhdpi/ic_launcher.png b/tests/uiautomator/app/res/drawable-xhdpi/ic_launcher.png
deleted file mode 100644
index 542a9cb..0000000
--- a/tests/uiautomator/app/res/drawable-xhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/tests/uiautomator/app/res/layout-land/test5_detail_fragment.xml b/tests/uiautomator/app/res/layout-land/test5_detail_fragment.xml
deleted file mode 100644
index 123ebde..0000000
--- a/tests/uiautomator/app/res/layout-land/test5_detail_fragment.xml
+++ /dev/null
@@ -1,123 +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:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:contentDescription="@string/test_5_Widgets_collection"
-    android:orientation="horizontal" >
-
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:orientation="vertical" >
-
-        <CheckBox
-            android:id="@+id/test_5_checkBox"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/test5_CheckBox" />
-
-        <Spinner
-            android:id="@+id/test_5_spinner"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-
-        <ProgressBar
-            android:id="@+id/test_5_progressBar"
-            style="?android:attr/progressBarStyleLarge"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
-
-        <GridLayout
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:columnCount="3" >
-
-            <ImageButton
-                android:id="@+id/test_5_imageButton"
-                android:layout_column="0"
-                android:layout_gravity="left"
-                android:layout_row="0"
-                android:src="@drawable/ic_launcher" />
-
-            <RatingBar
-                android:id="@+id/test_5_ratingBar"
-                android:layout_column="1"
-                android:layout_columnSpan="2"
-                android:layout_gravity="left|bottom"
-                android:layout_row="0" />
-
-            <Button
-                android:id="@+id/test_5_button2"
-                style="?android:attr/buttonStyleSmall"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="left|bottom"
-                android:enabled="false"
-                android:layout_row="0"
-                android:text="@string/test5_Button_Disabled" />
-
-            <Space
-                android:layout_width="21dp"
-                android:layout_height="1dp"
-                android:layout_column="1"
-                android:layout_row="0" />
-
-            <Space
-                android:layout_width="1dp"
-                android:layout_height="21dp"
-                android:layout_column="0"
-                android:layout_row="0" />
-
-            <Space
-                android:layout_width="221dp"
-                android:layout_height="15dp"
-                android:layout_column="2"
-                android:layout_row="1" />
-
-            <ToggleButton
-                android:id="@+id/test_5_toggleButton"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_column="2"
-                android:text="@string/test5_ToggleButton" />
-        </GridLayout>
-
-    </LinearLayout>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical" >
-
-        <SeekBar
-            android:id="@+id/test_5_seekBar"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
-
-        <Button
-            android:id="@+id/test_5_button1"
-            style="?android:attr/buttonStyleSmall"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:contentDescription="@string/test5_Button_Description"
-            android:text="@string/test5_Button" />
-
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/tests/uiautomator/app/res/layout/activity_main.xml b/tests/uiautomator/app/res/layout/activity_main.xml
deleted file mode 100644
index 72b68f3..0000000
--- a/tests/uiautomator/app/res/layout/activity_main.xml
+++ /dev/null
@@ -1,31 +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.
- -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    tools:context=".MainActivity" >
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_centerHorizontal="true"
-        android:layout_centerVertical="true"
-        android:text="@string/hello_world" />
-
-</RelativeLayout>
diff --git a/tests/uiautomator/app/res/layout/list_activity.xml b/tests/uiautomator/app/res/layout/list_activity.xml
deleted file mode 100644
index faedc91..0000000
--- a/tests/uiautomator/app/res/layout/list_activity.xml
+++ /dev/null
@@ -1,26 +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.
- -->
-<fragment xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:name="com.android.uiautomator.app.TestListFragment"
-    android:id="@+id/item_list"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_marginLeft="16dp"
-    android:layout_marginRight="16dp"
-    tools:context=".MainActivity" />
diff --git a/tests/uiautomator/app/res/layout/simple_list_item_selected.xml b/tests/uiautomator/app/res/layout/simple_list_item_selected.xml
deleted file mode 100644
index 978ceee..0000000
--- a/tests/uiautomator/app/res/layout/simple_list_item_selected.xml
+++ /dev/null
@@ -1,28 +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.
- -->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/label"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:textAppearance="?android:attr/textAppearanceListItemSmall"
-    android:gravity="center_vertical"
-    android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
-    android:paddingRight="?android:attr/listPreferredItemPaddingRight"
-    android:background="?android:attr/activatedBackgroundIndicator"
-    android:minHeight="?android:attr/listPreferredItemHeightSmall"
-/>
diff --git a/tests/uiautomator/app/res/layout/singlepane_activity.xml b/tests/uiautomator/app/res/layout/singlepane_activity.xml
deleted file mode 100644
index 78b2545..0000000
--- a/tests/uiautomator/app/res/layout/singlepane_activity.xml
+++ /dev/null
@@ -1,23 +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.
- -->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/test_results_detail_container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    tools:context=".TestResultsDetailActivity" />
\ No newline at end of file
diff --git a/tests/uiautomator/app/res/layout/test1_detail_fragment.xml b/tests/uiautomator/app/res/layout/test1_detail_fragment.xml
deleted file mode 100644
index c9b2a05..0000000
--- a/tests/uiautomator/app/res/layout/test1_detail_fragment.xml
+++ /dev/null
@@ -1,61 +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:id="@+id/test_1_detail_container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical" >
-
-    <TextView
-        android:id="@+id/item1_test_description"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="5dp"
-        android:text="@string/test1_description" />
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="horizontal" >
-
-        <EditText
-            android:id="@+id/test1TextField"
-            android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="5dp"
-            android:layout_weight="2"
-            android:inputType="textNoSuggestions"
-            android:paddingLeft="5dip"
-            android:paddingRight="5dip"
-            android:width="200dip" >
-
-            <requestFocus />
-        </EditText>
-
-        <Button
-            android:id="@+id/test1SubmitButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="5dip"
-            android:layout_marginRight="5dip"
-            android:minWidth="64dip"
-            android:text="@string/buttonSubmit" />
-
-    </LinearLayout>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/tests/uiautomator/app/res/layout/test2_detail_fragment.xml b/tests/uiautomator/app/res/layout/test2_detail_fragment.xml
deleted file mode 100644
index 1bf60b8..0000000
--- a/tests/uiautomator/app/res/layout/test2_detail_fragment.xml
+++ /dev/null
@@ -1,78 +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:id="@+id/test_2_detail_container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical" >
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="5dp"
-        android:text="@string/test2_description" />
-
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal"
-        android:orientation="horizontal" >
-
-        <Button
-            android:id="@+id/test2button1"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:contentDescription="@string/button1"
-            android:text="@string/button1" />
-
-        <Button
-            android:id="@+id/test2button2"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:contentDescription="@string/button2"
-            android:text="@string/button2" />
-
-        <Button
-            android:id="@+id/test2button3"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:contentDescription="@string/button3"
-            android:text="@string/button3" />
-    </LinearLayout>
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="5dp"
-        android:text="@string/test2_description_2" />
-
-    <LinearLayout
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal"
-        android:orientation="horizontal" >
-
-        <Button
-            android:id="@+id/test2dynaButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:contentDescription="@string/buttonBefore"
-            android:text="@string/buttonBefore" />
-
-    </LinearLayout>
-</LinearLayout>
\ No newline at end of file
diff --git a/tests/uiautomator/app/res/layout/test3_detail_fragment.xml b/tests/uiautomator/app/res/layout/test3_detail_fragment.xml
deleted file mode 100644
index de7ecb6..0000000
--- a/tests/uiautomator/app/res/layout/test3_detail_fragment.xml
+++ /dev/null
@@ -1,76 +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:id="@+id/test_3_detail_container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical" >
-
-    <TextView
-        android:id="@+id/item3_test_description"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="5dp"
-        android:text="@string/test3_description" />
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical" >
-
-        <TextView
-            android:id="@+id/test3ClockTextView"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_horizontal"
-            android:layout_marginBottom="10dip"
-            android:layout_marginTop="10dip"
-            android:contentDescription="@string/test3ClockDescription"
-            android:padding="10dp"
-            android:text="@string/test3InitialClock" />
-
-    </LinearLayout>
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal" >
-
-        <EditText
-            android:id="@+id/test3TextField"
-            android:layout_width="0dip"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="5dp"
-            android:layout_weight="2"
-            android:inputType="numberDecimal"
-            android:paddingLeft="5dip"
-            android:paddingRight="5dip"
-            android:width="200dip" >
-            <requestFocus />
-        </EditText>
-
-        <Button
-            android:id="@+id/test3SubmitButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginLeft="5dip"
-            android:layout_marginRight="5dip"
-            android:minWidth="64dip"
-            android:text="@string/buttonSubmit" />
-    </LinearLayout>
-</LinearLayout>
\ No newline at end of file
diff --git a/tests/uiautomator/app/res/layout/test4_detail_fragment.xml b/tests/uiautomator/app/res/layout/test4_detail_fragment.xml
deleted file mode 100644
index dbf88ee..0000000
--- a/tests/uiautomator/app/res/layout/test4_detail_fragment.xml
+++ /dev/null
@@ -1,23 +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.
- -->
- <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:id="@+id/test_4_detail_container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    tools:context=".Test4DetailActivity" />
\ No newline at end of file
diff --git a/tests/uiautomator/app/res/layout/test5_detail_fragment.xml b/tests/uiautomator/app/res/layout/test5_detail_fragment.xml
deleted file mode 100644
index e34f271..0000000
--- a/tests/uiautomator/app/res/layout/test5_detail_fragment.xml
+++ /dev/null
@@ -1,109 +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:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:contentDescription="@string/test_5_Widgets_collection"
-    android:orientation="vertical" >
-
-    <CheckBox
-        android:id="@+id/test_5_checkBox"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:text="@string/test5_CheckBox" />
-
-    <Spinner
-        android:id="@+id/test_5_spinner"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
-
-    <ProgressBar
-        android:id="@+id/test_5_progressBar"
-        style="?android:attr/progressBarStyleLarge"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content" />
-
-    <GridLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:columnCount="3" >
-
-        <ImageButton
-            android:id="@+id/test_5_imageButton"
-            android:layout_column="0"
-            android:layout_gravity="left"
-            android:layout_row="0"
-            android:src="@drawable/ic_launcher" />
-
-        <RatingBar
-            android:id="@+id/test_5_ratingBar"
-            android:layout_column="1"
-            android:layout_columnSpan="2"
-            android:layout_gravity="left|bottom"
-            android:layout_row="0" />
-
-        <Button
-            android:id="@+id/test_5_button2"
-            style="?android:attr/buttonStyleSmall"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="left|bottom"
-            android:enabled="false"
-            android:layout_row="0"
-            android:text="@string/test5_Button_Disabled" />
-
-        <Space
-            android:layout_width="21dp"
-            android:layout_height="1dp"
-            android:layout_column="1"
-            android:layout_row="0" />
-
-        <Space
-            android:layout_width="1dp"
-            android:layout_height="21dp"
-            android:layout_column="0"
-            android:layout_row="0" />
-
-        <Space
-            android:layout_width="221dp"
-            android:layout_height="15dp"
-            android:layout_column="2"
-            android:layout_row="1" />
-
-        <ToggleButton
-            android:id="@+id/test_5_toggleButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_column="2"
-            android:text="@string/test5_ToggleButton" />
-    </GridLayout>
-
-    <SeekBar
-        android:id="@+id/test_5_seekBar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-
-    <Button
-        android:id="@+id/test_5_button1"
-        style="?android:attr/buttonStyleSmall"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:contentDescription="@string/test5_Button_Description"
-        android:text="@string/test5_Button" />
-
-</LinearLayout>
diff --git a/tests/uiautomator/app/res/layout/test6_detail_fragment.xml b/tests/uiautomator/app/res/layout/test6_detail_fragment.xml
deleted file mode 100644
index 01a9fdc..0000000
--- a/tests/uiautomator/app/res/layout/test6_detail_fragment.xml
+++ /dev/null
@@ -1,28 +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:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical" >
-
-    <WebView
-        android:id="@+id/test6WebView"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/tests/uiautomator/app/res/layout/test_results_detail_fragment.xml b/tests/uiautomator/app/res/layout/test_results_detail_fragment.xml
deleted file mode 100644
index e8b8c05..0000000
--- a/tests/uiautomator/app/res/layout/test_results_detail_fragment.xml
+++ /dev/null
@@ -1,44 +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:id="@+id/test_results_detail_container"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:contentDescription="@string/title_test_view_detail"
-    android:orientation="vertical" >
-
-    <TextView
-        android:id="@+id/textView1"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="5dp"
-        android:text="@string/now_displaying_results_for" />
-
-    <TextView
-        android:id="@+id/testResultsTextView"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal"
-        android:contentDescription="@string/title_test_detail"
-        android:paddingLeft="2dp"
-        android:paddingTop="5dp"
-        android:textColor="#00aa00"
-        android:textSize="@dimen/padding_large"
-        android:textStyle="bold" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/tests/uiautomator/app/res/layout/twopane_activity.xml b/tests/uiautomator/app/res/layout/twopane_activity.xml
deleted file mode 100644
index a787368..0000000
--- a/tests/uiautomator/app/res/layout/twopane_activity.xml
+++ /dev/null
@@ -1,41 +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"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:orientation="horizontal"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_marginLeft="16dp"
-    android:layout_marginRight="16dp"
-    android:divider="?android:attr/dividerHorizontal"
-    android:showDividers="middle"
-    tools:context=".TestListActivity">
-
-    <fragment
-        android:id="@+id/item_list"
-        android:name="com.android.uiautomator.app.TestListFragment"
-        android:layout_width="0dp"
-        android:layout_height="match_parent"
-        android:layout_weight="1" />
-
-    <FrameLayout android:id="@+id/test_detail_container"
-        android:layout_width="0dp"
-        android:layout_height="match_parent"
-        android:layout_weight="3" />
-
-</LinearLayout>
diff --git a/tests/uiautomator/app/res/menu/activity_main.xml b/tests/uiautomator/app/res/menu/activity_main.xml
deleted file mode 100644
index c54c287..0000000
--- a/tests/uiautomator/app/res/menu/activity_main.xml
+++ /dev/null
@@ -1,26 +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.
- -->
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <item
-        android:id="@+id/menu_settings"
-        android:orderInCategory="100"
-        android:showAsAction="never"
-        android:title="@string/menu_settings"/>
-
-</menu>
diff --git a/tests/uiautomator/app/res/menu/test1_detail_activity.xml b/tests/uiautomator/app/res/menu/test1_detail_activity.xml
deleted file mode 100644
index fe1fe20..0000000
--- a/tests/uiautomator/app/res/menu/test1_detail_activity.xml
+++ /dev/null
@@ -1,23 +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.
- -->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/menu_settings"
-        android:title="@string/menu_settings"
-        android:orderInCategory="100"
-        android:showAsAction="never" />
-</menu>
diff --git a/tests/uiautomator/app/res/menu/test2_detail_activity.xml b/tests/uiautomator/app/res/menu/test2_detail_activity.xml
deleted file mode 100644
index 405d4c8..0000000
--- a/tests/uiautomator/app/res/menu/test2_detail_activity.xml
+++ /dev/null
@@ -1,32 +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.
- -->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/menu_text1"
-        android:title="Submit" />
-    <item android:id="@+id/menu_text2"
-        android:icon="@drawable/ic_launcher"
-        android:title="Done" />
-    <item android:id="@+id/menu_text3"
-        android:title="OK" />
-    <item android:id="@+id/menu_text4"
-        android:title="Finish" />
-    <item android:id="@+id/menu_text5"
-        android:title="Complete" />
-    <item android:id="@+id/menu_text6"
-        android:title="Exit" />
-</menu>
diff --git a/tests/uiautomator/app/res/menu/test3_detail_activity.xml b/tests/uiautomator/app/res/menu/test3_detail_activity.xml
deleted file mode 100644
index fe1fe20..0000000
--- a/tests/uiautomator/app/res/menu/test3_detail_activity.xml
+++ /dev/null
@@ -1,23 +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.
- -->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/menu_settings"
-        android:title="@string/menu_settings"
-        android:orderInCategory="100"
-        android:showAsAction="never" />
-</menu>
diff --git a/tests/uiautomator/app/res/menu/test4_detail_activity.xml b/tests/uiautomator/app/res/menu/test4_detail_activity.xml
deleted file mode 100644
index fe1fe20..0000000
--- a/tests/uiautomator/app/res/menu/test4_detail_activity.xml
+++ /dev/null
@@ -1,23 +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.
- -->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/menu_settings"
-        android:title="@string/menu_settings"
-        android:orderInCategory="100"
-        android:showAsAction="never" />
-</menu>
diff --git a/tests/uiautomator/app/res/menu/test5_detail_activity.xml b/tests/uiautomator/app/res/menu/test5_detail_activity.xml
deleted file mode 100644
index fe1fe20..0000000
--- a/tests/uiautomator/app/res/menu/test5_detail_activity.xml
+++ /dev/null
@@ -1,23 +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.
- -->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/menu_settings"
-        android:title="@string/menu_settings"
-        android:orderInCategory="100"
-        android:showAsAction="never" />
-</menu>
diff --git a/tests/uiautomator/app/res/menu/test6_detail_activity.xml b/tests/uiautomator/app/res/menu/test6_detail_activity.xml
deleted file mode 100644
index fe1fe20..0000000
--- a/tests/uiautomator/app/res/menu/test6_detail_activity.xml
+++ /dev/null
@@ -1,23 +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.
- -->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/menu_settings"
-        android:title="@string/menu_settings"
-        android:orderInCategory="100"
-        android:showAsAction="never" />
-</menu>
diff --git a/tests/uiautomator/app/res/menu/test_results_detail_activity.xml b/tests/uiautomator/app/res/menu/test_results_detail_activity.xml
deleted file mode 100644
index febffa2..0000000
--- a/tests/uiautomator/app/res/menu/test_results_detail_activity.xml
+++ /dev/null
@@ -1,24 +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.
- -->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:id="@+id/menu_settings"
-        android:title="@string/menu_settings"
-        android:orderInCategory="100"
-        android:showAsAction="never" />
-</menu>
-
diff --git a/tests/uiautomator/app/res/values-large/dimens.xml b/tests/uiautomator/app/res/values-large/dimens.xml
deleted file mode 100644
index 788578a..0000000
--- a/tests/uiautomator/app/res/values-large/dimens.xml
+++ /dev/null
@@ -1,24 +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.
- -->
-<resources>
-
-    <dimen name="padding_small">8dp</dimen>
-    <dimen name="padding_medium">16dp</dimen>
-    <dimen name="padding_large">16dp</dimen>
-
-</resources>
\ No newline at end of file
diff --git a/tests/uiautomator/app/res/values-large/refs.xml b/tests/uiautomator/app/res/values-large/refs.xml
deleted file mode 100644
index ac82847..0000000
--- a/tests/uiautomator/app/res/values-large/refs.xml
+++ /dev/null
@@ -1,20 +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.
- -->
-<resources>
-    <item type="layout" name="list_activity">@layout/twopane_activity</item>
-</resources>
diff --git a/tests/uiautomator/app/res/values-sw600dp/refs.xml b/tests/uiautomator/app/res/values-sw600dp/refs.xml
deleted file mode 100644
index ac82847..0000000
--- a/tests/uiautomator/app/res/values-sw600dp/refs.xml
+++ /dev/null
@@ -1,20 +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.
- -->
-<resources>
-    <item type="layout" name="list_activity">@layout/twopane_activity</item>
-</resources>
diff --git a/tests/uiautomator/app/res/values-v11/styles.xml b/tests/uiautomator/app/res/values-v11/styles.xml
deleted file mode 100644
index 504d3e3..0000000
--- a/tests/uiautomator/app/res/values-v11/styles.xml
+++ /dev/null
@@ -1,22 +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.
- -->
-<resources>
-
-    <style name="AppTheme" parent="android:Theme.Holo.Light" />
-
-</resources>
\ No newline at end of file
diff --git a/tests/uiautomator/app/res/values-v14/styles.xml b/tests/uiautomator/app/res/values-v14/styles.xml
deleted file mode 100644
index 1232912..0000000
--- a/tests/uiautomator/app/res/values-v14/styles.xml
+++ /dev/null
@@ -1,22 +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.
- -->
-<resources>
-
-    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar" />
-
-</resources>
\ No newline at end of file
diff --git a/tests/uiautomator/app/res/values-watch/styles.xml b/tests/uiautomator/app/res/values-watch/styles.xml
deleted file mode 100644
index 1d904c2..0000000
--- a/tests/uiautomator/app/res/values-watch/styles.xml
+++ /dev/null
@@ -1,22 +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.
- -->
-<resources>
-
-    <style name="AppTheme" parent="android:Theme.Holo.Light.NoActionBar" />
-
-</resources>
\ No newline at end of file
diff --git a/tests/uiautomator/app/res/values/dimens.xml b/tests/uiautomator/app/res/values/dimens.xml
deleted file mode 100644
index d607bb7..0000000
--- a/tests/uiautomator/app/res/values/dimens.xml
+++ /dev/null
@@ -1,24 +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.
- -->
-<resources>
-
-    <dimen name="padding_small">8dp</dimen>
-    <dimen name="padding_medium">8dp</dimen>
-    <dimen name="padding_large">16dp</dimen>
-
-</resources>
\ No newline at end of file
diff --git a/tests/uiautomator/app/res/values/strings.xml b/tests/uiautomator/app/res/values/strings.xml
deleted file mode 100644
index 04f0df4..0000000
--- a/tests/uiautomator/app/res/values/strings.xml
+++ /dev/null
@@ -1,63 +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.
- -->
-<resources>
-
-    <string name="app_name">UiAutomator Test App</string>
-    <string name="test1_description">This helps verify entering text into a pre-populated field. The pop-up dialog will echo the text entered after clicking submit. The initial value in the field must first be deleted.</string>
-    <string name="menu_settings">Settings</string>
-    <string name="title_activity_item1_detail">Item1DetailActivity</string>
-    <string name="buttonSubmit">Submit</string>
-    <string name="item1_dialog_title">Text submitted</string>
-    <string name="OK">OK</string>
-    <string name="title_test_list">UiAutomator Tests</string>
-    <string name="title_test_detail">Details</string>
-    <string name="hello_world">Hello world!</string>
-    <string name="title_activity_test2_detail">Test2DetailActivity</string>
-    <string name="test2_description">This helps test selection of button using Instance, Text and Content Description. Once clicked, a dialog pops up to verify the properties of button clicked.</string>
-    <string name="test2_description_2">This tests a Button text changing dynamically after a click. The test should attempt to find the button after it has changed using its new text.</string>
-    <string name="test3_description">The tests should read the clock, then write the clock back into the EditText then press submit. A dialog will display the time it took from reading the clock until submit is press. This can be used to get an idea of performance differences.</string>
-    <string name="button1">Button 1</string>
-    <string name="button1long">Longclick Button 1</string>
-    <string name="button2">Button 2</string>
-    <string name="button2long">Longclick Button 2</string>
-    <string name="button3">Button 3</string>
-    <string name="button3long">Longclick Button 3</string>
-    <string name="buttonBefore">Before</string>
-    <string name="buttonAfter">After</string>
-    <string name="dialog_title_result">Action results</string>
-    <string name="now_displaying_results_for">Verifying scroll into view and list item selection. Now displaying results for:</string>
-    <string name="title_activity_test3_detail">Performance test</string>
-    <string name="test3ClockDescription">Performance clock</string>
-    <string name="test3InitialClock">0000000000</string>
-    <string name="test3_dialog_title">Time difference in ms</string>
-    <string name="test5_CheckBox">CheckBox</string>
-    <string name="test5_ToggleButton">ToggleButton</string>
-    <string name="test5_Button">Button</string>
-    <string name="test5_Button_Description">Description for Button</string>
-    <string name="test5_Button_Disabled">Button D</string>
-    <string name="title_section4">Section 4</string>
-    <string name="title_section3">Section 3</string>
-    <string name="title_section2">Section 2</string>
-    <string name="title_section1">Section 1</string>
-    <string name="title_activity_test4_detail">Test4DetailActivity</string>
-    <string name="title_activity_test5_detail">Test5DetailActivity</string>
-    <string name="title_activity_test6_detail">Test6DetailActivity</string>
-    <string name="test_5_Widgets_collection">Widgets Collection</string>
-    <string name="generic_item_touch_dialog_title">Multi-touch test dialog</string>
-    <string name="drag_item_touch_dialog_title">Drag and drop test dialog</string>
-    <string name="title_test_view_detail">Details View</string>
-</resources>
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/MainActivity.java b/tests/uiautomator/app/src/com/android/uiautomator/app/MainActivity.java
deleted file mode 100644
index feb6767..0000000
--- a/tests/uiautomator/app/src/com/android/uiautomator/app/MainActivity.java
+++ /dev/null
@@ -1,59 +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.uiautomator.app;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
-import android.view.WindowManager;
-
-public class MainActivity extends FragmentActivity implements TestListFragment.Callbacks {
-
-    private boolean mTwoPane;
-    public static final String LOG_TAG = "UiAutomatorApp";
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        // If the device is locked, this attempts to dismiss the KeyGuard
-        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
-                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
-                      WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
-
-        setContentView(R.layout.list_activity);
-
-        if (findViewById(R.id.test_detail_container) != null) {
-            mTwoPane = true;
-            ((TestListFragment) getSupportFragmentManager().findFragmentById(R.id.item_list))
-                    .setActivateOnItemClick(true);
-        }
-    }
-
-    @Override
-    public void onItemSelected(String id) {
-        if (mTwoPane) {
-            Fragment fragment = TestItems.getFragment(id);
-            getSupportFragmentManager().beginTransaction()
-                    .replace(R.id.test_detail_container, fragment).commit();
-        } else {
-            Intent detailIntent = new Intent(this, SinglePaneDetailActivity.class);
-            detailIntent.putExtra("item_id", id);
-            startActivity(detailIntent);
-        }
-    }
-}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/SinglePaneDetailActivity.java b/tests/uiautomator/app/src/com/android/uiautomator/app/SinglePaneDetailActivity.java
deleted file mode 100644
index 553557e..0000000
--- a/tests/uiautomator/app/src/com/android/uiautomator/app/SinglePaneDetailActivity.java
+++ /dev/null
@@ -1,56 +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.uiautomator.app;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.NavUtils;
-import android.view.Menu;
-import android.view.MenuItem;
-
-public class SinglePaneDetailActivity extends FragmentActivity {
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.singlepane_activity);
-        getActionBar().setDisplayHomeAsUpEnabled(true);
-
-        if (savedInstanceState == null) {
-            Fragment fragment = TestItems.getFragment(getIntent().getStringExtra("item_id"));
-            getSupportFragmentManager().beginTransaction()
-                    .add(R.id.test_results_detail_container, fragment).commit();
-        }
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        getMenuInflater().inflate(R.menu.test_results_detail_activity, menu);
-        return true;
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-            case android.R.id.home:
-                NavUtils.navigateUpFromSameTask(this);
-                return true;
-        }
-        return super.onOptionsItemSelected(item);
-    }
-}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/Test1DetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/Test1DetailFragment.java
deleted file mode 100644
index f7dccb3..0000000
--- a/tests/uiautomator/app/src/com/android/uiautomator/app/Test1DetailFragment.java
+++ /dev/null
@@ -1,80 +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.uiautomator.app;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.Button;
-import android.widget.EditText;
-
-public class Test1DetailFragment extends Fragment {
-
-    public static final String ARG_ITEM_ID = "item_id";
-    private Button mSubmitButton;
-    private EditText mEditText;
-    TestItems.TestItem mItem;
-
-    public Test1DetailFragment() {
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        if (getArguments().containsKey(ARG_ITEM_ID)) {
-            mItem = TestItems.getTest(getArguments().getString(ARG_ITEM_ID));
-        }
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
-        View rootView = inflater.inflate(R.layout.test1_detail_fragment, container, false);
-        if (mItem != null) {
-            ((EditText) rootView.findViewById(R.id.test1TextField)).setText(mItem.mName);
-
-            mSubmitButton = (Button) rootView.findViewById(R.id.test1SubmitButton);
-            mEditText = (EditText) rootView.findViewById(R.id.test1TextField);
-            mEditText.setText("");
-            mSubmitButton.setOnClickListener(new Button.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    final String savedInput = mEditText.getText().toString();
-                    // clear so we won't be confused by the input text in
-                    // validation
-                    mEditText.setText("");
-                    // close soft keyboard
-                    InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
-                            Context.INPUT_METHOD_SERVICE);
-                    imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
-                    // display the submitted text
-                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-                    builder.setTitle(R.string.item1_dialog_title);
-                    builder.setPositiveButton(R.string.OK, null);
-                    builder.setMessage(savedInput);
-                    AlertDialog diag = builder.create();
-                    diag.show();
-                }
-            });
-        }
-        return rootView;
-    }
-}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/Test2DetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/Test2DetailFragment.java
deleted file mode 100644
index 1cb3a69..0000000
--- a/tests/uiautomator/app/src/com/android/uiautomator/app/Test2DetailFragment.java
+++ /dev/null
@@ -1,153 +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.uiautomator.app;
-
-import android.app.AlertDialog;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-
-public class Test2DetailFragment extends Fragment {
-    public static final String ARG_ITEM_ID = "item_id";
-    private Button mButton1, mButton2, mButton3, mDynaButton;
-
-    public Test2DetailFragment() {
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setHasOptionsMenu(true);
-    }
-
-    @Override
-    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        inflater.inflate(R.menu.test2_detail_activity, menu);
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-        builder.setTitle(R.string.dialog_title_result);
-        builder.setMessage(item.getTitle());
-        builder.setPositiveButton(R.string.OK, null);
-        AlertDialog diag = builder.create();
-        diag.show();
-        return super.onOptionsItemSelected(item);
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
-        View rootView = inflater.inflate(R.layout.test2_detail_fragment, container, false);
-
-        mButton1 = (Button) rootView.findViewById(R.id.test2button1);
-        mButton2 = (Button) rootView.findViewById(R.id.test2button2);
-        mButton3 = (Button) rootView.findViewById(R.id.test2button3);
-        mDynaButton = (Button) rootView.findViewById(R.id.test2dynaButton);
-
-        mButton1.setOnClickListener(new Button.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-                builder.setTitle(R.string.dialog_title_result);
-                builder.setPositiveButton(R.string.OK, null);
-                builder.setMessage(R.string.button1);
-                AlertDialog diag = builder.create();
-                diag.show();
-            }
-        });
-
-        mButton1.setOnLongClickListener(new Button.OnLongClickListener() {
-            @Override
-            public boolean onLongClick(View v) {
-                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-                builder.setTitle(R.string.dialog_title_result);
-                builder.setPositiveButton(R.string.OK, null);
-                builder.setMessage(R.string.button1long);
-                AlertDialog diag = builder.create();
-                diag.show();
-                return true;
-            }
-        });
-
-        mButton2.setOnClickListener(new Button.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-                builder.setTitle(R.string.dialog_title_result);
-                builder.setPositiveButton(R.string.OK, null);
-                builder.setMessage(R.string.button2);
-                AlertDialog diag = builder.create();
-                diag.show();
-            }
-        });
-
-        mButton2.setOnLongClickListener(new Button.OnLongClickListener() {
-            @Override
-            public boolean onLongClick(View v) {
-                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-                builder.setTitle(R.string.dialog_title_result);
-                builder.setPositiveButton(R.string.OK, null);
-                builder.setMessage(R.string.button2long);
-                AlertDialog diag = builder.create();
-                diag.show();
-                return true;
-            }
-        });
-
-        mButton3.setOnClickListener(new Button.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-                builder.setTitle(R.string.dialog_title_result);
-                builder.setPositiveButton(R.string.OK, null);
-                builder.setMessage(R.string.button3);
-                AlertDialog diag = builder.create();
-                diag.show();
-            }
-        });
-
-        mButton3.setOnLongClickListener(new Button.OnLongClickListener() {
-            @Override
-            public boolean onLongClick(View v) {
-                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-                builder.setTitle(R.string.dialog_title_result);
-                builder.setPositiveButton(R.string.OK, null);
-                builder.setMessage(R.string.button3long);
-                AlertDialog diag = builder.create();
-                diag.show();
-                return true;
-            }
-        });
-
-        mDynaButton.setOnClickListener(new Button.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                mDynaButton.setText(R.string.buttonAfter);
-                mDynaButton.setContentDescription(getString(R.string.buttonAfter));
-            }
-        });
-
-        return rootView;
-    }
-}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/Test3DetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/Test3DetailFragment.java
deleted file mode 100644
index cc76401..0000000
--- a/tests/uiautomator/app/src/com/android/uiautomator/app/Test3DetailFragment.java
+++ /dev/null
@@ -1,134 +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.uiautomator.app;
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.TextView;
-
-public class Test3DetailFragment extends Fragment {
-
-    public static final String ARG_ITEM_ID = "item_id";
-    private TextView mTextClock;
-    private Button mSubmitButton;
-    private EditText mEditText;
-    private long mCurrentTime;
-    private final Object sync = new Object();
-    private boolean mRunCounter = true;
-
-    public Test3DetailFragment() {
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setHasOptionsMenu(true);
-    }
-
-    @Override
-    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        inflater.inflate(R.menu.test2_detail_activity, menu);
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-        builder.setTitle(R.string.dialog_title_result);
-        builder.setMessage(item.getTitle());
-        builder.setPositiveButton(R.string.OK, null);
-        AlertDialog diag = builder.create();
-        diag.show();
-        return super.onOptionsItemSelected(item);
-    }
-
-    private final Handler mHandler = new Handler();
-
-    final Runnable mClockRunnable = new Runnable() {
-        @Override
-        public void run() {
-            // call the activity method that updates the UI
-            updateClockOnUi();
-        }
-    };
-
-    private void updateClockOnUi() {
-        synchronized (sync) {
-            mTextClock.setText("" + mCurrentTime);
-        }
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
-        View rootView = inflater.inflate(R.layout.test3_detail_fragment, container, false);
-        mTextClock = (TextView) rootView.findViewById(R.id.test3ClockTextView);
-        mSubmitButton = (Button) rootView.findViewById(R.id.test3SubmitButton);
-        mEditText = (EditText) rootView.findViewById(R.id.test3TextField);
-        mSubmitButton.setOnClickListener(new Button.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                // close soft keyboard
-                InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
-                        Context.INPUT_METHOD_SERVICE);
-                imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
-
-                // display the submitted text
-                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-                builder.setTitle(R.string.test3_dialog_title);
-                builder.setPositiveButton(R.string.OK, null);
-                CharSequence inputText = mEditText.getText();
-                if (inputText != null && !inputText.toString().isEmpty()) {
-                    long inputTime = Long.parseLong(inputText.toString());
-                    builder.setMessage("" + (mCurrentTime - inputTime));
-                } else {
-                    builder.setMessage("<NO DATA>");
-                }
-                AlertDialog diag = builder.create();
-                diag.show();
-                mEditText.setText("");
-                mRunCounter = false;
-            }
-        });
-
-        new Thread(new Runnable() {
-            @Override
-            public void run() {
-                while (mRunCounter) {
-                    synchronized (sync) {
-                        mCurrentTime = SystemClock.elapsedRealtime();
-                    }
-                    mHandler.post(mClockRunnable);
-                    SystemClock.sleep(100);
-                }
-            }
-        }).start();
-
-        return rootView;
-    }
-}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/Test4DetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/Test4DetailFragment.java
deleted file mode 100644
index cc7b9f8..0000000
--- a/tests/uiautomator/app/src/com/android/uiautomator/app/Test4DetailFragment.java
+++ /dev/null
@@ -1,178 +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.uiautomator.app;
-
-import android.app.ActionBar;
-import android.app.FragmentTransaction;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentPagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-public class Test4DetailFragment extends Fragment implements ActionBar.TabListener {
-    public static final String ARG_ITEM_ID = "item_id";
-
-    /**
-     * The {@link android.support.v4.view.PagerAdapter} that will provide
-     * fragments for each of the sections. We use a
-     * {@link android.support.v4.app.FragmentPagerAdapter} derivative, which
-     * will keep every loaded fragment in memory. If this becomes too memory
-     * intensive, it may be best to switch to a
-     * {@link android.support.v4.app.FragmentStatePagerAdapter}.
-     */
-    SectionsPagerAdapter mSectionsPagerAdapter;
-
-    /**
-     * The {@link ViewPager} that will host the section contents.
-     */
-    ViewPager mViewPager;
-
-    public Test4DetailFragment() {
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-    }
-
-    @Override
-    public void onDestroyView() {
-        getActivity().getActionBar().removeAllTabs();
-        super.onDestroyView();
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
-
-        View rootView = inflater.inflate(R.layout.test4_detail_fragment, container, false);
-
-        // Set up the action bar.
-        final ActionBar actionBar = getActivity().getActionBar();
-        if (actionBar.getTabCount() > 0) {
-            return rootView;
-        }
-        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
-
-        // Create the adapter that will return a fragment for each of the three
-        // primary sections of the app.
-        mSectionsPagerAdapter = new SectionsPagerAdapter(getActivity().getSupportFragmentManager());
-
-        // Set up the ViewPager with the sections adapter.
-        mViewPager = (ViewPager) rootView.findViewById(R.id.test_4_detail_container);
-        mViewPager.setAdapter(mSectionsPagerAdapter);
-
-        // When swiping between different sections, select the corresponding
-        // tab. We can also use ActionBar.Tab#select() to do this if we have a
-        // reference to the Tab.
-        mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
-            @Override
-            public void onPageSelected(int position) {
-                actionBar.setSelectedNavigationItem(position);
-            }
-        });
-
-        // For each of the sections in the app, add a tab to the action bar.
-        for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
-            // Create a tab with text corresponding to the page title defined by
-            // the adapter. Also specify this Activity object, which implements
-            // the TabListener interface, as the listener for when this tab is
-            // selected.
-            actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i))
-                    .setTabListener(this));
-        }
-        return rootView;
-    }
-
-    @Override
-    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
-    }
-
-    @Override
-    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
-    }
-
-    @Override
-    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
-    }
-
-    /**
-     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
-     * one of the primary sections of the app.
-     */
-    public class SectionsPagerAdapter extends FragmentPagerAdapter {
-
-        public SectionsPagerAdapter(FragmentManager fm) {
-            super(fm);
-        }
-
-        @Override
-        public Fragment getItem(int i) {
-            Fragment fragment = new DummySectionFragment();
-            Bundle args = new Bundle();
-            args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, i + 1);
-            fragment.setArguments(args);
-            return fragment;
-        }
-
-        @Override
-        public int getCount() {
-            return 4;
-        }
-
-        @Override
-        public CharSequence getPageTitle(int position) {
-            switch (position) {
-                case 0:
-                    return getString(R.string.title_section1).toUpperCase();
-                case 1:
-                    return getString(R.string.title_section2).toUpperCase();
-                case 2:
-                    return getString(R.string.title_section3).toUpperCase();
-                case 3:
-                    return getString(R.string.title_section4).toUpperCase();
-            }
-            return null;
-        }
-    }
-
-    /**
-     * A dummy fragment representing a section of the app, but that simply
-     * displays dummy text.
-     */
-    public static class DummySectionFragment extends Fragment {
-        public DummySectionFragment() {
-        }
-
-        public static final String ARG_SECTION_NUMBER = "section_number";
-
-        @Override
-        public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                Bundle savedInstanceState) {
-            TextView textView = new TextView(getActivity());
-            textView.setGravity(Gravity.CENTER);
-            Bundle args = getArguments();
-            textView.setText("[ " + Integer.toString(args.getInt(ARG_SECTION_NUMBER)) + " ]");
-            return textView;
-        }
-    }
-}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/Test5DetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/Test5DetailFragment.java
deleted file mode 100644
index 0e3eec4..0000000
--- a/tests/uiautomator/app/src/com/android/uiautomator/app/Test5DetailFragment.java
+++ /dev/null
@@ -1,151 +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.uiautomator.app;
-
-import android.app.AlertDialog;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.ImageButton;
-import android.widget.SeekBar;
-import android.widget.Spinner;
-
-public class Test5DetailFragment extends Fragment {
-
-    public static final String ARG_ITEM_ID = "item_id";
-
-    class PointerEvent {
-        int startX;
-        int startY;
-        int endX;
-        int endY;
-    }
-
-    private final PointerEvent mPointerEvent = new PointerEvent();
-
-    public Test5DetailFragment() {
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
-        View rootView = inflater.inflate(R.layout.test5_detail_fragment, container, false);
-
-        // Set the content description for the following
-        Spinner spinner = (Spinner) rootView.findViewById(R.id.test_5_spinner);
-        spinner.setContentDescription("Spinner");
-        ImageButton imageButton = (ImageButton) rootView.findViewById(R.id.test_5_imageButton);
-        imageButton.setContentDescription("Image button");
-
-        // Each time this view is displayed, reset the following states
-        SeekBar seekBar = (SeekBar) rootView.findViewById(R.id.test_5_seekBar);
-        seekBar.setProgress(50);
-        seekBar.setContentDescription("Progress is 50 %");
-        CheckBox checkbox = (CheckBox) rootView.findViewById(R.id.test_5_checkBox);
-        checkbox.setChecked(false);
-
-        // Register click event handlers for the following
-        Button button = (Button) rootView.findViewById(R.id.test_5_button1);
-        button.setOnClickListener(new Button.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                // we want an artificial crash
-                throw new RuntimeException("Artificial crash to test UiWatcher");
-            }
-        });
-
-        imageButton.setOnTouchListener(new ImageButton.OnTouchListener() {
-
-            @Override
-            public boolean onTouch(View v, MotionEvent event) {
-                if (event.getAction() == MotionEvent.ACTION_DOWN) {
-                    resetTouchResults();
-                    collectStartAction(event, v);
-                } else if (event.getAction() == MotionEvent.ACTION_UP) {
-                    collectEndAction(event, v);
-                    displayTouchResults();
-                }
-                return false;
-            }
-        });
-
-        return rootView;
-    }
-
-    private void displayTouchResults() {
-        StringBuilder output = new StringBuilder();
-
-        output.append(String.format("%d,%d:%d,%d\n",
-                mPointerEvent.startX, mPointerEvent.startY, mPointerEvent.endX,
-                mPointerEvent.endY));
-
-        // display the submitted text
-        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-        builder.setTitle(R.string.drag_item_touch_dialog_title);
-        builder.setPositiveButton(R.string.OK, null);
-        builder.setMessage(output.toString());
-        AlertDialog diag = builder.create();
-        diag.show();
-    }
-
-    /**
-     * Clears all collected pointer results
-     */
-    private void resetTouchResults() {
-         mPointerEvent.startX = mPointerEvent.startY =
-                    mPointerEvent.endX = mPointerEvent.endY = -1;
-    }
-
-    /**
-     * Collects pointer touch information converting from relative to absolute before
-     * storing it as starting touch coordinates.
-     *
-     * @param event
-     * @param view
-     * @param pointerIndex
-     */
-    private void collectStartAction(MotionEvent event, View view) {
-        int offsetInScreen[] = new int[2];
-        view.getLocationOnScreen(offsetInScreen);
-        mPointerEvent.startX = (int)(event.getX() + offsetInScreen[0]);
-        mPointerEvent.startY = (int)(event.getY() + offsetInScreen[1]);
-    }
-
-    /**
-     * Collects pointer touch information converting from relative to absolute before
-     * storing it as ending touch coordinates.
-     *
-     * @param event
-     * @param view
-     * @param pointerIndex
-     */
-    private void collectEndAction(MotionEvent event, View view) {
-        int offsetInScreen[] = new int[2];
-        view.getLocationOnScreen(offsetInScreen);
-        mPointerEvent.endX = (int)(event.getX() + offsetInScreen[0]);
-        mPointerEvent.endY = (int)(event.getY() + offsetInScreen[1]);
-    }
-}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/Test6DetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/Test6DetailFragment.java
deleted file mode 100644
index d1149a6..0000000
--- a/tests/uiautomator/app/src/com/android/uiautomator/app/Test6DetailFragment.java
+++ /dev/null
@@ -1,50 +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.uiautomator.app;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.webkit.WebView;
-
-public class Test6DetailFragment extends Fragment {
-    public static final String ARG_ITEM_ID = "item_id";
-    private final static String PAGE = "<html><body>"
-            + "This is test <b>6</b> for WebView text traversal test."
-            + "<p/><a href=\"http://google.com\">This is a link to google</a><br/>"
-            + "<h5>This is h5 text</h5>"
-            + "<a href=\"http://yahoo.com\">This is a link to yahoo</a>"
-            + "<p/><h4>This is h4 text</h4>" + "</body></html>";
-
-    public Test6DetailFragment() {
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
-        View rootView = inflater.inflate(R.layout.test6_detail_fragment, container, false);
-        WebView wv = (WebView) rootView.findViewById(R.id.test6WebView);
-        wv.loadData(PAGE, "text/html", null);
-        return rootView;
-    }
-}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/TestGenericDetailFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/TestGenericDetailFragment.java
deleted file mode 100644
index d87a849..0000000
--- a/tests/uiautomator/app/src/com/android/uiautomator/app/TestGenericDetailFragment.java
+++ /dev/null
@@ -1,176 +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.uiautomator.app;
-
-import android.app.AlertDialog;
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.TextView;
-
-public class TestGenericDetailFragment extends Fragment {
-    public static final String ARG_ITEM_ID = "item_id";
-    TestItems.TestItem mItem;
-
-    private class PointerEvent {
-        int startX;
-        int startY;
-        int endX;
-        int endY;
-    }
-
-    private final PointerEvent[] mPointerEvents = new PointerEvent[10];
-
-    public TestGenericDetailFragment() {
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        if (getArguments().containsKey(ARG_ITEM_ID)) {
-            mItem = TestItems.getTest(getArguments().getString(ARG_ITEM_ID));
-        }
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
-        View rootView = inflater.inflate(R.layout.test_results_detail_fragment, container, false);
-        if (mItem != null) {
-            ((TextView) rootView.findViewById(R.id.testResultsTextView)).setText(mItem.mName);
-        }
-
-        // listen to touch events to verify the multiPointerGesture APIs
-        // Since API Level 18
-        rootView.setOnTouchListener(new View.OnTouchListener() {
-            @Override
-            public boolean onTouch(View v, MotionEvent event) {
-
-                switch(event.getAction() & MotionEvent.ACTION_MASK) {
-                    case MotionEvent.ACTION_DOWN:
-                        // Reset any collected touch coordinate results on the primary touch down
-                        resetTouchResults();
-                        // collect this event
-                        collectStartAction(event, v, 0);
-                        break;
-
-                    case MotionEvent.ACTION_POINTER_DOWN:
-                        // collect this event
-                        collectStartAction(event, v, getPointerIndex(event));
-                        break;
-
-                    case MotionEvent.ACTION_POINTER_UP:
-                        // collect this event
-                        collectEndAction(event, v, getPointerIndex(event));
-                        break;
-
-                    case MotionEvent.ACTION_UP:
-                        // collect this event
-                        collectEndAction(event, v, 0);
-                        // on the primary touch up display results collected for all pointers
-                        displayTouchResults();
-                        break;
-                }
-                return true;
-            }
-        });
-
-        return rootView;
-    }
-
-    /**
-     * Displays collected results from all pointers into a dialog view in the following
-     * format: "startX,startY:endX,endY" where each line represent data for a pointer if
-     * multiple pointers (fingers) were detected.
-     */
-    private void displayTouchResults() {
-        StringBuilder output = new StringBuilder();
-        for (int x = 0; x < mPointerEvents.length; x++) {
-            if (mPointerEvents[x].startX == -1)
-                break;
-
-            output.append(String.format("%d,%d:%d,%d\n",
-                    mPointerEvents[x].startX, mPointerEvents[x].startY, mPointerEvents[x].endX,
-                    mPointerEvents[x].endY));
-        }
-
-        // display the submitted text
-        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-        builder.setTitle(R.string.generic_item_touch_dialog_title);
-        builder.setPositiveButton(R.string.OK, null);
-        builder.setMessage(output.toString());
-        AlertDialog diag = builder.create();
-        diag.show();
-    }
-
-    /**
-     * Clears all collected pointer results
-     */
-    private void resetTouchResults() {
-        for (int x = 0; x < mPointerEvents.length; x++) {
-            if (mPointerEvents[x] == null)
-                mPointerEvents[x] = new PointerEvent();
-            mPointerEvents[x].startX = mPointerEvents[x].startY =
-                    mPointerEvents[x].endX = mPointerEvents[x].endY = -1;
-        }
-    }
-
-    /**
-     * Collects pointer touch information converting from relative to absolute before
-     * storing it as starting touch coordinates.
-     *
-     * @param event
-     * @param view
-     * @param pointerIndex
-     */
-    private void collectStartAction(MotionEvent event, View view, int pointerIndex) {
-        int offsetInScreen[] = new int[2];
-        view.getLocationOnScreen(offsetInScreen);
-        mPointerEvents[getPointerId(event)].startX =
-                (int)(event.getX(pointerIndex) + offsetInScreen[0]);
-        mPointerEvents[getPointerId(event)].startY =
-                (int)(event.getY(pointerIndex) + offsetInScreen[1]);
-    }
-
-    /**
-     * Collects pointer touch information converting from relative to absolute before
-     * storing it as ending touch coordinates.
-     *
-     * @param event
-     * @param view
-     * @param pointerIndex
-     */
-    private void collectEndAction(MotionEvent event, View view, int pointerIndex) {
-        int offsetInScreen[] = new int[2];
-        view.getLocationOnScreen(offsetInScreen);
-        mPointerEvents[getPointerId(event)].endX =
-                (int)(event.getX(pointerIndex) + offsetInScreen[0]);
-        mPointerEvents[getPointerId(event)].endY =
-                (int)(event.getY(pointerIndex) + offsetInScreen[1]);
-    }
-
-    private int getPointerId(MotionEvent event) {
-        return event.getPointerId(getPointerIndex(event));
-    }
-
-    private int getPointerIndex(MotionEvent event) {
-        return ((event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
-                >> MotionEvent.ACTION_POINTER_INDEX_SHIFT);
-    }
-}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/TestItems.java b/tests/uiautomator/app/src/com/android/uiautomator/app/TestItems.java
deleted file mode 100644
index 89886fe..0000000
--- a/tests/uiautomator/app/src/com/android/uiautomator/app/TestItems.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 com.android.uiautomator.app;
-
-import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class TestItems {
-    private static String LOG_TAG = TestItems.class.getSimpleName();
-    private static List<TestItem> ITEMS = new ArrayList<TestItem>();
-    private static Map<String, TestItem> ITEM_MAP = new HashMap<String, TestItem>();
-
-    public static class TestItem {
-        public String mId;
-        public String mName;
-        private final Class<Fragment> mClassFragment;
-        public String mTestDescription;
-
-        @SuppressWarnings("unchecked")
-        public TestItem(String id, String name, Class<?> clsf) {
-            mId = id;
-            mName = name;
-            mClassFragment = (Class<Fragment>) clsf;
-        }
-
-        @Override
-        public String toString() {
-            return mName;
-        }
-    }
-
-    static {
-        addTestItem(new TestItem("1", "Test 1", Test1DetailFragment.class));
-        addTestItem(new TestItem("2", "Test 2", Test2DetailFragment.class));
-        addTestItem(new TestItem("3", "Test 3", Test3DetailFragment.class));
-        addTestItem(new TestItem("4", "Test 4", Test4DetailFragment.class));
-        addTestItem(new TestItem("5", "Test 5", Test5DetailFragment.class));
-        addTestItem(new TestItem("6", "Test 6", Test6DetailFragment.class));
-        addTestItem(new TestItem("7", "Test 7", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("8", "Test 8", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("9", "Test 9", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("10", "Test 10", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("11", "Test 11", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("12", "Test 12", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("13", "Test 13", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("14", "Test 14", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("15", "Test 15", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("16", "Test 16", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("17", "Test 17", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("18", "Test 18", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("19", "Test 19", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("20", "Test 20", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("21", "Test 21", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("22", "Test 22", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("23", "Test 23", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("24", "Test 24", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("25", "Test 25", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("26", "Test 26", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("27", "Test 27", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("28", "Test 28", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("29", "Test 29", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("30", "Test 30", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("31", "Test 31", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("32", "Test 32", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("33", "Test 33", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("34", "Test 34", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("35", "Test 35", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("36", "Test 36", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("37", "Test 37", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("38", "Test 38", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("39", "Test 39", TestGenericDetailFragment.class));
-        addTestItem(new TestItem("40", "Test 40", TestGenericDetailFragment.class));
-    }
-
-    private static void addTestItem(TestItem item) {
-        ITEMS.add(item);
-        ITEM_MAP.put(item.mId, item);
-    }
-
-    public static List<TestItem> getTests() {
-        return ITEMS;
-    }
-
-    public static TestItem getTest(String id) {
-        return ITEM_MAP.get(id);
-    }
-
-    public static TestItem getTest(int pos) {
-        return ITEMS.get(pos);
-    }
-
-    public static Fragment getFragment(String id) {
-        try {
-            Fragment fragment = getTest(id).mClassFragment.newInstance();
-            Bundle arguments = new Bundle();
-            arguments.putString("item_id", id);
-            fragment.setArguments(arguments);
-            return fragment;
-        } catch (InstantiationException e) {
-            Log.e(LOG_TAG, "Exception", e);
-            return null;
-        } catch (IllegalAccessException e) {
-            Log.e(LOG_TAG, "Exception", e);
-            return null;
-        }
-    }
-}
diff --git a/tests/uiautomator/app/src/com/android/uiautomator/app/TestListFragment.java b/tests/uiautomator/app/src/com/android/uiautomator/app/TestListFragment.java
deleted file mode 100644
index ba981cb..0000000
--- a/tests/uiautomator/app/src/com/android/uiautomator/app/TestListFragment.java
+++ /dev/null
@@ -1,105 +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.uiautomator.app;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.v4.app.ListFragment;
-import android.view.View;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-public class TestListFragment extends ListFragment {
-
-    private static final String STATE_ACTIVATED_POSITION = "activated_position";
-
-    private Callbacks mCallbacks = sDummyCallbacks;
-    private int mActivatedPosition = ListView.INVALID_POSITION;
-
-    public interface Callbacks {
-
-        public void onItemSelected(String id);
-    }
-
-    private static Callbacks sDummyCallbacks = new Callbacks() {
-        @Override
-        public void onItemSelected(String id) {
-        }
-    };
-
-    public TestListFragment() {
-    }
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setListAdapter(new ArrayAdapter<TestItems.TestItem>(getActivity(),
-                R.layout.simple_list_item_selected, R.id.label, TestItems.getTests()));
-    }
-
-    @Override
-    public void onViewCreated(View view, Bundle savedState) {
-        super.onViewCreated(view, savedState);
-        if (savedState != null && savedState.containsKey(STATE_ACTIVATED_POSITION)) {
-            setActivatedPosition(savedState.getInt(STATE_ACTIVATED_POSITION));
-        }
-    }
-
-    @Override
-    public void onAttach(Activity activity) {
-        super.onAttach(activity);
-        if (!(activity instanceof Callbacks)) {
-            throw new IllegalStateException("Activity must implement fragment's callbacks.");
-        }
-
-        mCallbacks = (Callbacks) activity;
-    }
-
-    @Override
-    public void onDetach() {
-        super.onDetach();
-        mCallbacks = sDummyCallbacks;
-    }
-
-    @Override
-    public void onListItemClick(ListView listView, View view, int position, long id) {
-        super.onListItemClick(listView, view, position, id);
-        mCallbacks.onItemSelected(TestItems.getTest(position).mId);
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        if (mActivatedPosition != ListView.INVALID_POSITION) {
-            outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
-        }
-    }
-
-    public void setActivateOnItemClick(boolean activateOnItemClick) {
-        getListView().setChoiceMode(
-                activateOnItemClick ? ListView.CHOICE_MODE_SINGLE : ListView.CHOICE_MODE_NONE);
-    }
-
-    public void setActivatedPosition(int position) {
-        if (position == ListView.INVALID_POSITION) {
-            getListView().setItemChecked(mActivatedPosition, false);
-        } else {
-            getListView().setItemChecked(position, true);
-        }
-
-        mActivatedPosition = position;
-    }
-}
diff --git a/tests/uiautomator/src/com/android/uiautomator/cts/UiAutomatorTest.java b/tests/uiautomator/src/com/android/uiautomator/cts/UiAutomatorTest.java
deleted file mode 100644
index 9873d1f..0000000
--- a/tests/uiautomator/src/com/android/uiautomator/cts/UiAutomatorTest.java
+++ /dev/null
@@ -1,1072 +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.uiautomator.cts;
-
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.util.Log;
-
-import com.android.uiautomator.core.UiCollection;
-import com.android.uiautomator.core.UiDevice;
-import com.android.uiautomator.core.UiObject;
-import com.android.uiautomator.core.UiObjectNotFoundException;
-import com.android.uiautomator.core.UiScrollable;
-import com.android.uiautomator.core.UiSelector;
-import com.android.uiautomator.core.UiWatcher;
-import com.android.uiautomator.testrunner.UiAutomatorTestCase;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Sanity test uiautomator functionality on target device.
- */
-public class UiAutomatorTest extends UiAutomatorTestCase {
-    private static final String LOG_TAG = UiAutomatorTest.class.getSimpleName();
-    private static final String[] LIST_SCROLL_TESTS = new String[] {
-            "Test 17", "Test 11", "Test 20", "Test 35"
-    };
-    private static final String PKG_NAME = "com.android.uiautomator.app";
-    private static final String LAUNCH_APP = "am start -a android.intent.action.MAIN -n "
-            + PKG_NAME + "/.MainActivity -W";
-
-    // Maximum wait for key object to become visible
-    private static final int WAIT_EXIST_TIMEOUT = 5 * 1000;
-
-    private static final String SCREEN_SHOT_FILE_PATH_NAME = "/data/local/tmp/ctsScreenShot";
-
-    // Should match the value defined in UiObject
-    private static final int FINGER_TOUCH_HALF_WIDTH = 20;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        // Make sure the test app is always running
-        UiDevice.getInstance().waitForIdle();
-        if (!new UiObject(new UiSelector().packageName(PKG_NAME)).exists())
-            runShellCommand(LAUNCH_APP);
-    }
-
-    /**
-     * Helper to execute a command on the shell
-     *
-     * @throws IOException
-     * @throws InterruptedException
-     */
-    private void runShellCommand(String command) throws IOException, InterruptedException {
-        Process p = null;
-        BufferedReader resultReader = null;
-        try {
-            p = Runtime.getRuntime().exec(command);
-            int status = p.waitFor();
-            if (status != 0) {
-                throw new RuntimeException(String.format("Run shell command: %s, status: %s",
-                        command, status));
-            }
-        } finally {
-            if (resultReader != null) {
-                resultReader.close();
-            }
-            if (p != null) {
-                p.destroy();
-            }
-        }
-    }
-
-    /*
-     * Items in the listScrollTests array should be spread out such that a
-     * scroll is required to reach each item at each of the far ends.
-     */
-    public void testListScrollAndSelect() throws UiObjectNotFoundException {
-        UiScrollable listView = new UiScrollable(
-                new UiSelector().className(android.widget.ListView.class.getName()));
-
-        // on single fragment display
-        if (!listView.exists())
-            UiDevice.getInstance().pressBack();
-
-        for (String test : LIST_SCROLL_TESTS) {
-            openTest(test);
-            verifyTestDetailsExists(test);
-        }
-    }
-
-    /**
-     * Test erasing of multi word text in edit field and input of new text. Test
-     * verifying input text using a complex UiSelector
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testTextEraseAndInput() throws UiObjectNotFoundException {
-        String testText = "Android Ui Automator Input Text";
-        openTest("Test 1");
-
-        UiObject editText = new UiObject(new UiSelector().className(android.widget.EditText.class
-                .getName()));
-        editText.setText(testText);
-
-        UiObject submitButton = new UiObject(new UiSelector()
-                .className(android.widget.Button.class.getName()).clickable(true)
-                .textStartsWith("Submit"));
-        submitButton.click();
-
-        UiObject result = new UiObject(new UiSelector().className(
-                android.widget.LinearLayout.class.getName()).childSelector(
-                (new UiSelector().className(android.widget.ScrollView.class.getName())
-                        .childSelector(new UiSelector().className(android.widget.TextView.class
-                                .getName())))));
-
-        if (!testText.equals(result.getText())) {
-            throw new UiObjectNotFoundException("Test text: " + testText);
-        }
-
-        getObjectByText("OK").click();
-    }
-
-    /**
-     * Select each of the buttons by using only the content description property
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testSelectByContentDescription() throws UiObjectNotFoundException {
-        openTest("Test 2");
-        getObjectByDescription("Button 1").click();
-        verifyDialogActionResults("Button 1");
-        getObjectByDescription("Button 2").click();
-        verifyDialogActionResults("Button 2");
-        getObjectByDescription("Button 3").click();
-        verifyDialogActionResults("Button 3");
-    }
-
-    /**
-     * Select each of the buttons by using only the text property
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testSelectByText() throws UiObjectNotFoundException {
-        openTest("Test 2");
-        getObjectByText("Button 1").click();
-        verifyDialogActionResults("Button 1");
-        getObjectByText("Button 2").click();
-        verifyDialogActionResults("Button 2");
-        getObjectByText("Button 3").click();
-        verifyDialogActionResults("Button 3");
-    }
-
-    /**
-     * Select each of the buttons by using only the index property
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testSelectByIndex() throws UiObjectNotFoundException {
-        openTest("Test 2");
-        getObjectByIndex(android.widget.Button.class.getName(), 0).click();
-        verifyDialogActionResults("Button 1");
-        getObjectByIndex(android.widget.Button.class.getName(), 1).click();
-        verifyDialogActionResults("Button 2");
-        getObjectByIndex(android.widget.Button.class.getName(), 2).click();
-        verifyDialogActionResults("Button 3");
-    }
-
-    /**
-     * Select each of the buttons by using only the instance number
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testSelectByInstance() throws UiObjectNotFoundException {
-        openTest("Test 2");
-        getObjectByInstance(android.widget.Button.class.getName(), 0).click();
-        verifyDialogActionResults("Button 1");
-        getObjectByInstance(android.widget.Button.class.getName(), 1).click();
-        verifyDialogActionResults("Button 2");
-        getObjectByInstance(android.widget.Button.class.getName(), 2).click();
-        verifyDialogActionResults("Button 3");
-    }
-
-    /**
-     * Test when a node's state is changed due to an action, it is updated in the accessibility
-     * hierarchy.
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testSelectAfterContentChanged() throws UiObjectNotFoundException {
-        openTest("Test 2");
-        UiObject dynaButton = getObjectByText("Before");
-        dynaButton.click();
-        assertTrue("Button state change is not refreshed in accessibility hierarchy",
-                getObjectByText("After").exists());
-    }
-
-    /**
-     * Test opening the options menu using the soft buttons
-     *
-     * @throws UiObjectNotFoundException
-     * @throws InterruptedException
-     * @throws IOException
-     */
-    public void testDeviceSoftKeys() throws UiObjectNotFoundException, IOException,
-            InterruptedException {
-        openTest("Test 2");
-        UiDevice device = UiDevice.getInstance();
-        device.pressMenu();
-        getObjectByText("Finish").click();
-        verifyDialogActionResults("Finish");
-
-        // Back button
-        openTest("Test 1");
-        UiObject editText = new UiObject(new UiSelector().className(android.widget.EditText.class
-                .getName()));
-        editText.setText("Android Geppetto Test Application");
-
-        UiObject submitButton = new UiObject(new UiSelector()
-                .className(android.widget.Button.class.getName()).clickable(true)
-                .textStartsWith("Submit"));
-        submitButton.click();
-
-        // Text from the popup dialog
-        UiObject result = new UiObject(new UiSelector().textContains("geppetto"));
-
-        // Back button test to dismiss the dialog
-        assertTrue("Wait for exist must return true", result.waitForExists(2000));
-        device.pressBack();
-        result.waitUntilGone(1000);
-        assertFalse("Wait for exist must return false after press back", result.exists());
-
-        // Home button test
-        openTest("Test 5");
-        String pkgName = device.getCurrentPackageName();
-        assertTrue("CTS test app must be running", pkgName.equals(PKG_NAME));
-        device.pressHome();
-        boolean gone = new UiObject(new UiSelector().packageName(PKG_NAME)).waitUntilGone(5000);
-        assertTrue("CTS test app still visble after pressing home", gone);
-    }
-
-    /**
-     * This view is in constant update generating window content changed events.
-     * The test will read the time displayed and exhaust each wait for idle
-     * timeout until it read and sets the text back into the edit field and
-     * presses submit. A dialog box should pop up with the time it took since
-     * reading the value until pressing submit.
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testWaitForIdleTimeout() throws UiObjectNotFoundException {
-        openTest("Test 3");
-        UiObject clk = new UiObject(new UiSelector().descriptionStartsWith("Performance "));
-
-        // First default wait for idle timeout assumed to be 10 seconds
-        String txtTime = clk.getText();
-        UiObject edit = new UiObject(new UiSelector().className(android.widget.EditText.class
-                .getName()));
-
-        // Second default wait for idle timeout assumed to be 10 seconds.
-        // Total ~20.
-        edit.setText(txtTime);
-
-        // Third default wait for idle timeout assumed to be 10 seconds.
-        // Total ~30.
-        getObjectByText("Submit").click();
-
-        // The value read should have value between 30 and 60 seconds indicating
-        // that the internal default timeouts for wait-for-idle is in acceptable
-        // range.
-        UiObject readTime = new UiObject(new UiSelector().className(
-                android.widget.TextView.class.getName()).instance(1));
-        String timeDiff = readTime.getText();
-        Log.i(LOG_TAG, "Sync time: " + timeDiff);
-
-        getObjectByText("OK").click();
-
-        int totalDelay = Integer.parseInt(timeDiff);
-
-        // Cumulative waits in this test should add up to at minimum 30 seconds
-        assertFalse("Timeout for wait-for-idle is too short. Expecting minimum 30 seconds",
-                totalDelay < 30 * 1000);
-
-        // allow for tolerance in time measurements due to differences between
-        // device speeds
-        assertFalse("Timeout for wait-for-idle is too long. Expecting maximum 60 seconds",
-                totalDelay > 60 * 1000);
-    }
-
-    /**
-     * This view is in constant update generating window content changed events.
-     * This test uses the soft key presses and clicks while the background
-     * screen is constantly updating causing a constant busy state.
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testVerifyMenuClicks() throws UiObjectNotFoundException {
-        openTest("Test 3");
-        UiDevice.getInstance().pressMenu();
-        new UiObject(new UiSelector().text("Submit")).click();
-        verifyDialogActionResults("Submit");
-        UiDevice.getInstance().pressMenu();
-        new UiObject(new UiSelector().text("Exit")).click();
-        verifyDialogActionResults("Exit");
-    }
-
-    /**
-     * Verifies swipeRight, swipeLeft and raw swipe APIs perform as expected.
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testSwipes() throws UiObjectNotFoundException {
-        openTest("Test 4");
-        UiObject textView = new UiObject(new UiSelector().textContains("["));
-
-        textView.swipeLeft(10);
-        assertTrue("UiObject swipe left 1->2", "[ 2 ]".equals(textView.getText()));
-
-        textView.swipeLeft(10);
-        assertTrue("UiObject swipe left 2->3", "[ 3 ]".equals(textView.getText()));
-
-        textView.swipeLeft(10);
-        assertTrue("UiObject swipe left 3->4", "[ 4 ]".equals(textView.getText()));
-
-        textView.swipeRight(10);
-        assertTrue("UiObject swipe right 3<-4", "[ 3 ]".equals(textView.getText()));
-
-        textView.swipeRight(10);
-        assertTrue("UiObject swipe right 2<-3", "[ 2 ]".equals(textView.getText()));
-
-        textView.swipeRight(10);
-        assertTrue("UiObject swipe right 1<-2", "[ 1 ]".equals(textView.getText()));
-
-        Rect tb = textView.getBounds();
-        UiDevice.getInstance().swipe(tb.right - 20, tb.centerY(), tb.left + 20, tb.centerY(), 50);
-
-        SystemClock.sleep(100);
-        assertTrue("UiDevice raw swipe 1->2", "[ 2 ]".equals(textView.getText()));
-    }
-
-    /**
-     * Creates a complex selector
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testComplexSelectors() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiSelector frameLayout = new UiSelector().className(android.widget.FrameLayout.class
-                .getName());
-        UiSelector gridLayout = new UiSelector().className(android.widget.GridLayout.class
-                .getName());
-        UiSelector toggleButton = new UiSelector().className(android.widget.ToggleButton.class
-                .getName());
-        UiObject button = new UiObject(frameLayout.childSelector(gridLayout).childSelector(
-                toggleButton));
-
-        assertTrue("Toggle button value should be OFF", "OFF".equals(button.getText()));
-        button.click();
-        assertTrue("Toggle button value should be ON", "ON".equals(button.getText()));
-        button.click();
-        assertTrue("Toggle button value should be OFF", "OFF".equals(button.getText()));
-    }
-
-    /**
-     * Test when an object does not exist, an exception is thrown
-     * @throws UiObjectNotFoundException
-     */
-    public void testExceptionObjectNotFound() throws UiObjectNotFoundException {
-        UiSelector selector = new UiSelector().text("Nothing should be found");
-        UiSelector child = new UiSelector().className("Nothing");
-        UiObject obj = new UiObject(selector.childSelector(child));
-
-        assertFalse("Object is reported as existing", obj.exists());
-
-        try {
-            obj.click();
-        } catch (UiObjectNotFoundException e) {
-            return;
-        }
-        assertTrue("Exception not thrown for Object not found", false);
-    }
-
-    /**
-     * Verifies the UiWatcher registration and trigger function
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testUiWatcher() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiDevice device = UiDevice.getInstance();
-        device.registerWatcher("Artificial crash", new UiWatcher() {
-
-            @Override
-            public boolean checkForCondition() {
-                if (new UiObject(new UiSelector().packageName("android")).exists()) {
-                    try {
-                        // Expecting a localized OK button
-                        new UiObject(new UiSelector().className(
-                                android.widget.Button.class.getName()).enabled(true)).click();
-                    } catch (UiObjectNotFoundException e) {
-                    }
-                    return true;
-                }
-                return false;
-            }
-        });
-
-        // Causes a runtime exception to be thrown
-        getObjectByText("Button").click();
-
-        // Fake doing something while the exception is being displayed
-        SystemClock.sleep(2000);
-        device.runWatchers();
-        assertTrue("UiWatcher not triggered", device.hasAnyWatcherTriggered());
-    }
-
-    /**
-     * Verifies the 'checked' property of both UiSelector and UiObject
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testSelectorChecked() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiObject checkboxChecked = new UiObject(new UiSelector().className(
-                android.widget.CheckBox.class.getName()).checked(true));
-        UiObject checkboxNotChecked = new UiObject(new UiSelector().className(
-                android.widget.CheckBox.class.getName()).checked(false));
-
-        checkboxNotChecked.click();
-        assertTrue("Checkbox should be checked", checkboxChecked.isChecked());
-        checkboxChecked.click();
-        assertFalse("Checkbox should be unchecked", checkboxNotChecked.isChecked());
-    }
-
-    /**
-     * Verifies the 'Clickable' property of both the UiSelector and UiObject
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testSelectorClickable() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiSelector clickableCheckbox = new UiSelector().clickable(true).className(
-                android.widget.CheckBox.class.getName());
-        UiSelector notClickableProgress = new UiSelector().clickable(false).className(
-                android.widget.ProgressBar.class.getName());
-
-        assertTrue("Selector clickable", new UiObject(clickableCheckbox).isClickable());
-        assertFalse("Selector not clickable", new UiObject(notClickableProgress).isClickable());
-    }
-
-    /**
-     * Verifies the 'focusable' property of both UiSelector and UiObject
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testSelectorFocusable() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiSelector mainLayout = new UiSelector().description("Widgets Collection");
-        UiSelector focusableCheckbox = mainLayout.childSelector(new UiSelector().className(
-                android.widget.CheckBox.class.getName()).focusable(true));
-        UiSelector notFocusableSpinner = mainLayout.childSelector(new UiSelector().className(
-                android.widget.Spinner.class.getName()).focusable(false));
-
-        assertTrue("Selector focusable", new UiObject(focusableCheckbox).isFocusable());
-        assertFalse("Selector not focusable", new UiObject(notFocusableSpinner).isFocusable());
-    }
-
-    /**
-     * Verifies the 'DescriptionContains' property of UiSelector
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testSelectorDescriptionContains() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiSelector progressDescriptionContains = new UiSelector().descriptionContains("%");
-        assertTrue("Selector descriptionContains", "Progress is 50 %".equals(new UiObject(
-                progressDescriptionContains).getContentDescription()));
-    }
-
-    /**
-     * Verifies the 'DescriptionStarts' property of UiSelector
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testSelectorDescriptionStarts() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiSelector progressDescriptionStart = new UiSelector().descriptionStartsWith("progress");
-        assertTrue("Selector descriptionStart", "Progress is 50 %".equals(new UiObject(
-                progressDescriptionStart).getContentDescription()));
-    }
-
-    /**
-     * Verifies the 'Enabled' property of both UiSelector and UiObject
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testSelectorEnabled() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiSelector mainLayout = new UiSelector().description("Widgets Collection");
-        UiSelector buttonDisabled = mainLayout.childSelector(new UiSelector().className(
-                android.widget.Button.class.getName()).enabled(false));
-        UiSelector buttonEnabled = mainLayout.childSelector(new UiSelector().className(
-                android.widget.Button.class.getName()).enabled(true));
-
-        assertFalse("Selector enabled false", new UiObject(buttonDisabled).isEnabled());
-        assertTrue("Selector enabled true", new UiObject(buttonEnabled).isEnabled());
-    }
-
-    /**
-     * Verifies the UiCollection object child counting by object pattern
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testCollectionCount() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiCollection collection = new UiCollection(
-                new UiSelector().description("Widgets Collection"));
-        assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
-
-        assertTrue("Collection count",
-                collection.getChildCount(new UiSelector().clickable(true)) == 6);
-    }
-
-    /**
-     * Verifies the UiCollection can find an object by text and returning by
-     * pattern
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testCollectionGetChildByText() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiCollection collection = new UiCollection(
-                new UiSelector().description("Widgets Collection"));
-        assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
-
-        UiObject item = collection.getChildByText(
-                new UiSelector().className(android.widget.Button.class.getName()), "Button");
-
-        assertTrue("Collection get child by text", "Button".equals(item.getText()));
-    }
-
-    /**
-     * Verifies the UiCollection can find an object by instance and returning by
-     * pattern
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testCollectionGetChildByInstance() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiCollection collection = new UiCollection(
-                new UiSelector().description("Widgets Collection"));
-        assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
-
-        // find the second button
-        UiObject item = collection.getChildByInstance(
-                new UiSelector().className(android.widget.Button.class.getName()), 1);
-
-        assertTrue("Collection get child by instance", "Button".equals(item.getText()));
-    }
-
-    /**
-     * Verifies the UiCollection can find an object by description and returning
-     * by pattern
-     *
-     * @throws UiObjectNotFoundException
-     */
-    public void testCollectionGetChildByDescription() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiCollection collection = new UiCollection(
-                new UiSelector().description("Widgets Collection"));
-        assertTrue("Collection layout not found", collection.waitForExists(WAIT_EXIST_TIMEOUT));
-
-        UiObject item = collection.getChildByDescription(
-                new UiSelector().className(android.widget.Button.class.getName()),
-                "Description for Button");
-
-        assertTrue("Collection get child by description", "Button".equals(item.getText()));
-    }
-
-    /**
-     * Test Orientation APIs by causing rotations and verifying current state
-     *
-     * @throws RemoteException
-     * @throws UiObjectNotFoundException
-     * @since API Level 17
-     */
-    public void testRotation() throws RemoteException, UiObjectNotFoundException {
-        openTest("Test 5");
-        UiDevice device = UiDevice.getInstance();
-
-        device.setOrientationLeft();
-        device.waitForIdle(); // isNaturalOrientation is not waiting for idle
-        SystemClock.sleep(1000);
-        assertFalse("Device orientation should not be natural", device.isNaturalOrientation());
-
-        device.setOrientationNatural();
-        device.waitForIdle(); // isNaturalOrientation is not waiting for idle
-        SystemClock.sleep(1000);
-        assertTrue("Device orientation should be natural", device.isNaturalOrientation());
-
-        device.setOrientationRight();
-        device.waitForIdle(); // isNaturalOrientation is not waiting for idle
-        SystemClock.sleep(1000);
-        assertFalse("Device orientation should not be natural", device.isNaturalOrientation());
-
-        device.setOrientationNatural();
-    }
-
-    /**
-     * Reads the current device's product name. Since it is not possible to predetermine the
-     * would be value, the check verifies that the value is not null and not empty.
-     *
-     * @since API Level 17
-     */
-    public void testGetProductName() {
-        String name = UiDevice.getInstance().getProductName();
-        assertFalse("Product name check returned empty string", name.isEmpty());
-    }
-
-    /**
-     * Select each of the buttons by using only regex text
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 17
-     */
-    public void testSelectByTextMatch() throws UiObjectNotFoundException {
-        openTest("Test 2");
-        getObjectByTextMatch(".*n\\s1$").click();
-        verifyDialogActionResults("Button 1");
-        getObjectByTextMatch(".*n\\s2$").click();
-        verifyDialogActionResults("Button 2");
-        getObjectByTextMatch(".*n\\s3$").click();
-        verifyDialogActionResults("Button 3");
-    }
-
-    /**
-     * Select each of the buttons by using only regex content-description
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 17
-     */
-    public void testSelectByDescriptionMatch() throws UiObjectNotFoundException {
-        openTest("Test 2");
-        getObjectByDescriptionMatch(".*n\\s1$").click();
-        verifyDialogActionResults("Button 1");
-        getObjectByDescriptionMatch(".*n\\s2$").click();
-        verifyDialogActionResults("Button 2");
-        getObjectByDescriptionMatch(".*n\\s3$").click();
-        verifyDialogActionResults("Button 3");
-    }
-
-    /**
-     * Select each of the buttons by using only regex class name
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 17
-     */
-    public void testSelectByClassMatch() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiObject tgl = getObjectByClassMatch(".*ToggleButton$", 0);
-        String tglValue = tgl.getText();
-        tgl.click();
-
-        assertFalse("Matching class by Regex failed", tglValue.equals(tgl.getText()));
-    }
-
-    /**
-     * Select each of the buttons by using only class type
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 17
-     */
-    public void testSelectByClassType() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiObject tgl = getObjectByClass(android.widget.ToggleButton.class, 0);
-        String tglValue = tgl.getText();
-        tgl.click();
-
-        assertFalse("Matching class by class type failed", tglValue.equals(tgl.getText()));
-    }
-
-    /**
-     * Test the coordinates of 3 buttons side by side verifying vertical and
-     * horizontal coordinates.
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 17
-     */
-    public void testGetVisibleBounds() throws UiObjectNotFoundException {
-        openTest("Test 2");
-        Rect rect1 = getObjectByText("Button 1").getVisibleBounds();
-        Rect rect2 = getObjectByText("Button 2").getVisibleBounds();
-        Rect rect3 = getObjectByText("Button 3").getVisibleBounds();
-
-        assertTrue("X coordinate check failed",
-                rect1.left < rect2.left && rect2.right < rect3.right);
-        assertTrue("Y coordinate check failed",
-                rect1.top == rect2.top && rect2.bottom == rect3.bottom);
-    }
-
-   /**
-     * Tests the LongClick functionality in the API
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 17
-     */
-    public void testSelectorLongClickable() throws UiObjectNotFoundException {
-        openTest("Test 2");
-        getObjectByText("Button 1").longClick();
-        verifyDialogActionResults("Longclick Button 1");
-    }
-
-    /**
-     * Test the UiSelector's long-clickable property
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 17
-     */
-    public void testSelectorLongClickableProperty() throws UiObjectNotFoundException {
-        openTest("Test 2");
-        UiObject button3 = new UiObject(new UiSelector().className(
-                android.widget.Button.class).longClickable(true).instance(2));
-        button3.longClick();
-        verifyDialogActionResults("Longclick Button 3");
-    }
-
-    /**
-     * Takes a screen shot of the current display and checks if the file is
-     * created and is not zero size.
-     *
-     * @since API Level 17
-     */
-    public void testTakeScreenShots() {
-        File storePath = new File(SCREEN_SHOT_FILE_PATH_NAME);
-        getUiDevice().takeScreenshot(storePath);
-
-        assertTrue("Screenshot file not detected in store", storePath.exists());
-        assertTrue("Zero size for screenshot file", storePath.length() > 0);
-    }
-
-    /**
-     * Verifies the 'Resource-Id' property of UiSelector
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 18
-     */
-    public void testSelectorResourceId() throws UiObjectNotFoundException {
-        openTest("Test 5");
-        UiSelector toggleSelector =
-                new UiSelector().resourceId("com.android.uiautomator.app:id/test_5_toggleButton");
-        UiObject toggleButton = new UiObject(toggleSelector);
-        assertTrue("Object with selector resource-id not found", toggleButton.exists());
-        assertTrue("Incorrect object for selector resource-id returned",
-                "OFF".equals(toggleButton.getText()) || "ON".equals(toggleButton.getText()));
-    }
-
-    /**
-     * Verify the UiSelector property resourceIdMatches
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 18
-     */
-    public void testSelectorResourceIdMatches() throws UiObjectNotFoundException {
-        openTest("Test 2");
-        new UiObject(new UiSelector().resourceIdMatches("(?i).*button.*").instance(2)).click();
-        verifyDialogActionResults("Button 3");
-        new UiObject(new UiSelector().resourceIdMatches("(?i).*button1.*")).click();
-        verifyDialogActionResults("Button 1");
-    }
-
-    /**
-     * Performs a pinch out from the center of a view to its edges and listens to
-     * the motion events to make sure the starting and ending points of both pointers
-     * are correct.
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 18
-     */
-    public void testPinchOut() throws UiObjectNotFoundException {
-        openTest("Test 12");
-
-        UiObject screen = new UiObject(
-                new UiSelector().description("Details View"));
-
-        // get the current view dimensions
-        Rect screenRect = screen.getBounds();
-
-        // perform the pinch for 100% of the view dimensions starting form
-        // the center out to the edges.
-        screen.pinchOut(100, 30);
-
-        // dialog with the detected pointers motion coordinates is displayed.
-        UiObject results = new UiObject(new UiSelector().className(
-                android.widget.ScrollView.class).childSelector(new UiSelector().className(
-                        android.widget.TextView.class)));
-        String allPointers = results.getText();
-        new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
-
-        // parse pointer 1
-        Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
-        Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
-        // parse pointer 2
-        Point p2s = parsePointerCoordinates(allPointers, 1, 0); // start
-        Point p2e = parsePointerCoordinates(allPointers, 1, 1); // end
-
-        assertTrue("All Y axis coordinates for pointer 1 must be the same", p1s.y == p1e.y);
-        assertTrue("All Y axis coordinates for pointer 2 must be the same", p2s.y == p2e.y);
-        assertTrue("All Y axis coordinates for both pointers must be the same", p1s.y == p2s.y);
-        assertTrue("Pinch must be in center of target view", p2s.y == screenRect.centerY());
-
-        assertTrue("Touch-down X coordinate for pointer 1 is invalid",
-                withinMarginOfError(0.125f, screenRect.centerX(), p1s.x));
-
-        assertTrue("Touch-down X coordinate for pointer 2 is invalid",
-                withinMarginOfError(0.125f, screenRect.centerX(), p2s.x));
-
-        assertTrue("Touch-up X coordinate for pointer 1 is invalid",
-                withinMarginOfError(0.125f, screenRect.centerX() - screenRect.left,
-                        screenRect.centerX() - p1e.x));
-
-        assertTrue("Touch-up X coordinate for pointer 2 is invalid",
-                withinMarginOfError(0.125f, screenRect.right, p2e.x));
-    }
-
-    /**
-     * Performs a pinch in from the edges of a view to its center and listens to
-     * the motion events to make sure the starting and ending points of both pointers
-     * are correct.
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 18
-     */
-    public void testPinchIn() throws UiObjectNotFoundException {
-        openTest("Test 12");
-
-        UiObject screen = new UiObject(
-                new UiSelector().description("Details View"));
-
-        // get the current view dimensions
-        Rect screenRect = screen.getBounds();
-
-        // perform the pinch for 100% of the view dimensions starting form
-        // the edges in towards the center.
-        screen.pinchIn(100, 30);
-
-        // dialog with the detected pointers motion coordinates is displayed.
-        UiObject results = new UiObject(new UiSelector().className(
-                android.widget.ScrollView.class).childSelector(new UiSelector().className(
-                        android.widget.TextView.class)));
-        String allPointers = results.getText();
-        new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
-
-        // parse pointer 1
-        Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
-        Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
-        // parse pointer 2
-        Point p2s = parsePointerCoordinates(allPointers, 1, 0); // start
-        Point p2e = parsePointerCoordinates(allPointers, 1, 1); // end
-
-        assertTrue("All Y axis coordinates for pointer 1 must be the same", p1s.y == p1e.y);
-        assertTrue("All Y axis coordinates for pointer 2 must be the same", p2s.y == p2e.y);
-        assertTrue("All Y axis coordinates for both pointers must be the same", p1s.y == p2s.y);
-        assertTrue("Pinch must be in center of target view", p2s.y == screenRect.centerY());
-
-        assertTrue("Touch-down X coordinate for pointer 1 is invalid",
-                withinMarginOfError(0.125f, screenRect.centerX() - screenRect.left,
-                        screenRect.centerX() -  p1s.x));
-
-        assertTrue("Touch-down X coordinate for pointer 2 is invalid",
-                withinMarginOfError(0.125f, screenRect.right, p2s.x));
-
-        assertTrue("Touch-up X coordinate for pointer 1 is invalid",
-                withinMarginOfError(0.125f, screenRect.centerX() - FINGER_TOUCH_HALF_WIDTH, p1e.x));
-
-        assertTrue("Touch-up X coordinate for pointer 2 is invalid",
-                withinMarginOfError(0.125f, screenRect.centerX() + FINGER_TOUCH_HALF_WIDTH, p2e.x));
-    }
-
-    /**
-     * Performs a drag and drop operation from one UiObject to another UiObject
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 18
-     */
-    public void testDragToObject() throws UiObjectNotFoundException {
-        openTest("Test 5");
-
-        UiObject imageButton = new UiObject(new UiSelector().description("Image button"));
-        UiObject starsBar = new UiObject(new UiSelector().className(android.widget.RatingBar.class));
-
-        Rect starsBarRect = starsBar.getBounds();
-        Rect imageButtonRect = imageButton.getBounds();
-        imageButton.dragTo(starsBar, 30);
-
-        // dialog with the detected pointers motion coordinates is displayed.
-        UiObject results = new UiObject(new UiSelector().className(
-                android.widget.ScrollView.class).childSelector(new UiSelector().className(
-                        android.widget.TextView.class)));
-        String allPointers = results.getText();
-        new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
-
-        // parse pointer 1
-        Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
-        Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
-
-        assertTrue("Invalid touch starting.X reported",
-                withinMarginOfError(0.05f, imageButtonRect.centerX(), p1s.x));
-        assertTrue("Invalid touch starting.Y reported",
-                withinMarginOfError(0.05f, imageButtonRect.centerY(), p1s.y));
-        assertTrue("Invalid touch ending.X reported",
-                withinMarginOfError(0.05f, starsBarRect.centerX(), p1e.x));
-        assertTrue("Invalid touch ending.Y reported",
-                withinMarginOfError(0.05f, starsBarRect.centerY(), p1e.y));
-    }
-
-    /**
-     * Performs a drag and drop operation from one UiObject to a specified coordinates
-     *
-     * @throws UiObjectNotFoundException
-     * @since API Level 18
-     */
-   public void testDragToCoordinates() throws UiObjectNotFoundException {
-       openTest("Test 5");
-
-       UiObject imageButton = new UiObject(new UiSelector().description("Image button"));
-       UiObject starsBar = new UiObject(new UiSelector().className(android.widget.RatingBar.class));
-
-       Rect starsBarRect = starsBar.getBounds();
-       Rect imageButtonRect = imageButton.getBounds();
-       imageButton.dragTo(starsBarRect.centerX(), starsBarRect.centerY(), 30);
-
-       // dialog with the detected pointers motion coordinates is displayed.
-       UiObject results = new UiObject(new UiSelector().className(
-               android.widget.ScrollView.class).childSelector(new UiSelector().className(
-                       android.widget.TextView.class)));
-       String allPointers = results.getText();
-       new UiObject(new UiSelector().text("OK")).click(); // dismiss dialog
-
-       // parse pointer 1
-       Point p1s = parsePointerCoordinates(allPointers, 0, 0); // start
-       Point p1e = parsePointerCoordinates(allPointers, 0, 1); // end
-
-       assertTrue("Invalid touch starting.X reported",
-               withinMarginOfError(0.05f, imageButtonRect.centerX(), p1s.x));
-       assertTrue("Invalid touch starting.Y reported",
-               withinMarginOfError(0.05f, imageButtonRect.centerY(), p1s.y));
-       assertTrue("Invalid touch ending.X reported",
-               withinMarginOfError(0.05f, starsBarRect.centerX(), p1e.x));
-       assertTrue("Invalid touch ending.Y reported",
-               withinMarginOfError(0.05f, starsBarRect.centerY(), p1e.y));
-   }
-
-   /**
-    * Detect if actual value is within the allowable margin of error of the expected value.
-    *
-    * Used essentially with actual values that may vary from the expected values such in the
-    * cases of touch and pinch and touch and swipe where the starting or ending points may
-    * not exactly match the expected value.
-    *
-    * @param marginPrecent is values between 0 and 1
-    * @param expected
-    * @param actual
-    * @return true if actual is within the allowed range from expected
-    */
-   private boolean withinMarginOfError(float marginPrecent, int expected, int actual) {
-       int m = (int) (marginPrecent * expected);
-       return actual >= expected - m && actual <= expected + m;
-   }
-
-   /**
-     * Parses a string containing starting to ending coordinates of one or more pointers.
-     *
-     * @param allPointers is a raw string with coordinates from all detected pointers
-     * @param pointerNumber is the desired pointer to be parsed
-     * @param edge is the 0 for the start or 1 for the end of the swipe
-     * @return Point containing the start or end coordinates of the specified pointer number
-     */
-    private Point parsePointerCoordinates(String allPointers, int pointerNumber, int edge) {
-        String pointers[] = allPointers.split("\n");
-        String coordinates = pointers[pointerNumber].split(":")[edge];
-        String xy[] = coordinates.split(",");
-        return new Point(Integer.parseInt(xy[0]), Integer.parseInt(xy[1]));
-    }
-
-    /**
-     * Private helper to open test views. Also covers UiScrollable tests
-     *
-     * @param name
-     * @throws UiObjectNotFoundException
-     */
-    private void openTest(String name) throws UiObjectNotFoundException {
-        try {
-            UiDevice.getInstance().setOrientationNatural();
-        } catch (RemoteException e) {
-            // will catch it in its own test. For now try to put the device
-            // in its natural orientation prior to each test
-        }
-        UiScrollable listView = new UiScrollable(
-                new UiSelector().className(android.widget.ListView.class.getName()));
-
-        // on single fragment display
-        if (!listView.exists())
-            UiDevice.getInstance().pressBack();
-
-        UiObject testItem = listView.getChildByText(
-                new UiSelector().className(android.widget.TextView.class.getName()), name);
-
-        testItem.click();
-    }
-
-    private void verifyTestDetailsExists(String name) throws UiObjectNotFoundException {
-        // verify that we're at the right test
-        new UiObject(new UiSelector().description("Details").text(name)).getText();
-    }
-
-    private UiObject getObjectByText(String txt) {
-        return new UiObject(new UiSelector().text(txt));
-    }
-
-    private UiObject getObjectByTextMatch(String regex) {
-        return new UiObject(new UiSelector().textMatches(regex));
-    }
-
-    private UiObject getObjectByDescriptionMatch(String regex) {
-        return new UiObject(new UiSelector().descriptionMatches(regex));
-    }
-
-    private UiObject getObjectByDescription(String txt) {
-        return new UiObject(new UiSelector().description(txt));
-    }
-
-    private UiObject getObjectByClassMatch(String regex, int instance) {
-        return new UiObject(new UiSelector().classNameMatches(regex).instance(instance));
-    }
-
-    private <T> UiObject getObjectByClass(Class<T> type, int instance) {
-        return new UiObject(new UiSelector().className(type).instance(instance));
-    }
-
-    private UiObject getObjectByIndex(String className, int index) {
-        return new UiObject(new UiSelector().className(className).index(index));
-    }
-
-    private UiObject getObjectByInstance(String className, int instance) {
-        return new UiObject(new UiSelector().className(className).instance(instance));
-    }
-
-    private void verifyDialogActionResults(String txt) throws UiObjectNotFoundException {
-        if (!getObjectByText("Action results").exists() || !getObjectByText(txt).exists()) {
-            throw new UiObjectNotFoundException(txt);
-        }
-        getObjectByText("OK").click();
-    }
-}
diff --git a/tools/selinux/SELinuxNeverallowTestFrame.py b/tools/selinux/SELinuxNeverallowTestFrame.py
index 6f2613b..ee14116 100644
--- a/tools/selinux/SELinuxNeverallowTestFrame.py
+++ b/tools/selinux/SELinuxNeverallowTestFrame.py
@@ -18,25 +18,22 @@
 
 package android.cts.security;
 
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 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 com.android.tradefed.testtype.IDeviceTest;
 
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.io.FileOutputStream;
-import java.lang.String;
-import java.net.URL;
-import java.util.Scanner;
 
 /**
  * Neverallow Rules SELinux tests.
  */
-public class SELinuxNeverallowRulesTest extends DeviceTestCase {
+public class SELinuxNeverallowRulesTest extends DeviceTestCase implements IBuildReceiver, IDeviceTest {
     private File sepolicyAnalyze;
     private File devicePolicyFile;
 
@@ -45,27 +42,28 @@
      */
     private ITestDevice mDevice;
 
-    private File copyResourceToTempFile(String resName) throws IOException {
-        InputStream is = this.getClass().getResourceAsStream(resName);
-        File tempFile = File.createTempFile("SELinuxHostTest", ".tmp");
-        FileOutputStream os = new FileOutputStream(tempFile);
-        int rByte = 0;
-        while ((rByte = is.read()) != -1) {
-            os.write(rByte);
-        }
-        os.flush();
-        os.close();
-        tempFile.deleteOnExit();
-        return tempFile;
+    private CompatibilityBuildHelper mHelper;
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setBuild(IBuildInfo build) {
+        mHelper = new CompatibilityBuildHelper(build);
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setDevice(ITestDevice device) {
+        super.setDevice(device);
+        mDevice = device;
+    }
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mDevice = getDevice();
-
-        /* retrieve the sepolicy-analyze executable from jar */
-        sepolicyAnalyze = copyResourceToTempFile("/sepolicy-analyze");
+        sepolicyAnalyze = new File(mHelper.getTestsDir(), "sepolicy-analyze");
         sepolicyAnalyze.setExecutable(true);
 
         /* obtain sepolicy file from running device */
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 b68073d..1234893 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
@@ -17,7 +17,6 @@
 package com.android.cts.tradefed.testtype;
 
 import com.android.compatibility.common.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.targetprep.ITargetPreparer;
@@ -54,7 +53,6 @@
     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 UIAUTOMATOR_TEST = "uiAutomator";
     public static final String JUNIT_DEVICE_TEST = "jUnitDeviceTest";
 
     private String mAppPackageName = null;
@@ -270,10 +268,6 @@
             WrappedGTest wrappedGeeTest = new WrappedGTest(mAppNameSpace, mAppPackageName, mName, mRunner);
             wrappedGeeTest.setAbi(mAbi);
             return wrappedGeeTest;
-        } else if (UIAUTOMATOR_TEST.equals(mTestType)) {
-            UiAutomatorJarTest uiautomatorTest = new UiAutomatorJarTest();
-            uiautomatorTest.setRunName(getId());
-            return setUiAutomatorTest(uiautomatorTest);
         } else if (JUNIT_DEVICE_TEST.equals(mTestType)){
             CLog.d("Creating JUnit device test %s", mName);
             JUnitDeviceTest jUnitDeviceTest = new JUnitDeviceTest();
@@ -320,29 +314,6 @@
     }
 
     /**
-     * Populates given {@link UiAutomatorJarTest} with data from the package xml.
-     *
-     * @param uiautomatorTest
-     * @return the populated {@link UiAutomatorJarTest} or <code>null</code>
-     */
-    @SuppressWarnings("deprecation")
-    private IRemoteTest setUiAutomatorTest(UiAutomatorJarTest uiautomatorTest) {
-        uiautomatorTest.setInstallArtifacts(getJarPath());
-        if (mClassName != null) {
-            if (mMethodName != null) {
-                CLog.logAndDisplay(LogLevel.WARN, "ui automator tests don't currently support" +
-                        "running  individual methods");
-            }
-            uiautomatorTest.addClassName(mClassName);
-        } else {
-            uiautomatorTest.addClassNames(mTestClasses);
-        }
-        uiautomatorTest.setRunName(getId());
-        uiautomatorTest.setCaptureLogs(false);
-        return uiautomatorTest;
-    }
-
-    /**
      * Filter the tests to run based on list of included/excluded tests, class and method name.
      *
      * @return the filtered collection of tests
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/UiAutomatorJarTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/UiAutomatorJarTest.java
deleted file mode 100644
index 83cc6d6..0000000
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/UiAutomatorJarTest.java
+++ /dev/null
@@ -1,97 +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.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.testtype.IBuildReceiver;
-import com.android.tradefed.testtype.UiAutomatorTest;
-
-import java.io.FileNotFoundException;
-import java.util.Arrays;
-
-import junit.framework.Assert;
-
-/**
- * A {@link UiAutomatorTest} that will install a uiautomator jar before test
- * execution, and uninstall on execution completion.
- */
-public class UiAutomatorJarTest extends UiAutomatorTest implements IBuildReceiver {
-
-    // TODO: expose this in parent
-    private static final String SHELL_EXE_BASE = "/data/local/tmp/";
-
-    /** the file names of the CTS jar to install */
-    private String mTestJarFileName;
-
-    private CtsBuildHelper mCtsBuild = null;
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void setBuild(IBuildInfo build) {
-        mCtsBuild  = CtsBuildHelper.createBuildHelper(build);
-    }
-
-    /**
-     * Setter for CTS build files needed to perform the test. 
-     *
-     * @param testJarName the file name of the jar containing the uiautomator tests
-     */
-    public void setInstallArtifacts(String testJarName) {
-        mTestJarFileName = testJarName;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void run(final ITestInvocationListener listener)
-            throws DeviceNotAvailableException {
-        Assert.assertNotNull("missing device", getDevice());
-        Assert.assertNotNull("missing build", mCtsBuild);
-        Assert.assertNotNull("missing jar to install", mTestJarFileName);
-
-        installJar();
-
-        super.run(listener);
-
-        uninstallJar();
-    }
-
-    private void installJar() throws DeviceNotAvailableException {
-        CLog.d("Installing %s on %s", mTestJarFileName, getDevice().getSerialNumber());
-        String fullJarPath = String.format("%s%s", SHELL_EXE_BASE, mTestJarFileName);
-        try {
-            boolean result = getDevice().pushFile(mCtsBuild.getTestApp(mTestJarFileName),
-                    fullJarPath);
-            Assert.assertTrue(String.format("Failed to push file to %s", fullJarPath), result);
-            setTestJarPaths(Arrays.asList(fullJarPath));
-        }  catch (FileNotFoundException e) {
-            Assert.fail(String.format("Could not find file %s", mTestJarFileName));
-        }
-    }
-
-    private void uninstallJar() throws DeviceNotAvailableException {
-        CLog.d("Uninstalling %s on %s", mTestJarFileName, getDevice().getSerialNumber());
-        String fullJarPath = String.format("%s%s", SHELL_EXE_BASE, mTestJarFileName);
-        getDevice().executeShellCommand(String.format("rm %s", fullJarPath));
-    }
-}