android_emoji_EmojiFactory.cpp revision cdf34469b3a49b73ffa4ab2766b55d7c0946fab1
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
15namespace android {
16
17class EmojiFactoryCaller {
18 public:
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
30bool 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
57FAIL:
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
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
92static EmojiFactoryCaller* gCaller;
93static pthread_once_t g_once = PTHREAD_ONCE_INIT;
94static bool lib_emoji_factory_is_ready;
95
96static jclass    gEmojiFactory_class;
97static jmethodID gEmojiFactory_constructorMethodID;
98
99static void InitializeCaller() {
100  gCaller = new EmojiFactoryCaller();
101  lib_emoji_factory_is_ready = gCaller->Init();
102}
103
104static 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
115static 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
136static 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
157static 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
177static 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
186static 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
192static 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
198static 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
204static 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
210static 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
216static 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
222static 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
228static 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
234static 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
261static 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
268static 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
276int 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