Add missing functions and tests for support library.

Missing functions:
rsFrac(float)
rsMatrixLoadRotate(rs_matrix4x4 *, float, float, float, float)
rsMatrixLoadScale(rs_matrix4x4 *, float, float, float)
rsMatrixLoadTranslate(rs_matrix4x4 *, float, float, float)
rsMatrixRotate(rs_matrix4x4 *, float, float, float, float)
rsMatrixScale(rs_matrix4x4 *, float, float, float)
rsMatrixTranslate(rs_matrix4x4 *, float, float, float)
rsMatrixLoadOrtho(rs_matrix4x4 *, float, float, float, float, float, float)
rsMatrixLoadFrustum(rs_matrix4x4 *, float, float, float, float, float, float)
rsMatrixLoadPerspective(rs_matrix4x4 *, float, float, float, float)
rsMatrixInverse(rs_matrix4x4 *)
rsMatrixInverseTranspose(rs_matrix4x4 *)
rsMatrixTranspose(rs_matrix4x4 *)
rsMatrixTranspose(rs_matrix3x3 *)
rsMatrixTranspose(rs_matrix2x2 *)
rsUptimeNanos()
rsGetDt()

Headers tested in this CL:
rs_element.rsh
rs_math.rsh
rs_matrix.rsh
rs_object.rsh
rs_sampler.rsh
rs_time.rsh

Change-Id: I6cb1972a44f66dc7fed8fe3cf0329720d166af81
diff --git a/cpu_ref/rsCpuRuntimeMath.cpp b/cpu_ref/rsCpuRuntimeMath.cpp
index 0aaadd4..66bd576 100644
--- a/cpu_ref/rsCpuRuntimeMath.cpp
+++ b/cpu_ref/rsCpuRuntimeMath.cpp
@@ -159,6 +159,60 @@
 EXPORT_F32_FN_F32(tanf)
 EXPORT_F32_FN_F32(tanhf)
 EXPORT_F32_FN_F32(truncf)
+float __attribute__((overloadable)) rsFrac(float f) {
+    return SC_frac(f);
+}
+void __attribute__((overloadable)) rsMatrixLoadRotate(rs_matrix4x4 *m,
+        float rot, float x, float y, float z) {
+    SC_MatrixLoadRotate((Matrix4x4 *) m, rot, x, y, z);
+}
+void __attribute__((overloadable)) rsMatrixLoadScale(rs_matrix4x4 *m,
+        float x, float y, float z) {
+    SC_MatrixLoadScale((Matrix4x4 *) m, x, y, z);
+}
+void __attribute__((overloadable)) rsMatrixLoadTranslate(rs_matrix4x4 *m,
+        float x, float y, float z) {
+    SC_MatrixLoadTranslate((Matrix4x4 *) m, x, y, z);
+}
+void __attribute__((overloadable)) rsMatrixRotate(rs_matrix4x4 *m, float rot,
+        float x, float y, float z) {
+    SC_MatrixRotate((Matrix4x4 *) m, rot, x, y, z);
+}
+void __attribute__((overloadable)) rsMatrixScale(rs_matrix4x4 *m, float x,
+        float y, float z) {
+    SC_MatrixScale((Matrix4x4 *) m, x, y, z);
+}
+void __attribute__((overloadable)) rsMatrixTranslate(rs_matrix4x4 *m, float x,
+        float y, float z) {
+    SC_MatrixTranslate((Matrix4x4 *) m, x, y, z);
+}
+void __attribute__((overloadable)) rsMatrixLoadOrtho(rs_matrix4x4 *m, float l,
+        float r, float b, float t, float n, float f) {
+    SC_MatrixLoadOrtho((Matrix4x4 *) m, l, r, b, t, n, f);
+}
+void __attribute__((overloadable)) rsMatrixLoadFrustum(rs_matrix4x4 *m,
+        float l, float r, float b, float t, float n, float f) {
+    SC_MatrixLoadFrustum((Matrix4x4 *) m, l, r, b, t, n, f);
+}
+void __attribute__((overloadable)) rsMatrixLoadPerspective(rs_matrix4x4 *m,
+        float fovy, float aspect, float near, float far) {
+    SC_MatrixLoadPerspective((Matrix4x4 *) m, fovy, aspect, near, far);
+}
+bool __attribute__((overloadable)) rsMatrixInverse(rs_matrix4x4 *m) {
+    return SC_MatrixInverse_4x4((Matrix4x4 *) m);
+}
+bool __attribute__((overloadable)) rsMatrixInverseTranspose(rs_matrix4x4 *m) {
+    return SC_MatrixInverseTranspose_4x4((Matrix4x4 *) m);
+}
+void __attribute__((overloadable)) rsMatrixTranspose(rs_matrix4x4 *m) {
+    SC_MatrixTranspose_4x4((Matrix4x4 *) m);
+}
+void __attribute__((overloadable)) rsMatrixTranspose(rs_matrix3x3 *m) {
+    SC_MatrixTranspose_3x3((Matrix3x3 *) m);
+}
+void __attribute__((overloadable)) rsMatrixTranspose(rs_matrix2x2 *m) {
+    SC_MatrixTranspose_2x2((Matrix2x2 *) m);
+}
 #endif
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/driver/rsdRuntimeStubs.cpp b/driver/rsdRuntimeStubs.cpp
index 1b617cd..cb5d008 100644
--- a/driver/rsdRuntimeStubs.cpp
+++ b/driver/rsdRuntimeStubs.cpp
@@ -1323,6 +1323,14 @@
     return rsrUptimeMillis(rsc);
 }
 
+int64_t rsUptimeNanos() {
+    return SC_UptimeNanos();
+}
+
+float rsGetDt() {
+    return SC_GetDt();
+}
+
 uint32_t rsSendToClient(int cmdID) {
     return SC_ToClient(cmdID);
 }
diff --git a/java/tests/RSTest_CompatLib/src/com/android/rs/test/apitest.rs b/java/tests/RSTest_CompatLib/src/com/android/rs/test/apitest.rs
index 27753af..865620f 100644
--- a/java/tests/RSTest_CompatLib/src/com/android/rs/test/apitest.rs
+++ b/java/tests/RSTest_CompatLib/src/com/android/rs/test/apitest.rs
@@ -15,6 +15,14 @@
 rs_script scriptNull;
 rs_script scriptNonNull;
 
+volatile rs_data_type dt;
+volatile rs_data_kind dk;
+
+volatile rs_sampler_value rsv;
+
+volatile rs_time_t rst;
+volatile static rs_tm rstm;
+
 char *allocPtr;
 rs_allocation allocDst;
 
@@ -61,6 +69,7 @@
 volatile double2 d2;
 volatile double3 d3;
 volatile double4 d4;
+float fa[16];
 
 rs_allocation aChar;
 rs_allocation aChar2;
@@ -1163,6 +1172,121 @@
     rsDebug("", ul3);
     rsDebug("", ul4);
 
+    // rs_element.rsh
+    ui = rsElementGetSubElementCount(elemNonNull);
+    elemNull = rsElementGetSubElement(elemNonNull, 0);
+    ui = rsElementGetSubElementNameLength(elemNonNull, 0);
+    ui = rsElementGetSubElementName(elemNonNull, 0, NULL, 0);
+    ui = rsElementGetSubElementArraySize(elemNonNull, 0);
+    ui = rsElementGetSubElementOffsetBytes(elemNonNull, 0);
+    ui = rsElementGetBytesSize(elemNonNull);
+
+    dt = rsElementGetDataType(elemNonNull);
+    dk = rsElementGetDataKind(elemNonNull);
+
+    ui = rsElementGetVectorSize(elemNonNull);
+
+    // rs_math.rsh
+    i = rsRand(i);
+    i = rsRand(i, i);
+    f = rsRand(f);
+    f = rsFrac(f);
+    ui = rsClamp(ui, ui, ui);
+    i = rsClamp(i, i, i);
+    us = rsClamp(us, us, us);
+    s = rsClamp(s, s, s);
+    uc = rsClamp(uc, uc, uc);
+    c = rsClamp(c, c, c);
+
+    // skip always-inlined rsExtractFrustumPlanes
+    // skip always-inlined rsIsSphereInFrustum
+
+    uc4 = rsPackColorTo8888(f, f, f);
+    uc4 = rsPackColorTo8888(f, f, f, f);
+    uc4 = rsPackColorTo8888(f3);
+    uc4 = rsPackColorTo8888(f4);
+    f4 = rsUnpackColor8888(uc4);
+    uc4 = rsYuvToRGBA_uchar4(uc, uc, uc);
+    f4 = rsYuvToRGBA_float4(uc, uc, uc);
+
+    // rs_matrix.rsh
+    rsMatrixSet(&m4x4, ui, ui, f);
+    rsMatrixSet(&m3x3, ui, ui, f);
+    rsMatrixSet(&m2x2, ui, ui, f);
+    f = rsMatrixGet(&m4x4, ui, ui);
+    f = rsMatrixGet(&m3x3, ui, ui);
+    f = rsMatrixGet(&m2x2, ui, ui);
+    rsMatrixLoadIdentity(&m4x4);
+    rsMatrixLoadIdentity(&m3x3);
+    rsMatrixLoadIdentity(&m2x2);
+    rsMatrixLoad(&m4x4, fa);
+    rsMatrixLoad(&m3x3, fa);
+    rsMatrixLoad(&m2x2, fa);
+    rsMatrixLoad(&m4x4, &m4x4);
+    rsMatrixLoad(&m4x4, &m3x3);
+    rsMatrixLoad(&m4x4, &m2x2);
+    rsMatrixLoad(&m3x3, &m3x3);
+    rsMatrixLoad(&m2x2, &m2x2);
+    rsMatrixLoadRotate(&m4x4, f, f, f, f);
+    rsMatrixLoadScale(&m4x4, f, f, f);
+    rsMatrixLoadTranslate(&m4x4, f, f, f);
+    rsMatrixLoadMultiply(&m4x4, &m4x4, &m4x4);
+    rsMatrixLoadMultiply(&m3x3, &m3x3, &m3x3);
+    rsMatrixLoadMultiply(&m2x2, &m2x2, &m2x2);
+    rsMatrixMultiply(&m4x4, &m4x4);
+    rsMatrixMultiply(&m3x3, &m3x3);
+    rsMatrixMultiply(&m2x2, &m2x2);
+    rsMatrixRotate(&m4x4, f, f, f, f);
+    rsMatrixScale(&m4x4, f, f, f);
+    rsMatrixTranslate(&m4x4, f, f, f);
+    rsMatrixLoadOrtho(&m4x4, f, f, f, f, f, f);
+    rsMatrixLoadFrustum(&m4x4, f, f, f, f, f, f);
+    rsMatrixLoadPerspective(&m4x4, f, f, f, f);
+    f4 = rsMatrixMultiply(&m4x4, f4);
+    f4 = rsMatrixMultiply(&m4x4, f3);
+    f4 = rsMatrixMultiply(&m4x4, f2);
+    f3 = rsMatrixMultiply(&m3x3, f3);
+    f3 = rsMatrixMultiply(&m3x3, f2);
+    f2 = rsMatrixMultiply(&m2x2, f2);
+    b = rsMatrixInverse(&m4x4);
+    b = rsMatrixInverseTranspose(&m4x4);
+    rsMatrixTranspose(&m4x4);
+    rsMatrixTranspose(&m3x3);
+    rsMatrixTranspose(&m2x2);
+
+    // rs_object.rsh
+    rsSetObject(&elemNonNull, elemNonNull);
+    rsSetObject(&typeNonNull, typeNonNull);
+    rsSetObject(&allocNonNull, allocNonNull);
+    rsSetObject(&samplerNonNull, samplerNonNull);
+    rsSetObject(&scriptNonNull, scriptNonNull);
+    rsClearObject(&elemNonNull);
+    rsClearObject(&typeNonNull);
+    rsClearObject(&allocNonNull);
+    rsClearObject(&samplerNonNull);
+    rsClearObject(&scriptNonNull);
+    b = rsIsObject(elemNonNull);
+    b = rsIsObject(typeNonNull);
+    b = rsIsObject(allocNonNull);
+    b = rsIsObject(samplerNonNull);
+    b = rsIsObject(scriptNonNull);
+
+    // rs_quaternion.rsh skipped because all functions are static.
+
+    // rs_sampler.rsh
+    rsv = rsSamplerGetMinification(samplerNonNull);
+    rsv = rsSamplerGetMagnification(samplerNonNull);
+    rsv = rsSamplerGetWrapS(samplerNonNull);
+    rsv = rsSamplerGetWrapT(samplerNonNull);
+    f = rsSamplerGetAnisotropy(samplerNonNull);
+
+    // rs_time.rsh
+    rst = rsTime(NULL);
+    rsLocaltime((rs_tm *) &rstm, (rs_time_t *) &rst);
+    ll = rsUptimeMillis();
+    ll = rsUptimeNanos();
+    f = rsGetDt();
+
     /********************************
      * DO NOT EXECUTE THIS FUNCTION *
      ********************************/
diff --git a/rsScript.cpp b/rsScript.cpp
index 7857667..a4a4e3b 100644
--- a/rsScript.cpp
+++ b/rsScript.cpp
@@ -65,7 +65,8 @@
 void Script::getVar(uint32_t slot, const void *val, size_t len) {
     //ALOGE("getVar %i %p %i", slot, val, len);
     if (slot >= mHal.info.exportedVariableCount) {
-        ALOGE("Script::getVar unable to set allocation, invalid slot index");
+        ALOGE("Script::getVar unable to set allocation, invalid slot index: "
+              "%u >= %u", slot, mHal.info.exportedVariableCount);
         return;
     }
     mRSC->mHal.funcs.script.getGlobalVar(mRSC, this, slot, (void *)val, len);
@@ -74,7 +75,8 @@
 void Script::setVar(uint32_t slot, const void *val, size_t len, Element *e,
                     const size_t *dims, size_t dimLen) {
     if (slot >= mHal.info.exportedVariableCount) {
-        ALOGE("Script::setVar unable to set allocation, invalid slot index");
+        ALOGE("Script::setVar unable to set allocation, invalid slot index: "
+              "%u >= %u", slot, mHal.info.exportedVariableCount);
         return;
     }
     mRSC->mHal.funcs.script.setGlobalVarWithElemDims(mRSC, this, slot,
@@ -84,7 +86,8 @@
 void Script::setVarObj(uint32_t slot, ObjectBase *val) {
     //ALOGE("setVarObj %i %p", slot, val);
     if (slot >= mHal.info.exportedVariableCount) {
-        ALOGE("Script::setVarObj unable to set allocation, invalid slot index");
+        ALOGE("Script::setVarObj unable to set allocation, invalid slot index: "
+              "%u >= %u", slot, mHal.info.exportedVariableCount);
         return;
     }
     mHasObjectSlots = true;