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