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 "GraphicsJNI.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 ALOGE("%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 gEmojiFactory_class;
97 static jmethodID gEmojiFactory_constructorMethodID;
98
InitializeCaller()99 static void InitializeCaller() {
100 gCaller = new EmojiFactoryCaller();
101 lib_emoji_factory_is_ready = gCaller->Init();
102 }
103
create_java_EmojiFactory(JNIEnv * env,EmojiFactory * factory,jstring name)104 static jobject create_java_EmojiFactory(
105 JNIEnv* env, EmojiFactory* factory, jstring name) {
106 jobject obj = env->NewObject(gEmojiFactory_class, gEmojiFactory_constructorMethodID,
107 reinterpret_cast<jlong>(factory), name);
108 if (env->ExceptionCheck() != 0) {
109 ALOGE("*** Uncaught exception returned from Java call!\n");
110 env->ExceptionDescribe();
111 }
112 return obj;
113 }
114
android_emoji_EmojiFactory_newInstance(JNIEnv * env,jobject clazz,jstring name)115 static jobject android_emoji_EmojiFactory_newInstance(
116 JNIEnv* env, jobject clazz, jstring name) {
117 if (NULL == name) {
118 return NULL;
119 }
120 pthread_once(&g_once, InitializeCaller);
121 if (!lib_emoji_factory_is_ready) {
122 return NULL;
123 }
124
125 ScopedUtfChars nameUtf(env, name);
126
127 EmojiFactory *factory = gCaller->TryCallGetImplementation(nameUtf.c_str());
128 // EmojiFactory *factory = EmojiFactory::GetImplementation(str.string());
129 if (NULL == factory) {
130 return NULL;
131 }
132
133 return create_java_EmojiFactory(env, factory, name);
134 }
135
android_emoji_EmojiFactory_newAvailableInstance(JNIEnv * env,jobject clazz)136 static jobject android_emoji_EmojiFactory_newAvailableInstance(
137 JNIEnv* env, jobject clazz) {
138 pthread_once(&g_once, InitializeCaller);
139 if (!lib_emoji_factory_is_ready) {
140 return NULL;
141 }
142
143 EmojiFactory *factory = gCaller->TryCallGetAvailableImplementation();
144 // EmojiFactory *factory = EmojiFactory::GetAvailableImplementation();
145 if (NULL == factory) {
146 return NULL;
147 }
148
149 jstring jname = env->NewStringUTF(factory->Name());
150 if (NULL == jname) {
151 return NULL;
152 }
153
154 return create_java_EmojiFactory(env, factory, jname);
155 }
156
android_emoji_EmojiFactory_getBitmapFromAndroidPua(JNIEnv * env,jobject clazz,jlong nativeEmojiFactory,jint pua)157 static jobject android_emoji_EmojiFactory_getBitmapFromAndroidPua(
158 JNIEnv* env, jobject clazz, jlong nativeEmojiFactory, jint pua) {
159 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
160
161 int size;
162 const char *bytes = factory->GetImageBinaryFromAndroidPua(pua, &size);
163 if (bytes == NULL) {
164 return NULL;
165 }
166
167 SkBitmap *bitmap = new SkBitmap;
168 if (!SkImageDecoder::DecodeMemory(bytes, size, bitmap)) {
169 ALOGE("SkImageDecoder::DecodeMemory() failed.");
170 return NULL;
171 }
172
173 return GraphicsJNI::createBitmap(env, bitmap,
174 GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL);
175 }
176
android_emoji_EmojiFactory_destructor(JNIEnv * env,jobject obj,jlong nativeEmojiFactory)177 static void android_emoji_EmojiFactory_destructor(
178 JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
179 /*
180 // Must not delete this object!!
181 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
182 delete factory;
183 */
184 }
185
android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis(JNIEnv * env,jobject obj,jlong nativeEmojiFactory,jchar sjis)186 static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis(
187 JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jchar sjis) {
188 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
189 return factory->GetAndroidPuaFromVendorSpecificSjis(sjis);
190 }
191
android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua(JNIEnv * env,jobject obj,jlong nativeEmojiFactory,jint pua)192 static jint android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua(
193 JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint pua) {
194 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
195 return factory->GetVendorSpecificSjisFromAndroidPua(pua);
196 }
197
android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua(JNIEnv * env,jobject obj,jlong nativeEmojiFactory,jint vsu)198 static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua(
199 JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint vsu) {
200 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
201 return factory->GetAndroidPuaFromVendorSpecificPua(vsu);
202 }
203
android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua(JNIEnv * env,jobject obj,jlong nativeEmojiFactory,jint pua)204 static jint android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua(
205 JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint pua) {
206 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
207 return factory->GetVendorSpecificPuaFromAndroidPua(pua);
208 }
209
android_emoji_EmojiFactory_getMaximumVendorSpecificPua(JNIEnv * env,jobject obj,jlong nativeEmojiFactory)210 static jint android_emoji_EmojiFactory_getMaximumVendorSpecificPua(
211 JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
212 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
213 return factory->GetMaximumVendorSpecificPua();
214 }
215
android_emoji_EmojiFactory_getMinimumVendorSpecificPua(JNIEnv * env,jobject obj,jlong nativeEmojiFactory)216 static jint android_emoji_EmojiFactory_getMinimumVendorSpecificPua(
217 JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
218 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
219 return factory->GetMinimumVendorSpecificPua();
220 }
221
android_emoji_EmojiFactory_getMaximumAndroidPua(JNIEnv * env,jobject obj,jlong nativeEmojiFactory)222 static jint android_emoji_EmojiFactory_getMaximumAndroidPua(
223 JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
224 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
225 return factory->GetMaximumAndroidPua();
226 }
227
android_emoji_EmojiFactory_getMinimumAndroidPua(JNIEnv * env,jobject obj,jlong nativeEmojiFactory)228 static jint android_emoji_EmojiFactory_getMinimumAndroidPua(
229 JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
230 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
231 return factory->GetMinimumAndroidPua();
232 }
233
234 static JNINativeMethod gMethods[] = {
235 { "newInstance", "(Ljava/lang/String;)Landroid/emoji/EmojiFactory;",
236 (void*)android_emoji_EmojiFactory_newInstance},
237 { "newAvailableInstance", "()Landroid/emoji/EmojiFactory;",
238 (void*)android_emoji_EmojiFactory_newAvailableInstance},
239 { "nativeDestructor", "(J)V",
240 (void*)android_emoji_EmojiFactory_destructor},
241 { "nativeGetBitmapFromAndroidPua", "(JI)Landroid/graphics/Bitmap;",
242 (void*)android_emoji_EmojiFactory_getBitmapFromAndroidPua},
243 { "nativeGetAndroidPuaFromVendorSpecificSjis", "(JC)I",
244 (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis},
245 { "nativeGetVendorSpecificSjisFromAndroidPua", "(JI)I",
246 (void*)android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua},
247 { "nativeGetAndroidPuaFromVendorSpecificPua", "(JI)I",
248 (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua},
249 { "nativeGetVendorSpecificPuaFromAndroidPua", "(JI)I",
250 (void*)android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua},
251 { "nativeGetMaximumVendorSpecificPua", "(J)I",
252 (void*)android_emoji_EmojiFactory_getMaximumVendorSpecificPua},
253 { "nativeGetMinimumVendorSpecificPua", "(J)I",
254 (void*)android_emoji_EmojiFactory_getMinimumVendorSpecificPua},
255 { "nativeGetMaximumAndroidPua", "(J)I",
256 (void*)android_emoji_EmojiFactory_getMaximumAndroidPua},
257 { "nativeGetMinimumAndroidPua", "(J)I",
258 (void*)android_emoji_EmojiFactory_getMinimumAndroidPua}
259 };
260
make_globalref(JNIEnv * env,const char classname[])261 static jclass make_globalref(JNIEnv* env, const char classname[])
262 {
263 jclass c = env->FindClass(classname);
264 SkASSERT(c);
265 return (jclass)env->NewGlobalRef(c);
266 }
267
getFieldIDCheck(JNIEnv * env,jclass clazz,const char fieldname[],const char type[])268 static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
269 const char fieldname[], const char type[])
270 {
271 jfieldID id = env->GetFieldID(clazz, fieldname, type);
272 SkASSERT(id);
273 return id;
274 }
275
register_android_emoji_EmojiFactory(JNIEnv * env)276 int register_android_emoji_EmojiFactory(JNIEnv* env) {
277 gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory");
278 gEmojiFactory_constructorMethodID = env->GetMethodID(
279 gEmojiFactory_class, "<init>", "(JLjava/lang/String;)V");
280 return jniRegisterNativeMethods(env, "android/emoji/EmojiFactory",
281 gMethods, NELEM(gMethods));
282 }
283
284 } // namespace android
285