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