Add RuntimeShader API to RenderEffect

Bug: 201546136
Test: atest CtsUiRenderingTestCases:RuntimeShaderTests
Change-Id: I96ad4fcfc0486f340653878519efcc4a793191a2
diff --git a/libs/hwui/jni/RenderEffect.cpp b/libs/hwui/jni/RenderEffect.cpp
index a48d7f7..213f35a 100644
--- a/libs/hwui/jni/RenderEffect.cpp
+++ b/libs/hwui/jni/RenderEffect.cpp
@@ -127,6 +127,32 @@
     return reinterpret_cast<jlong>(shaderFilter.release());
 }
 
+static inline int ThrowIAEFmt(JNIEnv* env, const char* fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+    int ret = jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", fmt, args);
+    va_end(args);
+    return ret;
+}
+
+static jlong createRuntimeShaderEffect(JNIEnv* env, jobject, jlong shaderBuilderHandle,
+                                       jstring inputShaderName) {
+    SkRuntimeShaderBuilder* builder =
+            reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilderHandle);
+    ScopedUtfChars name(env, inputShaderName);
+
+    if (builder->child(name.c_str()).fChild == nullptr) {
+        ThrowIAEFmt(env,
+                    "unable to find a uniform with the name '%s' of the correct "
+                    "type defined by the provided RuntimeShader",
+                    name.c_str());
+        return 0;
+    }
+
+    sk_sp<SkImageFilter> filter = SkImageFilters::RuntimeShader(*builder, name.c_str(), nullptr);
+    return reinterpret_cast<jlong>(filter.release());
+}
+
 static void RenderEffect_safeUnref(SkImageFilter* filter) {
     SkSafeUnref(filter);
 }
@@ -136,15 +162,16 @@
 }
 
 static const JNINativeMethod gRenderEffectMethods[] = {
-    {"nativeGetFinalizer", "()J", (void*)getRenderEffectFinalizer},
-    {"nativeCreateOffsetEffect", "(FFJ)J", (void*)createOffsetEffect},
-    {"nativeCreateBlurEffect", "(FFJI)J", (void*)createBlurEffect},
-    {"nativeCreateBitmapEffect", "(JFFFFFFFF)J", (void*)createBitmapEffect},
-    {"nativeCreateColorFilterEffect", "(JJ)J", (void*)createColorFilterEffect},
-    {"nativeCreateBlendModeEffect", "(JJI)J", (void*)createBlendModeEffect},
-    {"nativeCreateChainEffect", "(JJ)J", (void*)createChainEffect},
-    {"nativeCreateShaderEffect", "(J)J", (void*)createShaderEffect}
-};
+        {"nativeGetFinalizer", "()J", (void*)getRenderEffectFinalizer},
+        {"nativeCreateOffsetEffect", "(FFJ)J", (void*)createOffsetEffect},
+        {"nativeCreateBlurEffect", "(FFJI)J", (void*)createBlurEffect},
+        {"nativeCreateBitmapEffect", "(JFFFFFFFF)J", (void*)createBitmapEffect},
+        {"nativeCreateColorFilterEffect", "(JJ)J", (void*)createColorFilterEffect},
+        {"nativeCreateBlendModeEffect", "(JJI)J", (void*)createBlendModeEffect},
+        {"nativeCreateChainEffect", "(JJ)J", (void*)createChainEffect},
+        {"nativeCreateShaderEffect", "(J)J", (void*)createShaderEffect},
+        {"nativeCreateRuntimeShaderEffect", "(JLjava/lang/String;)J",
+         (void*)createRuntimeShaderEffect}};
 
 int register_android_graphics_RenderEffect(JNIEnv* env) {
     android::RegisterMethodsOrDie(env, "android/graphics/RenderEffect",