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 |