android_emoji_EmojiFactory.cpp revision b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54
1#include "SkTypes.h" 2#include "SkImageDecoder.h" 3 4#define LOG_TAG "DoCoMoEmojiFactory_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 16// Note: This class is originally developed so that libandroid_runtime does 17// not have to depend on libemoji which is optional library. However, we 18// cannot use this class, since current (2009-02-16) bionic libc does not allow 19// dlopen()-ing inside dlopen(), while not only this class but also libemoji 20// uses dlopen(). 21class EmojiFactoryCaller { 22 public: 23 EmojiFactoryCaller(); 24 virtual ~EmojiFactoryCaller(); 25 EmojiFactory *TryCallGetImplementation(const char* name); 26 EmojiFactory *TryCallGetAvailableImplementation(); 27 private: 28 void *m_handle; 29 EmojiFactory *(*m_get_implementation)(const char*); 30 EmojiFactory *(*m_get_available_implementation)(); 31}; 32 33EmojiFactoryCaller::EmojiFactoryCaller() { 34 m_handle = dlopen("libemoji.so", RTLD_LAZY | RTLD_LOCAL); 35 const char* error_str = dlerror(); 36 if (error_str) { 37 LOGI("Failed to load libemoji.so: %s", error_str); 38 return; 39 } 40 41 m_get_implementation = 42 reinterpret_cast<EmojiFactory *(*)(const char*)>( 43 dlsym(m_handle, "GetImplementation")); 44 error_str = dlerror(); 45 if (error_str) { 46 LOGE("Failed to get symbol of GetImplementation: %s", error_str); 47 dlclose(m_handle); 48 m_handle = NULL; 49 return; 50 } 51 52 m_get_available_implementation = 53 reinterpret_cast<EmojiFactory *(*)()>( 54 dlsym(m_handle,"GetAvailableImplementation")); 55 error_str = dlerror(); 56 if (error_str) { 57 LOGE("Failed to get symbol of GetAvailableImplementation: %s", error_str); 58 dlclose(m_handle); 59 m_handle = NULL; 60 return; 61 } 62} 63 64EmojiFactoryCaller::~EmojiFactoryCaller() { 65 if (m_handle) { 66 dlclose(m_handle); 67 } 68} 69 70EmojiFactory *EmojiFactoryCaller::TryCallGetImplementation( 71 const char* name) { 72 if (NULL == m_handle) { 73 return NULL; 74 } 75 return m_get_implementation(name); 76} 77 78EmojiFactory *EmojiFactoryCaller::TryCallGetAvailableImplementation() { 79 if (NULL == m_handle) { 80 return NULL; 81 } 82 return m_get_available_implementation(); 83} 84 85// Note: bionic libc's dlopen() does not allow recursive dlopen(). So currently 86// we cannot use EmojiFactoryCaller here. 87// static EmojiFactoryCaller* gCaller; 88// static pthread_once_t g_once = PTHREAD_ONCE_INIT; 89 90static jclass gString_class; 91 92static jclass gBitmap_class; 93static jmethodID gBitmap_constructorMethodID; 94 95static jclass gEmojiFactory_class; 96static jmethodID gEmojiFactory_constructorMethodID; 97 98// static void InitializeCaller() { 99// gCaller = new EmojiFactoryCaller(); 100// } 101 102static jobject create_java_EmojiFactory( 103 JNIEnv* env, EmojiFactory* factory, jstring name) { 104 jobject obj = env->AllocObject(gEmojiFactory_class); 105 if (obj) { 106 env->CallVoidMethod(obj, gEmojiFactory_constructorMethodID, 107 (jint)factory, name); 108 if (env->ExceptionCheck() != 0) { 109 LOGE("*** Uncaught exception returned from Java call!\n"); 110 env->ExceptionDescribe(); 111 obj = NULL; 112 } 113 } 114 return obj; 115} 116 117static jobject android_emoji_EmojiFactory_newInstance( 118 JNIEnv* env, jobject clazz, jstring name) { 119 // pthread_once(&g_once, InitializeCaller); 120 121 if (NULL == name) { 122 return NULL; 123 } 124 125 const jchar* jchars = env->GetStringChars(name, NULL); 126 jsize len = env->GetStringLength(name); 127 String8 str(String16(jchars, len)); 128 129 // EmojiFactory *factory = gCaller->TryCallGetImplementation(str.string()); 130 EmojiFactory *factory = EmojiFactory::GetImplementation(str.string()); 131 132 env->ReleaseStringChars(name, jchars); 133 134 return create_java_EmojiFactory(env, factory, name); 135} 136 137static jobject android_emoji_EmojiFactory_newAvailableInstance( 138 JNIEnv* env, jobject clazz) { 139 // pthread_once(&g_once, InitializeCaller); 140 141 // EmojiFactory *factory = gCaller->TryCallGetAvailableImplementation(); 142 EmojiFactory *factory = EmojiFactory::GetAvailableImplementation(); 143 if (NULL == factory) { 144 return NULL; 145 } 146 String16 name_16(String8(factory->Name())); 147 jstring jname = env->NewString(name_16.string(), name_16.size()); 148 if (NULL == jname) { 149 return NULL; 150 } 151 152 return create_java_EmojiFactory(env, factory, jname); 153} 154 155static jobject android_emoji_EmojiFactory_getBitmapFromAndroidPua( 156 JNIEnv* env, jobject clazz, jint nativeEmojiFactory, jint pua) { 157 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 158 159 int size; 160 const char *bytes = factory->GetImageBinaryFromAndroidPua(pua, &size); 161 if (bytes == NULL) { 162 return NULL; 163 } 164 165 SkBitmap *bitmap = new SkBitmap; 166 if (!SkImageDecoder::DecodeMemory(bytes, size, bitmap)) { 167 LOGE("SkImageDecoder::DecodeMemory() failed."); 168 return NULL; 169 } 170 171 jobject obj = env->AllocObject(gBitmap_class); 172 if (obj) { 173 env->CallVoidMethod(obj, gBitmap_constructorMethodID, 174 reinterpret_cast<jint>(bitmap), false, NULL); 175 if (env->ExceptionCheck() != 0) { 176 LOGE("*** Uncaught exception returned from Java call!\n"); 177 env->ExceptionDescribe(); 178 return NULL; 179 } 180 } 181 182 return obj; 183} 184 185static void android_emoji_EmojiFactory_destructor( 186 JNIEnv* env, jobject obj, jint nativeEmojiFactory) { 187 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 188 delete factory; 189} 190 191static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis( 192 JNIEnv* env, jobject obj, jint nativeEmojiFactory, jchar sjis) { 193 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 194 return factory->GetAndroidPuaFromVendorSpecificSjis(sjis); 195} 196 197static jint android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua( 198 JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) { 199 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 200 return factory->GetVendorSpecificSjisFromAndroidPua(pua); 201} 202 203static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua( 204 JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint vsu) { 205 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 206 return factory->GetAndroidPuaFromVendorSpecificPua(vsu); 207} 208 209static jint android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua( 210 JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) { 211 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 212 return factory->GetVendorSpecificPuaFromAndroidPua(pua); 213} 214 215static jint android_emoji_EmojiFactory_getMaximumVendorSpecificPua( 216 JNIEnv* env, jobject obj, jint nativeEmojiFactory) { 217 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 218 return factory->GetMaximumVendorSpecificPua(); 219} 220 221static jint android_emoji_EmojiFactory_getMinimumVendorSpecificPua( 222 JNIEnv* env, jobject obj, jint nativeEmojiFactory) { 223 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 224 return factory->GetMinimumVendorSpecificPua(); 225} 226 227static jint android_emoji_EmojiFactory_getMaximumAndroidPua( 228 JNIEnv* env, jobject obj, jint nativeEmojiFactory) { 229 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 230 return factory->GetMaximumAndroidPua(); 231} 232 233static jint android_emoji_EmojiFactory_getMinimumAndroidPua( 234 JNIEnv* env, jobject obj, jint nativeEmojiFactory) { 235 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 236 return factory->GetMinimumAndroidPua(); 237} 238 239static JNINativeMethod gMethods[] = { 240 { "newInstance", "(Ljava/lang/String;)Landroid/emoji/EmojiFactory;", 241 (void*)android_emoji_EmojiFactory_newInstance}, 242 { "newAvailableInstance", "()Landroid/emoji/EmojiFactory;", 243 (void*)android_emoji_EmojiFactory_newAvailableInstance}, 244 { "nativeDestructor", "(I)V", 245 (void*)android_emoji_EmojiFactory_destructor}, 246 { "nativeGetBitmapFromAndroidPua", "(II)Landroid/graphics/Bitmap;", 247 (void*)android_emoji_EmojiFactory_getBitmapFromAndroidPua}, 248 { "nativeGetAndroidPuaFromVendorSpecificSjis", "(IC)I", 249 (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis}, 250 { "nativeGetVendorSpecificSjisFromAndroidPua", "(II)I", 251 (void*)android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua}, 252 { "nativeGetAndroidPuaFromVendorSpecificPua", "(II)I", 253 (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua}, 254 { "nativeGetVendorSpecificPuaFromAndroidPua", "(II)I", 255 (void*)android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua}, 256 { "nativeGetMaximumVendorSpecificPua", "(I)I", 257 (void*)android_emoji_EmojiFactory_getMaximumVendorSpecificPua}, 258 { "nativeGetMinimumVendorSpecificPua", "(I)I", 259 (void*)android_emoji_EmojiFactory_getMinimumVendorSpecificPua}, 260 { "nativeGetMaximumAndroidPua", "(I)I", 261 (void*)android_emoji_EmojiFactory_getMaximumAndroidPua}, 262 { "nativeGetMinimumAndroidPua", "(I)I", 263 (void*)android_emoji_EmojiFactory_getMinimumAndroidPua} 264}; 265 266static jclass make_globalref(JNIEnv* env, const char classname[]) 267{ 268 jclass c = env->FindClass(classname); 269 SkASSERT(c); 270 return (jclass)env->NewGlobalRef(c); 271} 272 273static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, 274 const char fieldname[], const char type[]) 275{ 276 jfieldID id = env->GetFieldID(clazz, fieldname, type); 277 SkASSERT(id); 278 return id; 279} 280 281int register_android_emoji_EmojiFactory(JNIEnv* env) { 282 gBitmap_class = make_globalref(env, "android/graphics/Bitmap"); 283 gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", 284 "(IZ[B)V"); 285 gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory"); 286 gEmojiFactory_constructorMethodID = env->GetMethodID( 287 gEmojiFactory_class, "<init>", "(ILjava/lang/String;)V"); 288 return jniRegisterNativeMethods(env, "android/emoji/EmojiFactory", 289 gMethods, NELEM(gMethods)); 290} 291 292} // namespace android 293