• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <string>
18 
19 #include "jni/jni_util.h"
20 
21 #include "base/logging.h"
22 
23 #if 0
24 JavaObject::JavaObject()
25     : object_(JNI_NULL),
26       ref_count_(new int(0)) {
27 }
28 
29 JavaObject::JavaObject(const JavaObject& java_obj)
30     : object_(java_obj.object_),
31       ref_count_(java_obj.ref_count_) {
32   Retain();
33 }
34 
35 JavaObject::JavaObject(jobject object, JNIEnv* env)
36     : object_(NULL),
37       ref_count_(new int(0)) {
38   Retain();
39   object_ = env->NewGlobalRef(object_);
40 }
41 
42 JavaObject::~JavaObject() {
43   Release();
44 }
45 
46 JavaObject& JavaObject::operator=(const JavaObject& java_obj) {
47   Release();
48   object_ = java_obj.object_;
49   ref_count_ = java_obj.ref_count_;
50   Retain();
51   return *this;
52 }
53 
54 void JavaObject::Retain() {
55   if (ref_count_)
56     ++(*ref_count_);
57   else
58     ALOGE("JavaObject: Reference count is NULL! JavaObject may be corrupted.");
59 }
60 
61 void JavaObject::Release() {
62   if (ref_count_) {
63     if (*ref_count_ > 0)
64       --(*ref_count_);
65     if (*ref_count_ == 0) {
66       JNIEnv* env = GetCurrentJNIEnv();
67       if (!env)
68         ALOGE("JavaObject: Releasing outside of Java thread. Will just leak!");
69       else if (object_)
70         env->DeleteGlobalRef(object_);
71       delete ref_count_;
72       ref_count_ = NULL;
73     }
74   } else {
75     ALOGE("JavaObject: Reference count is NULL! JavaObject may be corrupted.");
76   }
77 }
78 
79 void JavaObject::Reset() {
80   Release();
81   object_ = NULL;
82   ref_count_ = new int(0);
83 }
84 
85 JavaVM* GetCurrentJavaVM() {
86   return g_current_java_vm_;
87 }
88 
89 JNIEnv* GetCurrentJNIEnv() {
90   JavaVM* vm = GetCurrentJavaVM();
91   JNIEnv* env = NULL;
92   const jint result = vm->GetEnv(reinterpret_cast<void**>(&env),
93                                  JNI_VERSION_1_4);
94   return result == JNI_OK ? env : NULL;
95 }
96 #endif
97 
ToJString(JNIEnv * env,const std::string & value)98 jstring ToJString(JNIEnv* env, const std::string& value) {
99   return env->NewStringUTF(value.c_str());
100 }
101 
ToCppString(JNIEnv * env,jstring value)102 std::string ToCppString(JNIEnv* env, jstring value) {
103   jboolean isCopy;
104   const char* c_value = env->GetStringUTFChars(value, &isCopy);
105   std::string result(c_value);
106   if (isCopy == JNI_TRUE)
107     env->ReleaseStringUTFChars(value, c_value);
108   return result;
109 }
110 
ToJBool(bool value)111 jboolean ToJBool(bool value) {
112   return value ? JNI_TRUE : JNI_FALSE;
113 }
114 
ToCppBool(jboolean value)115 bool ToCppBool(jboolean value) {
116   return value == JNI_TRUE;
117 }
118 
119 // TODO: We actually shouldn't use such a function as it requires a class name lookup at every
120 // invocation. Instead, store the class objects and use those.
IsJavaInstanceOf(JNIEnv * env,jobject object,const std::string & class_name)121 bool IsJavaInstanceOf(JNIEnv* env, jobject object, const std::string& class_name) {
122   jclass clazz = env->FindClass(class_name.c_str());
123   return clazz ? env->IsInstanceOf(object, clazz) == JNI_TRUE : false;
124 }
125 
126 template<typename T>
CreateJObject(JNIEnv * env,const std::string & class_name,const std::string & signature,T value)127 jobject CreateJObject(JNIEnv* env, const std::string& class_name, const std::string& signature, T value) {
128   jobject result = JNI_NULL;
129 
130   return result;
131 }
132 
ToCValue(JNIEnv * env,jobject object)133 Value ToCValue(JNIEnv* env, jobject object) {
134   Value result = MakeNullValue();
135   if (object != NULL) {
136     if (IsJavaInstanceOf(env, object, "java/lang/Boolean")) {
137       jmethodID method = env->GetMethodID(env->GetObjectClass(object), "booleanValue", "()Z");
138       result = MakeIntValue(env->CallBooleanMethod(object, method) == JNI_TRUE ? 1 : 0);
139     } else if (IsJavaInstanceOf(env, object, "java/lang/Integer")) {
140       jmethodID method = env->GetMethodID(env->GetObjectClass(object), "intValue", "()I");
141       result = MakeIntValue(env->CallIntMethod(object, method));
142     } else if (IsJavaInstanceOf(env, object, "java/lang/Float")) {
143       jmethodID method = env->GetMethodID(env->GetObjectClass(object), "floatValue", "()F");
144       result = MakeFloatValue(env->CallFloatMethod(object, method));
145     } else if (IsJavaInstanceOf(env, object, "java/lang/String")) {
146       result = MakeStringValue(ToCppString(env, static_cast<jstring>(object)).c_str());
147     } else if (IsJavaInstanceOf(env, object, "[I")) {
148       jint* elems = env->GetIntArrayElements(static_cast<jintArray>(object), NULL);
149       const jint count = env->GetArrayLength(static_cast<jintArray>(object));
150       result = MakeIntArrayValue(elems, count);
151       env->ReleaseIntArrayElements(static_cast<jintArray>(object), elems, JNI_ABORT);
152     } else if (IsJavaInstanceOf(env, object, "[F")) {
153       jfloat* elems = env->GetFloatArrayElements(static_cast<jfloatArray>(object), NULL);
154       const jint count = env->GetArrayLength(static_cast<jfloatArray>(object));
155       result = MakeFloatArrayValue(elems, count);
156       env->ReleaseFloatArrayElements(static_cast<jfloatArray>(object), elems, JNI_ABORT);
157     }
158   }
159   return result;
160 }
161 
ToJObject(JNIEnv * env,const Value & value)162 jobject ToJObject(JNIEnv* env, const Value& value) {
163   jobject result = JNI_NULL;
164   if (ValueIsInt(value)) {
165     jclass clazz = env->FindClass("java/lang/Integer");
166     jmethodID constructorID = env->GetMethodID(clazz, "<init>", "(I)V");
167     result = env->NewObject(clazz, constructorID, GetIntValue(value));
168   } else if (ValueIsFloat(value)) {
169     jclass clazz = env->FindClass("java/lang/Float");
170     jmethodID constructorID = env->GetMethodID(clazz, "<init>", "(F)V");
171     result = env->NewObject(clazz, constructorID, GetFloatValue(value));
172   } else if (ValueIsString(value)) {
173     result = ToJString(env, GetStringValue(value));
174   } else if (ValueIsIntArray(value)) {
175     result = env->NewIntArray(GetValueCount(value));
176     env->SetIntArrayRegion(static_cast<jintArray>(result),
177                            0,
178                            GetValueCount(value),
179                            reinterpret_cast<const jint*>(GetIntArrayValue(value)));
180   } else if (ValueIsFloatArray(value)) {
181     result = env->NewFloatArray(GetValueCount(value));
182     env->SetFloatArrayRegion(static_cast<jfloatArray>(result),
183                              0,
184                              GetValueCount(value),
185                              reinterpret_cast<const jfloat*>(GetFloatArrayValue(value)));
186   }
187   return result;
188 }
189