blob: 1ebb36c8e873cc0071247a18981bc921e10c8f6d [file] [log] [blame]
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07001#include "SkTypes.h"
2#include "SkImageDecoder.h"
3
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +09004#define LOG_TAG "EmojiFactory_jni"
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07005#include <utils/Log.h>
6#include <utils/String8.h>
Kenny Root300ba682010-11-09 14:37:23 -08007#include <utils/String16.h>
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07008
9#include "EmojiFactory.h"
10#include <nativehelper/JNIHelp.h>
11
12#include <dlfcn.h>
13// #include <pthread.h>
14
15namespace android {
16
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070017class EmojiFactoryCaller {
18 public:
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +090019 EmojiFactoryCaller() {}
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070020 virtual ~EmojiFactoryCaller();
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +090021 bool Init();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070022 EmojiFactory *TryCallGetImplementation(const char* name);
23 EmojiFactory *TryCallGetAvailableImplementation();
24 private:
25 void *m_handle;
26 EmojiFactory *(*m_get_implementation)(const char*);
27 EmojiFactory *(*m_get_available_implementation)();
28};
29
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +090030bool EmojiFactoryCaller::Init() {
31 const char* error_msg;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070032 m_handle = dlopen("libemoji.so", RTLD_LAZY | RTLD_LOCAL);
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +090033
34 if (m_handle == NULL) {
35 error_msg = "Failed to load libemoji.so";
36 goto FAIL;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070037 }
38
39 m_get_implementation =
40 reinterpret_cast<EmojiFactory *(*)(const char*)>(
41 dlsym(m_handle, "GetImplementation"));
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +090042 if (m_get_implementation == NULL) {
43 error_msg = "Failed to get symbol of GetImplementation";
44 goto FAIL;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070045 }
46
47 m_get_available_implementation =
48 reinterpret_cast<EmojiFactory *(*)()>(
49 dlsym(m_handle,"GetAvailableImplementation"));
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +090050 if (m_get_available_implementation == NULL) {
51 error_msg = "Failed to get symbol of GetAvailableImplementation";
52 goto FAIL;
53 }
54
55 return true;
56
57FAIL:
58 const char* error_str = dlerror();
59 if (error_str == NULL) {
60 error_str = "unknown reason";
61 }
62
63 LOGE("%s: %s", error_msg, error_str);
64 if (m_handle != NULL) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070065 dlclose(m_handle);
66 m_handle = NULL;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070067 }
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +090068 return false;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070069}
70
71EmojiFactoryCaller::~EmojiFactoryCaller() {
72 if (m_handle) {
73 dlclose(m_handle);
74 }
75}
76
77EmojiFactory *EmojiFactoryCaller::TryCallGetImplementation(
78 const char* name) {
79 if (NULL == m_handle) {
80 return NULL;
81 }
82 return m_get_implementation(name);
83}
84
85EmojiFactory *EmojiFactoryCaller::TryCallGetAvailableImplementation() {
86 if (NULL == m_handle) {
87 return NULL;
88 }
89 return m_get_available_implementation();
90}
91
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +090092static EmojiFactoryCaller* gCaller;
93static pthread_once_t g_once = PTHREAD_ONCE_INIT;
94static bool lib_emoji_factory_is_ready;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070095
96static jclass gString_class;
97
98static jclass gBitmap_class;
99static jmethodID gBitmap_constructorMethodID;
100
101static jclass gEmojiFactory_class;
102static jmethodID gEmojiFactory_constructorMethodID;
103
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +0900104static void InitializeCaller() {
105 gCaller = new EmojiFactoryCaller();
106 lib_emoji_factory_is_ready = gCaller->Init();
107}
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700108
109static jobject create_java_EmojiFactory(
110 JNIEnv* env, EmojiFactory* factory, jstring name) {
111 jobject obj = env->AllocObject(gEmojiFactory_class);
112 if (obj) {
113 env->CallVoidMethod(obj, gEmojiFactory_constructorMethodID,
114 (jint)factory, name);
115 if (env->ExceptionCheck() != 0) {
116 LOGE("*** Uncaught exception returned from Java call!\n");
117 env->ExceptionDescribe();
118 obj = NULL;
119 }
120 }
121 return obj;
122}
123
124static jobject android_emoji_EmojiFactory_newInstance(
125 JNIEnv* env, jobject clazz, jstring name) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700126 if (NULL == name) {
127 return NULL;
128 }
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +0900129 pthread_once(&g_once, InitializeCaller);
130 if (!lib_emoji_factory_is_ready) {
131 return NULL;
132 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700133
134 const jchar* jchars = env->GetStringChars(name, NULL);
135 jsize len = env->GetStringLength(name);
136 String8 str(String16(jchars, len));
137
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +0900138 EmojiFactory *factory = gCaller->TryCallGetImplementation(str.string());
139 // EmojiFactory *factory = EmojiFactory::GetImplementation(str.string());
140 if (NULL == factory) {
141 return NULL;
142 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700143 env->ReleaseStringChars(name, jchars);
144
145 return create_java_EmojiFactory(env, factory, name);
146}
147
148static jobject android_emoji_EmojiFactory_newAvailableInstance(
149 JNIEnv* env, jobject clazz) {
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +0900150 pthread_once(&g_once, InitializeCaller);
151 if (!lib_emoji_factory_is_ready) {
152 return NULL;
153 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700154
Daisuke Miyakawa63507ba2009-05-26 14:46:35 +0900155 EmojiFactory *factory = gCaller->TryCallGetAvailableImplementation();
156 // EmojiFactory *factory = EmojiFactory::GetAvailableImplementation();
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700157 if (NULL == factory) {
158 return NULL;
159 }
160 String16 name_16(String8(factory->Name()));
161 jstring jname = env->NewString(name_16.string(), name_16.size());
162 if (NULL == jname) {
163 return NULL;
164 }
165
166 return create_java_EmojiFactory(env, factory, jname);
167}
168
169static jobject android_emoji_EmojiFactory_getBitmapFromAndroidPua(
170 JNIEnv* env, jobject clazz, jint nativeEmojiFactory, jint pua) {
171 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
172
173 int size;
174 const char *bytes = factory->GetImageBinaryFromAndroidPua(pua, &size);
175 if (bytes == NULL) {
176 return NULL;
177 }
178
179 SkBitmap *bitmap = new SkBitmap;
180 if (!SkImageDecoder::DecodeMemory(bytes, size, bitmap)) {
181 LOGE("SkImageDecoder::DecodeMemory() failed.");
182 return NULL;
183 }
184
185 jobject obj = env->AllocObject(gBitmap_class);
186 if (obj) {
187 env->CallVoidMethod(obj, gBitmap_constructorMethodID,
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800188 reinterpret_cast<jint>(bitmap), NULL, false, NULL, -1);
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700189 if (env->ExceptionCheck() != 0) {
190 LOGE("*** Uncaught exception returned from Java call!\n");
191 env->ExceptionDescribe();
192 return NULL;
193 }
194 }
195
196 return obj;
197}
198
199static void android_emoji_EmojiFactory_destructor(
200 JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
Daisuke Miyakawac81c4392009-09-01 08:32:24 +0900201 /*
202 // Must not delete this object!!
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700203 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
204 delete factory;
Daisuke Miyakawac81c4392009-09-01 08:32:24 +0900205 */
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700206}
207
208static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis(
209 JNIEnv* env, jobject obj, jint nativeEmojiFactory, jchar sjis) {
210 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
211 return factory->GetAndroidPuaFromVendorSpecificSjis(sjis);
212}
213
214static jint android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua(
215 JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) {
216 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
217 return factory->GetVendorSpecificSjisFromAndroidPua(pua);
218}
219
220static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua(
221 JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint vsu) {
222 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
223 return factory->GetAndroidPuaFromVendorSpecificPua(vsu);
224}
225
226static jint android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua(
227 JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) {
228 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
229 return factory->GetVendorSpecificPuaFromAndroidPua(pua);
230}
231
232static jint android_emoji_EmojiFactory_getMaximumVendorSpecificPua(
233 JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
234 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
235 return factory->GetMaximumVendorSpecificPua();
236}
237
238static jint android_emoji_EmojiFactory_getMinimumVendorSpecificPua(
239 JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
240 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
241 return factory->GetMinimumVendorSpecificPua();
242}
243
244static jint android_emoji_EmojiFactory_getMaximumAndroidPua(
245 JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
246 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
247 return factory->GetMaximumAndroidPua();
248}
249
250static jint android_emoji_EmojiFactory_getMinimumAndroidPua(
251 JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
252 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
253 return factory->GetMinimumAndroidPua();
254}
255
256static JNINativeMethod gMethods[] = {
257 { "newInstance", "(Ljava/lang/String;)Landroid/emoji/EmojiFactory;",
258 (void*)android_emoji_EmojiFactory_newInstance},
259 { "newAvailableInstance", "()Landroid/emoji/EmojiFactory;",
260 (void*)android_emoji_EmojiFactory_newAvailableInstance},
261 { "nativeDestructor", "(I)V",
262 (void*)android_emoji_EmojiFactory_destructor},
263 { "nativeGetBitmapFromAndroidPua", "(II)Landroid/graphics/Bitmap;",
264 (void*)android_emoji_EmojiFactory_getBitmapFromAndroidPua},
265 { "nativeGetAndroidPuaFromVendorSpecificSjis", "(IC)I",
266 (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis},
267 { "nativeGetVendorSpecificSjisFromAndroidPua", "(II)I",
268 (void*)android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua},
269 { "nativeGetAndroidPuaFromVendorSpecificPua", "(II)I",
270 (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua},
271 { "nativeGetVendorSpecificPuaFromAndroidPua", "(II)I",
272 (void*)android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua},
273 { "nativeGetMaximumVendorSpecificPua", "(I)I",
274 (void*)android_emoji_EmojiFactory_getMaximumVendorSpecificPua},
275 { "nativeGetMinimumVendorSpecificPua", "(I)I",
276 (void*)android_emoji_EmojiFactory_getMinimumVendorSpecificPua},
277 { "nativeGetMaximumAndroidPua", "(I)I",
278 (void*)android_emoji_EmojiFactory_getMaximumAndroidPua},
279 { "nativeGetMinimumAndroidPua", "(I)I",
280 (void*)android_emoji_EmojiFactory_getMinimumAndroidPua}
281};
282
283static jclass make_globalref(JNIEnv* env, const char classname[])
284{
285 jclass c = env->FindClass(classname);
286 SkASSERT(c);
287 return (jclass)env->NewGlobalRef(c);
288}
289
290static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
291 const char fieldname[], const char type[])
292{
293 jfieldID id = env->GetFieldID(clazz, fieldname, type);
294 SkASSERT(id);
295 return id;
296}
297
298int register_android_emoji_EmojiFactory(JNIEnv* env) {
299 gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
300 gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>",
Patrick Dubroye4ac2d62010-12-01 11:23:13 -0800301 "(I[BZ[BI)V");
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700302 gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory");
303 gEmojiFactory_constructorMethodID = env->GetMethodID(
304 gEmojiFactory_class, "<init>", "(ILjava/lang/String;)V");
305 return jniRegisterNativeMethods(env, "android/emoji/EmojiFactory",
306 gMethods, NELEM(gMethods));
307}
308
309} // namespace android