| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/android/jni_android.h" | 5 #include "base/android/jni_android.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "base/atomicops.h" | 9 #include "base/atomicops.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/threading/platform_thread.h" | 12 #include "base/threading/platform_thread.h" |
| 13 | 13 |
| 14 namespace { | 14 namespace { |
| 15 JavaVM* g_jvm = 0; | 15 |
| 16 jobject g_application_context = NULL; | 16 JavaVM* g_jvm = NULL; |
| 17 |
| 18 base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> > |
| 19 g_application_context = LAZY_INSTANCE_INITIALIZER; |
| 17 | 20 |
| 18 struct MethodIdentifier { | 21 struct MethodIdentifier { |
| 19 const char* class_name; | 22 const char* class_name; |
| 20 const char* method; | 23 const char* method; |
| 21 const char* jni_signature; | 24 const char* jni_signature; |
| 22 | 25 |
| 23 bool operator<(const MethodIdentifier& other) const { | 26 bool operator<(const MethodIdentifier& other) const { |
| 24 int r = strcmp(class_name, other.class_name); | 27 int r = strcmp(class_name, other.class_name); |
| 25 if (r < 0) { | 28 if (r < 0) { |
| 26 return true; | 29 return true; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 if (g_jvm) | 69 if (g_jvm) |
| 67 g_jvm->DetachCurrentThread(); | 70 g_jvm->DetachCurrentThread(); |
| 68 } | 71 } |
| 69 | 72 |
| 70 void InitVM(JavaVM* vm) { | 73 void InitVM(JavaVM* vm) { |
| 71 DCHECK(!g_jvm); | 74 DCHECK(!g_jvm); |
| 72 g_jvm = vm; | 75 g_jvm = vm; |
| 73 } | 76 } |
| 74 | 77 |
| 75 void InitApplicationContext(const JavaRef<jobject>& context) { | 78 void InitApplicationContext(const JavaRef<jobject>& context) { |
| 76 DCHECK(!g_application_context); | 79 DCHECK(g_application_context.Get().is_null()); |
| 77 g_application_context = context.env()->NewGlobalRef(context.obj()); | 80 g_application_context.Get().Reset(context); |
| 78 } | 81 } |
| 79 | 82 |
| 80 jobject GetApplicationContext() { | 83 const jobject GetApplicationContext() { |
| 81 DCHECK(g_application_context); | 84 DCHECK(!g_application_context.Get().is_null()); |
| 82 return g_application_context; | 85 return g_application_context.Get().obj(); |
| 86 } |
| 87 |
| 88 ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) { |
| 89 jclass clazz = env->FindClass(class_name); |
| 90 CHECK(clazz && !ClearException(env)) << "Failed to find class " << class_name; |
| 91 return ScopedJavaLocalRef<jclass>(env, clazz); |
| 92 } |
| 93 |
| 94 bool HasClass(JNIEnv* env, const char* class_name) { |
| 95 ScopedJavaLocalRef<jclass> clazz(env, env->FindClass(class_name)); |
| 96 if (!clazz.obj()) { |
| 97 ClearException(env); |
| 98 return false; |
| 99 } |
| 100 bool error = ClearException(env); |
| 101 DCHECK(!error); |
| 102 return true; |
| 103 } |
| 104 |
| 105 jmethodID GetMethodID(JNIEnv* env, |
| 106 const JavaRef<jclass>& clazz, |
| 107 const char* method_name, |
| 108 const char* jni_signature) { |
| 109 jmethodID method_id = |
| 110 env->GetMethodID(clazz.obj(), method_name, jni_signature); |
| 111 CHECK(method_id && !ClearException(env)) << "Failed to find method " << |
| 112 method_name << " " << jni_signature; |
| 113 return method_id; |
| 114 } |
| 115 |
| 116 jmethodID GetStaticMethodID(JNIEnv* env, |
| 117 const JavaRef<jclass>& clazz, |
| 118 const char* method_name, |
| 119 const char* jni_signature) { |
| 120 jmethodID method_id = |
| 121 env->GetStaticMethodID(clazz.obj(), method_name, jni_signature); |
| 122 CHECK(method_id && !ClearException(env)) << "Failed to find static method " << |
| 123 method_name << " " << jni_signature; |
| 124 return method_id; |
| 125 } |
| 126 |
| 127 bool HasMethod(JNIEnv* env, |
| 128 const JavaRef<jclass>& clazz, |
| 129 const char* method_name, |
| 130 const char* jni_signature) { |
| 131 jmethodID method_id = |
| 132 env->GetMethodID(clazz.obj(), method_name, jni_signature); |
| 133 if (!method_id) { |
| 134 ClearException(env); |
| 135 return false; |
| 136 } |
| 137 bool error = ClearException(env); |
| 138 DCHECK(!error); |
| 139 return true; |
| 140 } |
| 141 |
| 142 jfieldID GetFieldID(JNIEnv* env, |
| 143 const JavaRef<jclass>& clazz, |
| 144 const char* field_name, |
| 145 const char* jni_signature) { |
| 146 jfieldID field_id = env->GetFieldID(clazz.obj(), field_name, jni_signature); |
| 147 CHECK(field_id && !ClearException(env)) << "Failed to find field " << |
| 148 field_name << " " << jni_signature; |
| 149 bool error = ClearException(env); |
| 150 DCHECK(!error); |
| 151 return field_id; |
| 152 } |
| 153 |
| 154 bool HasField(JNIEnv* env, |
| 155 const JavaRef<jclass>& clazz, |
| 156 const char* field_name, |
| 157 const char* jni_signature) { |
| 158 jfieldID field_id = env->GetFieldID(clazz.obj(), field_name, jni_signature); |
| 159 if (!field_id) { |
| 160 ClearException(env); |
| 161 return false; |
| 162 } |
| 163 bool error = ClearException(env); |
| 164 DCHECK(!error); |
| 165 return true; |
| 166 } |
| 167 |
| 168 jfieldID GetStaticFieldID(JNIEnv* env, |
| 169 const JavaRef<jclass>& clazz, |
| 170 const char* field_name, |
| 171 const char* jni_signature) { |
| 172 jfieldID field_id = |
| 173 env->GetStaticFieldID(clazz.obj(), field_name, jni_signature); |
| 174 CHECK(field_id && !ClearException(env)) << "Failed to find static field " << |
| 175 field_name << " " << jni_signature; |
| 176 bool error = ClearException(env); |
| 177 DCHECK(!error); |
| 178 return field_id; |
| 83 } | 179 } |
| 84 | 180 |
| 85 jmethodID GetMethodIDFromClassName(JNIEnv* env, | 181 jmethodID GetMethodIDFromClassName(JNIEnv* env, |
| 86 const char* class_name, | 182 const char* class_name, |
| 87 const char* method, | 183 const char* method, |
| 88 const char* jni_signature) { | 184 const char* jni_signature) { |
| 89 MethodIdentifier key; | 185 MethodIdentifier key; |
| 90 key.class_name = class_name; | 186 key.class_name = class_name; |
| 91 key.method = method; | 187 key.method = method; |
| 92 key.jni_signature = jni_signature; | 188 key.jni_signature = jni_signature; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 104 found = true; | 200 found = true; |
| 105 } | 201 } |
| 106 base::subtle::Release_Store(&g_method_id_map_lock, kUnlocked); | 202 base::subtle::Release_Store(&g_method_id_map_lock, kUnlocked); |
| 107 | 203 |
| 108 // Addition to the map does not invalidate this iterator. | 204 // Addition to the map does not invalidate this iterator. |
| 109 if (found) { | 205 if (found) { |
| 110 return iter->second; | 206 return iter->second; |
| 111 } | 207 } |
| 112 | 208 |
| 113 ScopedJavaLocalRef<jclass> clazz(env, env->FindClass(class_name)); | 209 ScopedJavaLocalRef<jclass> clazz(env, env->FindClass(class_name)); |
| 114 jmethodID id = GetMethodID(env, clazz.obj(), method, jni_signature); | 210 jmethodID id = GetMethodID(env, clazz, method, jni_signature); |
| 115 | 211 |
| 116 while (base::subtle::Acquire_CompareAndSwap(&g_method_id_map_lock, | 212 while (base::subtle::Acquire_CompareAndSwap(&g_method_id_map_lock, |
| 117 kUnlocked, | 213 kUnlocked, |
| 118 kLocked) != kUnlocked) { | 214 kLocked) != kUnlocked) { |
| 119 base::PlatformThread::YieldCurrentThread(); | 215 base::PlatformThread::YieldCurrentThread(); |
| 120 } | 216 } |
| 121 // Another thread may have populated the map already. | 217 // Another thread may have populated the map already. |
| 122 std::pair<MethodIDMap::const_iterator, bool> result = | 218 std::pair<MethodIDMap::const_iterator, bool> result = |
| 123 map->insert(std::make_pair(key, id)); | 219 map->insert(std::make_pair(key, id)); |
| 124 DCHECK_EQ(id, result.first->second); | 220 DCHECK_EQ(id, result.first->second); |
| 125 base::subtle::Release_Store(&g_method_id_map_lock, kUnlocked); | 221 base::subtle::Release_Store(&g_method_id_map_lock, kUnlocked); |
| 126 | 222 |
| 127 return id; | 223 return id; |
| 128 } | 224 } |
| 129 | 225 |
| 130 jmethodID GetMethodID(JNIEnv* env, | 226 bool HasException(JNIEnv* env) { |
| 131 jclass clazz, | 227 return env->ExceptionCheck() != JNI_FALSE; |
| 132 const char* const method, | |
| 133 const char* const jni_signature) { | |
| 134 jmethodID id = env->GetMethodID(clazz, method, jni_signature); | |
| 135 DCHECK(id) << method; | |
| 136 CheckException(env); | |
| 137 return id; | |
| 138 } | 228 } |
| 139 | 229 |
| 140 jmethodID GetStaticMethodID(JNIEnv* env, | 230 bool ClearException(JNIEnv* env) { |
| 141 jclass clazz, | 231 if (!HasException(env)) |
| 142 const char* const method, | |
| 143 const char* const jni_signature) { | |
| 144 jmethodID id = env->GetStaticMethodID(clazz, method, jni_signature); | |
| 145 DCHECK(id) << method; | |
| 146 CheckException(env); | |
| 147 return id; | |
| 148 } | |
| 149 | |
| 150 jfieldID GetFieldID(JNIEnv* env, | |
| 151 jclass clazz, | |
| 152 const char* field, | |
| 153 const char* jni_signature) { | |
| 154 jfieldID id = env->GetFieldID(clazz, field, jni_signature); | |
| 155 DCHECK(id) << field; | |
| 156 CheckException(env); | |
| 157 return id; | |
| 158 } | |
| 159 | |
| 160 bool CheckException(JNIEnv* env) { | |
| 161 if (env->ExceptionCheck() == JNI_FALSE) | |
| 162 return false; | 232 return false; |
| 163 env->ExceptionDescribe(); | |
| 164 env->ExceptionClear(); | 233 env->ExceptionClear(); |
| 165 return true; | 234 return true; |
| 166 } | 235 } |
| 167 | 236 |
| 237 void CheckException(JNIEnv* env) { |
| 238 if (HasException(env)) { |
| 239 env->ExceptionDescribe(); |
| 240 CHECK(false); |
| 241 } |
| 242 } |
| 243 |
| 168 } // namespace android | 244 } // namespace android |
| 169 } // namespace base | 245 } // namespace base |
| OLD | NEW |