• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkTypes.h"
2 #include "SkImageDecoder.h"
3 
4 #define LOG_TAG "EmojiFactory_jni"
5 #include <utils/Log.h>
6 #include <utils/String8.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:
EmojiFactoryCaller()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 
Init()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   LOGE("%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 
~EmojiFactoryCaller()70 EmojiFactoryCaller::~EmojiFactoryCaller() {
71   if (m_handle) {
72     dlclose(m_handle);
73   }
74 }
75 
TryCallGetImplementation(const char * name)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 
TryCallGetAvailableImplementation()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    gString_class;
96 
97 static jclass    gBitmap_class;
98 static jmethodID gBitmap_constructorMethodID;
99 
100 static jclass    gEmojiFactory_class;
101 static jmethodID gEmojiFactory_constructorMethodID;
102 
InitializeCaller()103 static void InitializeCaller() {
104   gCaller = new EmojiFactoryCaller();
105   lib_emoji_factory_is_ready = gCaller->Init();
106 }
107 
create_java_EmojiFactory(JNIEnv * env,EmojiFactory * factory,jstring name)108 static jobject create_java_EmojiFactory(
109     JNIEnv* env, EmojiFactory* factory, jstring name) {
110   jobject obj = env->AllocObject(gEmojiFactory_class);
111   if (obj) {
112     env->CallVoidMethod(obj, gEmojiFactory_constructorMethodID,
113                         (jint)factory, name);
114     if (env->ExceptionCheck() != 0) {
115       LOGE("*** Uncaught exception returned from Java call!\n");
116       env->ExceptionDescribe();
117       obj = NULL;
118     }
119   }
120   return obj;
121 }
122 
android_emoji_EmojiFactory_newInstance(JNIEnv * env,jobject clazz,jstring name)123 static jobject android_emoji_EmojiFactory_newInstance(
124     JNIEnv* env, jobject clazz, jstring name) {
125   if (NULL == name) {
126     return NULL;
127   }
128   pthread_once(&g_once, InitializeCaller);
129   if (!lib_emoji_factory_is_ready) {
130     return NULL;
131   }
132 
133   const jchar* jchars = env->GetStringChars(name, NULL);
134   jsize len = env->GetStringLength(name);
135   String8 str(String16(jchars, len));
136 
137   EmojiFactory *factory = gCaller->TryCallGetImplementation(str.string());
138   // EmojiFactory *factory = EmojiFactory::GetImplementation(str.string());
139   if (NULL == factory) {
140     return NULL;
141   }
142   env->ReleaseStringChars(name, jchars);
143 
144   return create_java_EmojiFactory(env, factory, name);
145 }
146 
android_emoji_EmojiFactory_newAvailableInstance(JNIEnv * env,jobject clazz)147 static jobject android_emoji_EmojiFactory_newAvailableInstance(
148     JNIEnv* env, jobject clazz) {
149   pthread_once(&g_once, InitializeCaller);
150   if (!lib_emoji_factory_is_ready) {
151     return NULL;
152   }
153 
154   EmojiFactory *factory = gCaller->TryCallGetAvailableImplementation();
155   // EmojiFactory *factory = EmojiFactory::GetAvailableImplementation();
156   if (NULL == factory) {
157     return NULL;
158   }
159   String16 name_16(String8(factory->Name()));
160   jstring jname = env->NewString(name_16.string(), name_16.size());
161   if (NULL == jname) {
162     return NULL;
163   }
164 
165   return create_java_EmojiFactory(env, factory, jname);
166 }
167 
android_emoji_EmojiFactory_getBitmapFromAndroidPua(JNIEnv * env,jobject clazz,jint nativeEmojiFactory,jint pua)168 static jobject android_emoji_EmojiFactory_getBitmapFromAndroidPua(
169     JNIEnv* env, jobject clazz, jint nativeEmojiFactory, jint pua) {
170   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
171 
172   int size;
173   const char *bytes = factory->GetImageBinaryFromAndroidPua(pua, &size);
174   if (bytes == NULL) {
175     return NULL;
176   }
177 
178   SkBitmap *bitmap = new SkBitmap;
179   if (!SkImageDecoder::DecodeMemory(bytes, size, bitmap)) {
180     LOGE("SkImageDecoder::DecodeMemory() failed.");
181     return NULL;
182   }
183 
184   jobject obj = env->AllocObject(gBitmap_class);
185   if (obj) {
186     env->CallVoidMethod(obj, gBitmap_constructorMethodID,
187                         reinterpret_cast<jint>(bitmap), false, NULL, -1);
188     if (env->ExceptionCheck() != 0) {
189       LOGE("*** Uncaught exception returned from Java call!\n");
190       env->ExceptionDescribe();
191       return NULL;
192     }
193   }
194 
195   return obj;
196 }
197 
android_emoji_EmojiFactory_destructor(JNIEnv * env,jobject obj,jint nativeEmojiFactory)198 static void android_emoji_EmojiFactory_destructor(
199     JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
200   /*
201   // Must not delete this object!!
202   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
203   delete factory;
204   */
205 }
206 
android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis(JNIEnv * env,jobject obj,jint nativeEmojiFactory,jchar sjis)207 static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis(
208     JNIEnv* env, jobject obj, jint nativeEmojiFactory, jchar sjis) {
209   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
210   return factory->GetAndroidPuaFromVendorSpecificSjis(sjis);
211 }
212 
android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua(JNIEnv * env,jobject obj,jint nativeEmojiFactory,jint pua)213 static jint android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua(
214     JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) {
215   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
216   return factory->GetVendorSpecificSjisFromAndroidPua(pua);
217 }
218 
android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua(JNIEnv * env,jobject obj,jint nativeEmojiFactory,jint vsu)219 static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua(
220     JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint vsu) {
221   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
222   return factory->GetAndroidPuaFromVendorSpecificPua(vsu);
223 }
224 
android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua(JNIEnv * env,jobject obj,jint nativeEmojiFactory,jint pua)225 static jint android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua(
226     JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) {
227   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
228   return factory->GetVendorSpecificPuaFromAndroidPua(pua);
229 }
230 
android_emoji_EmojiFactory_getMaximumVendorSpecificPua(JNIEnv * env,jobject obj,jint nativeEmojiFactory)231 static jint android_emoji_EmojiFactory_getMaximumVendorSpecificPua(
232     JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
233   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
234   return factory->GetMaximumVendorSpecificPua();
235 }
236 
android_emoji_EmojiFactory_getMinimumVendorSpecificPua(JNIEnv * env,jobject obj,jint nativeEmojiFactory)237 static jint android_emoji_EmojiFactory_getMinimumVendorSpecificPua(
238     JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
239   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
240   return factory->GetMinimumVendorSpecificPua();
241 }
242 
android_emoji_EmojiFactory_getMaximumAndroidPua(JNIEnv * env,jobject obj,jint nativeEmojiFactory)243 static jint android_emoji_EmojiFactory_getMaximumAndroidPua(
244     JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
245   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
246   return factory->GetMaximumAndroidPua();
247 }
248 
android_emoji_EmojiFactory_getMinimumAndroidPua(JNIEnv * env,jobject obj,jint nativeEmojiFactory)249 static jint android_emoji_EmojiFactory_getMinimumAndroidPua(
250     JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
251   EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
252   return factory->GetMinimumAndroidPua();
253 }
254 
255 static JNINativeMethod gMethods[] = {
256   { "newInstance", "(Ljava/lang/String;)Landroid/emoji/EmojiFactory;",
257     (void*)android_emoji_EmojiFactory_newInstance},
258   { "newAvailableInstance", "()Landroid/emoji/EmojiFactory;",
259     (void*)android_emoji_EmojiFactory_newAvailableInstance},
260   { "nativeDestructor", "(I)V",
261     (void*)android_emoji_EmojiFactory_destructor},
262   { "nativeGetBitmapFromAndroidPua", "(II)Landroid/graphics/Bitmap;",
263     (void*)android_emoji_EmojiFactory_getBitmapFromAndroidPua},
264   { "nativeGetAndroidPuaFromVendorSpecificSjis", "(IC)I",
265     (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis},
266   { "nativeGetVendorSpecificSjisFromAndroidPua", "(II)I",
267     (void*)android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua},
268   { "nativeGetAndroidPuaFromVendorSpecificPua", "(II)I",
269     (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua},
270   { "nativeGetVendorSpecificPuaFromAndroidPua", "(II)I",
271     (void*)android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua},
272   { "nativeGetMaximumVendorSpecificPua", "(I)I",
273     (void*)android_emoji_EmojiFactory_getMaximumVendorSpecificPua},
274   { "nativeGetMinimumVendorSpecificPua", "(I)I",
275     (void*)android_emoji_EmojiFactory_getMinimumVendorSpecificPua},
276   { "nativeGetMaximumAndroidPua", "(I)I",
277     (void*)android_emoji_EmojiFactory_getMaximumAndroidPua},
278   { "nativeGetMinimumAndroidPua", "(I)I",
279     (void*)android_emoji_EmojiFactory_getMinimumAndroidPua}
280 };
281 
make_globalref(JNIEnv * env,const char classname[])282 static jclass make_globalref(JNIEnv* env, const char classname[])
283 {
284     jclass c = env->FindClass(classname);
285     SkASSERT(c);
286     return (jclass)env->NewGlobalRef(c);
287 }
288 
getFieldIDCheck(JNIEnv * env,jclass clazz,const char fieldname[],const char type[])289 static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
290                                 const char fieldname[], const char type[])
291 {
292     jfieldID id = env->GetFieldID(clazz, fieldname, type);
293     SkASSERT(id);
294     return id;
295 }
296 
register_android_emoji_EmojiFactory(JNIEnv * env)297 int register_android_emoji_EmojiFactory(JNIEnv* env) {
298   gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
299   gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>",
300                                                  "(IZ[BI)V");
301   gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory");
302   gEmojiFactory_constructorMethodID = env->GetMethodID(
303       gEmojiFactory_class, "<init>", "(ILjava/lang/String;)V");
304   return jniRegisterNativeMethods(env, "android/emoji/EmojiFactory",
305                                   gMethods, NELEM(gMethods));
306 }
307 
308 }  // namespace android
309