| // Copyright 2016 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "flutter/lib/jni/jni_class.h" | 
 |  | 
 | #include "flutter/lib/jni/dart_jni.h" | 
 |  | 
 | namespace blink { | 
 |  | 
 | using tonic::ToDart; | 
 | using base::android::ScopedJavaLocalRef; | 
 |  | 
 | IMPLEMENT_WRAPPERTYPEINFO(jni, JniClass); | 
 |  | 
 | JniClass::JniClass(JNIEnv* env, jclass clazz) : JniObject(env, clazz) {} | 
 |  | 
 | JniClass::~JniClass() {} | 
 |  | 
 | ftl::RefPtr<JniClass> JniClass::FromName(const char* name) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     if (!name) | 
 |       return nullptr; | 
 |  | 
 |     ScopedJavaLocalRef<jclass> clazz = DartJni::GetClass(env, name); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return ftl::MakeRefCounted<JniClass>(env, clazz.obj()); | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return nullptr; | 
 | } | 
 |  | 
 | ftl::RefPtr<JniClass> JniClass::FromClassObject(const JniObject* clazz) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     if (!clazz) | 
 |       return nullptr; | 
 |  | 
 |     jobject class_object = clazz->java_object(); | 
 |     if (!env->IsInstanceOf(class_object, DartJni::class_clazz())) { | 
 |       exception = ToDart("invalid JNI class object"); | 
 |       goto fail; | 
 |     } | 
 |  | 
 |     return ftl::MakeRefCounted<JniClass>(env, | 
 |                                          static_cast<jclass>(class_object)); | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return nullptr; | 
 | } | 
 |  | 
 | intptr_t JniClass::GetFieldId(const char* name, const char* sig) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jfieldID id = env->GetFieldID(java_class(), name, sig); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return reinterpret_cast<intptr_t>(id); | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | intptr_t JniClass::GetStaticFieldId(const char* name, const char* sig) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jfieldID id = env->GetStaticFieldID(java_class(), name, sig); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return reinterpret_cast<intptr_t>(id); | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | intptr_t JniClass::GetMethodId(const char* name, const char* sig) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jmethodID id = env->GetMethodID(java_class(), name, sig); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return reinterpret_cast<intptr_t>(id); | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | intptr_t JniClass::GetStaticMethodId(const char* name, const char* sig) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jmethodID id = env->GetStaticMethodID(java_class(), name, sig); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return reinterpret_cast<intptr_t>(id); | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | ftl::RefPtr<JniObject> JniClass::NewObject( | 
 |     jmethodID methodId, | 
 |     const std::vector<Dart_Handle>& args) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     JniMethodArgs java_args; | 
 |     java_args.Convert(env, args, &exception); | 
 |     if (exception) | 
 |       goto fail; | 
 |  | 
 |     jobject obj = env->NewObjectA(java_class(), methodId, java_args.jvalues()); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return JniObject::Create(env, obj); | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return nullptr; | 
 | } | 
 |  | 
 | bool JniClass::IsAssignable(const JniClass* clazz) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jboolean result = env->IsAssignableFrom(java_class(), clazz->java_class()); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result == JNI_TRUE; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return false; | 
 | } | 
 |  | 
 | ftl::RefPtr<JniObject> JniClass::GetStaticObjectField(jfieldID fieldId) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jobject obj = env->GetStaticObjectField(java_class(), fieldId); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return JniObject::Create(env, obj); | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return nullptr; | 
 | } | 
 |  | 
 | bool JniClass::GetStaticBooleanField(jfieldID fieldId) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jboolean result = env->GetStaticBooleanField(java_class(), fieldId); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result == JNI_TRUE; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return false; | 
 | } | 
 |  | 
 | int64_t JniClass::GetStaticByteField(jfieldID fieldId) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jbyte result = env->GetStaticByteField(java_class(), fieldId); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | int64_t JniClass::GetStaticCharField(jfieldID fieldId) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jchar result = env->GetStaticCharField(java_class(), fieldId); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | int64_t JniClass::GetStaticShortField(jfieldID fieldId) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jshort result = env->GetStaticShortField(java_class(), fieldId); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | int64_t JniClass::GetStaticIntField(jfieldID fieldId) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jint result = env->GetStaticIntField(java_class(), fieldId); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | int64_t JniClass::GetStaticLongField(jfieldID fieldId) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jlong result = env->GetStaticLongField(java_class(), fieldId); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | double JniClass::GetStaticFloatField(jfieldID fieldId) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jfloat result = env->GetStaticFloatField(java_class(), fieldId); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | double JniClass::GetStaticDoubleField(jfieldID fieldId) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     jfloat result = env->GetStaticDoubleField(java_class(), fieldId); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | void JniClass::SetStaticObjectField(jfieldID fieldId, const JniObject* value) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     env->SetStaticObjectField(java_class(), fieldId, | 
 |                               value ? value->java_object() : nullptr); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return; | 
 | } | 
 |  | 
 | void JniClass::SetStaticBooleanField(jfieldID fieldId, bool value) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     env->SetStaticBooleanField(java_class(), fieldId, | 
 |                                value ? JNI_TRUE : JNI_FALSE); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return; | 
 | } | 
 |  | 
 | void JniClass::SetStaticByteField(jfieldID fieldId, int64_t value) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     env->SetStaticByteField(java_class(), fieldId, value); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return; | 
 | } | 
 |  | 
 | void JniClass::SetStaticCharField(jfieldID fieldId, int64_t value) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     env->SetStaticCharField(java_class(), fieldId, value); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return; | 
 | } | 
 |  | 
 | void JniClass::SetStaticShortField(jfieldID fieldId, int64_t value) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     env->SetStaticShortField(java_class(), fieldId, value); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return; | 
 | } | 
 |  | 
 | void JniClass::SetStaticIntField(jfieldID fieldId, int64_t value) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     env->SetStaticIntField(java_class(), fieldId, value); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return; | 
 | } | 
 |  | 
 | void JniClass::SetStaticLongField(jfieldID fieldId, int64_t value) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     env->SetStaticLongField(java_class(), fieldId, value); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return; | 
 | } | 
 |  | 
 | void JniClass::SetStaticFloatField(jfieldID fieldId, double value) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     env->SetStaticFloatField(java_class(), fieldId, value); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return; | 
 | } | 
 |  | 
 | void JniClass::SetStaticDoubleField(jfieldID fieldId, double value) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     env->SetStaticDoubleField(java_class(), fieldId, value); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return; | 
 | } | 
 |  | 
 | ftl::RefPtr<JniObject> JniClass::CallStaticObjectMethod( | 
 |     jmethodID methodId, | 
 |     const std::vector<Dart_Handle>& args) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     JniMethodArgs java_args; | 
 |     java_args.Convert(env, args, &exception); | 
 |     if (exception) | 
 |       goto fail; | 
 |  | 
 |     jobject obj = env->CallStaticObjectMethodA(java_class(), methodId, | 
 |                                                java_args.jvalues()); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return JniObject::Create(env, obj); | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return nullptr; | 
 | } | 
 |  | 
 | bool JniClass::CallStaticBooleanMethod(jmethodID methodId, | 
 |                                        const std::vector<Dart_Handle>& args) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     JniMethodArgs java_args; | 
 |     java_args.Convert(env, args, &exception); | 
 |     if (exception) | 
 |       goto fail; | 
 |  | 
 |     jboolean result = env->CallStaticBooleanMethodA(java_class(), methodId, | 
 |                                                     java_args.jvalues()); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result == JNI_TRUE; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return false; | 
 | } | 
 |  | 
 | int64_t JniClass::CallStaticByteMethod(jmethodID methodId, | 
 |                                        const std::vector<Dart_Handle>& args) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     JniMethodArgs java_args; | 
 |     java_args.Convert(env, args, &exception); | 
 |     if (exception) | 
 |       goto fail; | 
 |  | 
 |     jbyte result = | 
 |         env->CallStaticByteMethodA(java_class(), methodId, java_args.jvalues()); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | int64_t JniClass::CallStaticCharMethod(jmethodID methodId, | 
 |                                        const std::vector<Dart_Handle>& args) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     JniMethodArgs java_args; | 
 |     java_args.Convert(env, args, &exception); | 
 |     if (exception) | 
 |       goto fail; | 
 |  | 
 |     jchar result = | 
 |         env->CallStaticCharMethodA(java_class(), methodId, java_args.jvalues()); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | int64_t JniClass::CallStaticShortMethod(jmethodID methodId, | 
 |                                         const std::vector<Dart_Handle>& args) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     JniMethodArgs java_args; | 
 |     java_args.Convert(env, args, &exception); | 
 |     if (exception) | 
 |       goto fail; | 
 |  | 
 |     jshort result = env->CallStaticShortMethodA(java_class(), methodId, | 
 |                                                 java_args.jvalues()); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | int64_t JniClass::CallStaticIntMethod(jmethodID methodId, | 
 |                                       const std::vector<Dart_Handle>& args) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     JniMethodArgs java_args; | 
 |     java_args.Convert(env, args, &exception); | 
 |     if (exception) | 
 |       goto fail; | 
 |  | 
 |     jint result = | 
 |         env->CallStaticIntMethodA(java_class(), methodId, java_args.jvalues()); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | int64_t JniClass::CallStaticLongMethod(jmethodID methodId, | 
 |                                        const std::vector<Dart_Handle>& args) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     JniMethodArgs java_args; | 
 |     java_args.Convert(env, args, &exception); | 
 |     if (exception) | 
 |       goto fail; | 
 |  | 
 |     jlong result = | 
 |         env->CallStaticLongMethodA(java_class(), methodId, java_args.jvalues()); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | double JniClass::CallStaticFloatMethod(jmethodID methodId, | 
 |                                        const std::vector<Dart_Handle>& args) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     JniMethodArgs java_args; | 
 |     java_args.Convert(env, args, &exception); | 
 |     if (exception) | 
 |       goto fail; | 
 |  | 
 |     jfloat result = env->CallStaticFloatMethodA(java_class(), methodId, | 
 |                                                 java_args.jvalues()); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | double JniClass::CallStaticDoubleMethod(jmethodID methodId, | 
 |                                         const std::vector<Dart_Handle>& args) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     JniMethodArgs java_args; | 
 |     java_args.Convert(env, args, &exception); | 
 |     if (exception) | 
 |       goto fail; | 
 |  | 
 |     jdouble result = env->CallStaticDoubleMethodA(java_class(), methodId, | 
 |                                                   java_args.jvalues()); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return result; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | void JniClass::CallStaticVoidMethod(jmethodID methodId, | 
 |                                     const std::vector<Dart_Handle>& args) { | 
 |   Dart_Handle exception = nullptr; | 
 |   { | 
 |     ENTER_JNI(); | 
 |  | 
 |     JniMethodArgs java_args; | 
 |     java_args.Convert(env, args, &exception); | 
 |     if (exception) | 
 |       goto fail; | 
 |  | 
 |     env->CallStaticVoidMethodA(java_class(), methodId, java_args.jvalues()); | 
 |     if (CheckJniException(env, &exception)) | 
 |       goto fail; | 
 |  | 
 |     return; | 
 |   } | 
 | fail: | 
 |   Dart_ThrowException(exception); | 
 |   FTL_NOTREACHED(); | 
 |   return; | 
 | } | 
 |  | 
 | }  // namespace blink |