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 "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:
     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 
     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 
     71 EmojiFactoryCaller::~EmojiFactoryCaller() {
     72   if (m_handle) {
     73     dlclose(m_handle);
     74   }
     75 }
     76 
     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 
     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 
     99 static void InitializeCaller() {
    100   gCaller = new EmojiFactoryCaller();
    101   lib_emoji_factory_is_ready = gCaller->Init();
    102 }
    103 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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