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