Home | History | Annotate | Download | only in jni
      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
    295