android_emoji_EmojiFactory.cpp revision 63507babb6798d65bf965de6ea4622b7ec65aa28
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 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 201 delete factory; 202} 203 204static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis( 205 JNIEnv* env, jobject obj, jint nativeEmojiFactory, jchar sjis) { 206 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 207 return factory->GetAndroidPuaFromVendorSpecificSjis(sjis); 208} 209 210static jint android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua( 211 JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) { 212 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 213 return factory->GetVendorSpecificSjisFromAndroidPua(pua); 214} 215 216static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua( 217 JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint vsu) { 218 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 219 return factory->GetAndroidPuaFromVendorSpecificPua(vsu); 220} 221 222static jint android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua( 223 JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) { 224 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 225 return factory->GetVendorSpecificPuaFromAndroidPua(pua); 226} 227 228static jint android_emoji_EmojiFactory_getMaximumVendorSpecificPua( 229 JNIEnv* env, jobject obj, jint nativeEmojiFactory) { 230 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 231 return factory->GetMaximumVendorSpecificPua(); 232} 233 234static jint android_emoji_EmojiFactory_getMinimumVendorSpecificPua( 235 JNIEnv* env, jobject obj, jint nativeEmojiFactory) { 236 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 237 return factory->GetMinimumVendorSpecificPua(); 238} 239 240static jint android_emoji_EmojiFactory_getMaximumAndroidPua( 241 JNIEnv* env, jobject obj, jint nativeEmojiFactory) { 242 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 243 return factory->GetMaximumAndroidPua(); 244} 245 246static jint android_emoji_EmojiFactory_getMinimumAndroidPua( 247 JNIEnv* env, jobject obj, jint nativeEmojiFactory) { 248 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 249 return factory->GetMinimumAndroidPua(); 250} 251 252static JNINativeMethod gMethods[] = { 253 { "newInstance", "(Ljava/lang/String;)Landroid/emoji/EmojiFactory;", 254 (void*)android_emoji_EmojiFactory_newInstance}, 255 { "newAvailableInstance", "()Landroid/emoji/EmojiFactory;", 256 (void*)android_emoji_EmojiFactory_newAvailableInstance}, 257 { "nativeDestructor", "(I)V", 258 (void*)android_emoji_EmojiFactory_destructor}, 259 { "nativeGetBitmapFromAndroidPua", "(II)Landroid/graphics/Bitmap;", 260 (void*)android_emoji_EmojiFactory_getBitmapFromAndroidPua}, 261 { "nativeGetAndroidPuaFromVendorSpecificSjis", "(IC)I", 262 (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis}, 263 { "nativeGetVendorSpecificSjisFromAndroidPua", "(II)I", 264 (void*)android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua}, 265 { "nativeGetAndroidPuaFromVendorSpecificPua", "(II)I", 266 (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua}, 267 { "nativeGetVendorSpecificPuaFromAndroidPua", "(II)I", 268 (void*)android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua}, 269 { "nativeGetMaximumVendorSpecificPua", "(I)I", 270 (void*)android_emoji_EmojiFactory_getMaximumVendorSpecificPua}, 271 { "nativeGetMinimumVendorSpecificPua", "(I)I", 272 (void*)android_emoji_EmojiFactory_getMinimumVendorSpecificPua}, 273 { "nativeGetMaximumAndroidPua", "(I)I", 274 (void*)android_emoji_EmojiFactory_getMaximumAndroidPua}, 275 { "nativeGetMinimumAndroidPua", "(I)I", 276 (void*)android_emoji_EmojiFactory_getMinimumAndroidPua} 277}; 278 279static jclass make_globalref(JNIEnv* env, const char classname[]) 280{ 281 jclass c = env->FindClass(classname); 282 SkASSERT(c); 283 return (jclass)env->NewGlobalRef(c); 284} 285 286static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, 287 const char fieldname[], const char type[]) 288{ 289 jfieldID id = env->GetFieldID(clazz, fieldname, type); 290 SkASSERT(id); 291 return id; 292} 293 294int register_android_emoji_EmojiFactory(JNIEnv* env) { 295 gBitmap_class = make_globalref(env, "android/graphics/Bitmap"); 296 gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", 297 "(IZ[B)V"); 298 gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory"); 299 gEmojiFactory_constructorMethodID = env->GetMethodID( 300 gEmojiFactory_class, "<init>", "(ILjava/lang/String;)V"); 301 return jniRegisterNativeMethods(env, "android/emoji/EmojiFactory", 302 gMethods, NELEM(gMethods)); 303} 304 305} // namespace android 306