OSDN Git Service

am 336fcac3: Merge "Fix bug #8194572 Chrome SIGBUS\'es on launch around TextLayoutCac...
[android-x86/frameworks-base.git] / core / jni / android_emoji_EmojiFactory.cpp
1 #include "SkTypes.h"
2 #include "SkImageDecoder.h"
3
4 #define LOG_TAG "EmojiFactory_jni"
5 #include <utils/Log.h>
6 #include <ScopedUtfChars.h>
7
8 #include "EmojiFactory.h"
9 #include <nativehelper/JNIHelp.h>
10
11 #include <dlfcn.h>
12 // #include <pthread.h>
13
14 namespace android {
15
16 class EmojiFactoryCaller {
17  public:
18   EmojiFactoryCaller() {}
19   virtual ~EmojiFactoryCaller();
20   bool Init();
21   EmojiFactory *TryCallGetImplementation(const char* name);
22   EmojiFactory *TryCallGetAvailableImplementation();
23  private:
24   void *m_handle;
25   EmojiFactory *(*m_get_implementation)(const char*);
26   EmojiFactory *(*m_get_available_implementation)();
27 };
28
29 bool EmojiFactoryCaller::Init() {
30   const char* error_msg;
31   m_handle = dlopen("libemoji.so", RTLD_LAZY | RTLD_LOCAL);
32
33   if (m_handle == NULL) {
34     error_msg = "Failed to load libemoji.so";
35     goto FAIL;
36   }
37
38   m_get_implementation =
39       reinterpret_cast<EmojiFactory *(*)(const char*)>(
40           dlsym(m_handle, "GetImplementation"));
41   if (m_get_implementation == NULL) {
42     error_msg = "Failed to get symbol of GetImplementation";
43     goto FAIL;
44   }
45
46   m_get_available_implementation =
47       reinterpret_cast<EmojiFactory *(*)()>(
48           dlsym(m_handle,"GetAvailableImplementation"));
49   if (m_get_available_implementation == NULL) {
50     error_msg = "Failed to get symbol of GetAvailableImplementation";
51     goto FAIL;
52   }
53
54   return true;
55
56 FAIL:
57   const char* error_str = dlerror();
58   if (error_str == NULL) {
59     error_str = "unknown reason";
60   }
61
62   ALOGE("%s: %s", error_msg, error_str);
63   if (m_handle != NULL) {
64     dlclose(m_handle);
65     m_handle = NULL;
66   }
67   return false;
68 }
69
70 EmojiFactoryCaller::~EmojiFactoryCaller() {
71   if (m_handle) {
72     dlclose(m_handle);
73   }
74 }
75
76 EmojiFactory *EmojiFactoryCaller::TryCallGetImplementation(
77     const char* name) {
78   if (NULL == m_handle) {
79     return NULL;
80   }
81   return m_get_implementation(name);
82 }
83
84 EmojiFactory *EmojiFactoryCaller::TryCallGetAvailableImplementation() {
85   if (NULL == m_handle) {
86     return NULL;
87   }
88   return m_get_available_implementation();
89 }
90
91 static EmojiFactoryCaller* gCaller;
92 static pthread_once_t g_once = PTHREAD_ONCE_INIT;
93 static bool lib_emoji_factory_is_ready;
94
95 static jclass    gBitmap_class;
96 static jmethodID gBitmap_constructorMethodID;
97
98 static jclass    gEmojiFactory_class;
99 static jmethodID gEmojiFactory_constructorMethodID;
100
101 static void InitializeCaller() {
102   gCaller = new EmojiFactoryCaller();
103   lib_emoji_factory_is_ready = gCaller->Init();
104 }
105
106 static jobject create_java_EmojiFactory(
107     JNIEnv* env, EmojiFactory* factory, jstring name) {
108   jobject obj = env->NewObject(gEmojiFactory_class, gEmojiFactory_constructorMethodID,
109       static_cast<jint>(reinterpret_cast<uintptr_t>(factory)), name);
110   if (env->ExceptionCheck() != 0) {
111     ALOGE("*** Uncaught exception returned from Java call!\n");
112     env->ExceptionDescribe();
113   }
114   return obj;
115 }
116
117 static jobject android_emoji_EmojiFactory_newInstance(
118     JNIEnv* env, jobject clazz, jstring name) {
119   if (NULL == name) {
120     return NULL;
121   }
122   pthread_once(&g_once, InitializeCaller);
123   if (!lib_emoji_factory_is_ready) {
124     return NULL;
125   }
126
127   ScopedUtfChars nameUtf(env, name);
128
129   EmojiFactory *factory = gCaller->TryCallGetImplementation(nameUtf.c_str());
130   // EmojiFactory *factory = EmojiFactory::GetImplementation(str.string());
131   if (NULL == factory) {
132     return NULL;
133   }
134
135   return create_java_EmojiFactory(env, factory, name);
136 }
137
138 static jobject android_emoji_EmojiFactory_newAvailableInstance(
139     JNIEnv* env, jobject clazz) {
140   pthread_once(&g_once, InitializeCaller);
141   if (!lib_emoji_factory_is_ready) {
142     return NULL;
143   }
144
145   EmojiFactory *factory = gCaller->TryCallGetAvailableImplementation();
146   // EmojiFactory *factory = EmojiFactory::GetAvailableImplementation();
147   if (NULL == factory) {
148     return NULL;
149   }
150
151   jstring jname = env->NewStringUTF(factory->Name());
152   if (NULL == jname) {
153     return NULL;
154   }
155
156   return create_java_EmojiFactory(env, factory, jname);
157 }
158
159 static jobject android_emoji_EmojiFactory_getBitmapFromAndroidPua(
160     JNIEnv* env, jobject clazz, jint nativeEmojiFactory, jint pua) {
161   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
162
163   int size;
164   const char *bytes = factory->GetImageBinaryFromAndroidPua(pua, &size);
165   if (bytes == NULL) {
166     return NULL;
167   }
168
169   SkBitmap *bitmap = new SkBitmap;
170   if (!SkImageDecoder::DecodeMemory(bytes, size, bitmap)) {
171     ALOGE("SkImageDecoder::DecodeMemory() failed.");
172     return NULL;
173   }
174
175   jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
176       static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)), NULL, false, NULL, -1);
177   if (env->ExceptionCheck() != 0) {
178     ALOGE("*** Uncaught exception returned from Java call!\n");
179     env->ExceptionDescribe();
180   }
181   return obj;
182 }
183
184 static void android_emoji_EmojiFactory_destructor(
185     JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
186   /*
187   // Must not delete this object!!
188   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
189   delete factory;
190   */
191 }
192
193 static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis(
194     JNIEnv* env, jobject obj, jint nativeEmojiFactory, jchar sjis) {
195   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
196   return factory->GetAndroidPuaFromVendorSpecificSjis(sjis);
197 }
198
199 static jint android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua(
200     JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) {
201   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
202   return factory->GetVendorSpecificSjisFromAndroidPua(pua);
203 }
204
205 static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua(
206     JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint vsu) {
207   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
208   return factory->GetAndroidPuaFromVendorSpecificPua(vsu);
209 }
210
211 static jint android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua(
212     JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) {
213   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
214   return factory->GetVendorSpecificPuaFromAndroidPua(pua);
215 }
216
217 static jint android_emoji_EmojiFactory_getMaximumVendorSpecificPua(
218     JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
219   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
220   return factory->GetMaximumVendorSpecificPua();
221 }
222
223 static jint android_emoji_EmojiFactory_getMinimumVendorSpecificPua(
224     JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
225   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
226   return factory->GetMinimumVendorSpecificPua();
227 }
228
229 static jint android_emoji_EmojiFactory_getMaximumAndroidPua(
230     JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
231   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
232   return factory->GetMaximumAndroidPua();
233 }
234
235 static jint android_emoji_EmojiFactory_getMinimumAndroidPua(
236     JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
237   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
238   return factory->GetMinimumAndroidPua();
239 }
240
241 static JNINativeMethod gMethods[] = {
242   { "newInstance", "(Ljava/lang/String;)Landroid/emoji/EmojiFactory;",
243     (void*)android_emoji_EmojiFactory_newInstance},
244   { "newAvailableInstance", "()Landroid/emoji/EmojiFactory;",
245     (void*)android_emoji_EmojiFactory_newAvailableInstance},
246   { "nativeDestructor", "(I)V",
247     (void*)android_emoji_EmojiFactory_destructor},
248   { "nativeGetBitmapFromAndroidPua", "(II)Landroid/graphics/Bitmap;",
249     (void*)android_emoji_EmojiFactory_getBitmapFromAndroidPua},
250   { "nativeGetAndroidPuaFromVendorSpecificSjis", "(IC)I",
251     (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis},
252   { "nativeGetVendorSpecificSjisFromAndroidPua", "(II)I",
253     (void*)android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua},
254   { "nativeGetAndroidPuaFromVendorSpecificPua", "(II)I",
255     (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua},
256   { "nativeGetVendorSpecificPuaFromAndroidPua", "(II)I",
257     (void*)android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua},
258   { "nativeGetMaximumVendorSpecificPua", "(I)I",
259     (void*)android_emoji_EmojiFactory_getMaximumVendorSpecificPua},
260   { "nativeGetMinimumVendorSpecificPua", "(I)I",
261     (void*)android_emoji_EmojiFactory_getMinimumVendorSpecificPua},
262   { "nativeGetMaximumAndroidPua", "(I)I",
263     (void*)android_emoji_EmojiFactory_getMaximumAndroidPua},
264   { "nativeGetMinimumAndroidPua", "(I)I",
265     (void*)android_emoji_EmojiFactory_getMinimumAndroidPua}
266 };
267
268 static jclass make_globalref(JNIEnv* env, const char classname[])
269 {
270     jclass c = env->FindClass(classname);
271     SkASSERT(c);
272     return (jclass)env->NewGlobalRef(c);
273 }
274
275 static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
276                                 const char fieldname[], const char type[])
277 {
278     jfieldID id = env->GetFieldID(clazz, fieldname, type);
279     SkASSERT(id);
280     return id;
281 }
282
283 int register_android_emoji_EmojiFactory(JNIEnv* env) {
284   gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
285   gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>",
286                                                  "(I[BZ[BI)V");
287   gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory");
288   gEmojiFactory_constructorMethodID = env->GetMethodID(
289       gEmojiFactory_class, "<init>", "(ILjava/lang/String;)V");
290   return jniRegisterNativeMethods(env, "android/emoji/EmojiFactory",
291                                   gMethods, NELEM(gMethods));
292 }
293
294 }  // namespace android