165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/* 265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project 365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License"); 565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License. 665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at 765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * http://www.apache.org/licenses/LICENSE-2.0 965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software 1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS, 1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and 1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License. 1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <string> 1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "jni/jni_util.h" 2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "base/logging.h" 2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#if 0 2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennJavaObject::JavaObject() 2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : object_(JNI_NULL), 2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ref_count_(new int(0)) { 2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennJavaObject::JavaObject(const JavaObject& java_obj) 3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : object_(java_obj.object_), 3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ref_count_(java_obj.ref_count_) { 3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Retain(); 3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennJavaObject::JavaObject(jobject object, JNIEnv* env) 3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : object_(NULL), 3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ref_count_(new int(0)) { 3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Retain(); 3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn object_ = env->NewGlobalRef(object_); 4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennJavaObject::~JavaObject() { 4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Release(); 4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennJavaObject& JavaObject::operator=(const JavaObject& java_obj) { 4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Release(); 4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn object_ = java_obj.object_; 4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ref_count_ = java_obj.ref_count_; 5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Retain(); 5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return *this; 5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid JavaObject::Retain() { 5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (ref_count_) 5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ++(*ref_count_); 5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn else 5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("JavaObject: Reference count is NULL! JavaObject may be corrupted."); 5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid JavaObject::Release() { 6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (ref_count_) { 6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (*ref_count_ > 0) 6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn --(*ref_count_); 6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (*ref_count_ == 0) { 6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn JNIEnv* env = GetCurrentJNIEnv(); 6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!env) 6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("JavaObject: Releasing outside of Java thread. Will just leak!"); 6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn else if (object_) 7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn env->DeleteGlobalRef(object_); 7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn delete ref_count_; 7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ref_count_ = NULL; 7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("JavaObject: Reference count is NULL! JavaObject may be corrupted."); 7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid JavaObject::Reset() { 8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Release(); 8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn object_ = NULL; 8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ref_count_ = new int(0); 8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennJavaVM* GetCurrentJavaVM() { 8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return g_current_java_vm_; 8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennJNIEnv* GetCurrentJNIEnv() { 9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn JavaVM* vm = GetCurrentJavaVM(); 9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn JNIEnv* env = NULL; 9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const jint result = vm->GetEnv(reinterpret_cast<void**>(&env), 9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn JNI_VERSION_1_4); 9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result == JNI_OK ? env : NULL; 9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#endif 9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjstring ToJString(JNIEnv* env, const std::string& value) { 9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return env->NewStringUTF(value.c_str()); 10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennstd::string ToCppString(JNIEnv* env, jstring value) { 10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jboolean isCopy; 10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const char* c_value = env->GetStringUTFChars(value, &isCopy); 10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn std::string result(c_value); 10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (isCopy == JNI_TRUE) 10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn env->ReleaseStringUTFChars(value, c_value); 10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result; 10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjboolean ToJBool(bool value) { 11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return value ? JNI_TRUE : JNI_FALSE; 11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ToCppBool(jboolean value) { 11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return value == JNI_TRUE; 11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// TODO: We actually shouldn't use such a function as it requires a class name lookup at every 12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// invocation. Instead, store the class objects and use those. 12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool IsJavaInstanceOf(JNIEnv* env, jobject object, const std::string& class_name) { 12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jclass clazz = env->FindClass(class_name.c_str()); 12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return clazz ? env->IsInstanceOf(object, clazz) == JNI_TRUE : false; 12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renntemplate<typename T> 12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjobject CreateJObject(JNIEnv* env, const std::string& class_name, const std::string& signature, T value) { 12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jobject result = JNI_NULL; 12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result; 13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennValue ToCValue(JNIEnv* env, jobject object) { 13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Value result = MakeNullValue(); 13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (object != NULL) { 13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (IsJavaInstanceOf(env, object, "java/lang/Boolean")) { 13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jmethodID method = env->GetMethodID(env->GetObjectClass(object), "booleanValue", "()Z"); 13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = MakeIntValue(env->CallBooleanMethod(object, method) == JNI_TRUE ? 1 : 0); 13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (IsJavaInstanceOf(env, object, "java/lang/Integer")) { 14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jmethodID method = env->GetMethodID(env->GetObjectClass(object), "intValue", "()I"); 14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = MakeIntValue(env->CallIntMethod(object, method)); 14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (IsJavaInstanceOf(env, object, "java/lang/Float")) { 14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jmethodID method = env->GetMethodID(env->GetObjectClass(object), "floatValue", "()F"); 14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = MakeFloatValue(env->CallFloatMethod(object, method)); 14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (IsJavaInstanceOf(env, object, "java/lang/String")) { 14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = MakeStringValue(ToCppString(env, static_cast<jstring>(object)).c_str()); 14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (IsJavaInstanceOf(env, object, "[I")) { 14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jint* elems = env->GetIntArrayElements(static_cast<jintArray>(object), NULL); 14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const jint count = env->GetArrayLength(static_cast<jintArray>(object)); 15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = MakeIntArrayValue(elems, count); 15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn env->ReleaseIntArrayElements(static_cast<jintArray>(object), elems, JNI_ABORT); 15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (IsJavaInstanceOf(env, object, "[F")) { 15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jfloat* elems = env->GetFloatArrayElements(static_cast<jfloatArray>(object), NULL); 15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const jint count = env->GetArrayLength(static_cast<jfloatArray>(object)); 15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = MakeFloatArrayValue(elems, count); 15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn env->ReleaseFloatArrayElements(static_cast<jfloatArray>(object), elems, JNI_ABORT); 15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result; 16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennjobject ToJObject(JNIEnv* env, const Value& value) { 16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jobject result = JNI_NULL; 16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (ValueIsInt(value)) { 16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jclass clazz = env->FindClass("java/lang/Integer"); 16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jmethodID constructorID = env->GetMethodID(clazz, "<init>", "(I)V"); 16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = env->NewObject(clazz, constructorID, GetIntValue(value)); 16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (ValueIsFloat(value)) { 16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jclass clazz = env->FindClass("java/lang/Float"); 17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn jmethodID constructorID = env->GetMethodID(clazz, "<init>", "(F)V"); 17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = env->NewObject(clazz, constructorID, GetFloatValue(value)); 17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (ValueIsString(value)) { 17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = ToJString(env, GetStringValue(value)); 17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (ValueIsIntArray(value)) { 17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = env->NewIntArray(GetValueCount(value)); 17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn env->SetIntArrayRegion(static_cast<jintArray>(result), 17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 0, 17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GetValueCount(value), 17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn reinterpret_cast<const jint*>(GetIntArrayValue(value))); 18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (ValueIsFloatArray(value)) { 18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result = env->NewFloatArray(GetValueCount(value)); 18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn env->SetFloatArrayRegion(static_cast<jfloatArray>(result), 18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 0, 18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GetValueCount(value), 18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn reinterpret_cast<const jfloat*>(GetFloatArrayValue(value))); 18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result; 18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 189