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