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 "GraphicsJNI.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 gEmojiFactory_class; 97static jmethodID gEmojiFactory_constructorMethodID; 98 99static void InitializeCaller() { 100 gCaller = new EmojiFactoryCaller(); 101 lib_emoji_factory_is_ready = gCaller->Init(); 102} 103 104static jobject create_java_EmojiFactory( 105 JNIEnv* env, EmojiFactory* factory, jstring name) { 106 jobject obj = env->NewObject(gEmojiFactory_class, gEmojiFactory_constructorMethodID, 107 reinterpret_cast<jlong>(factory), name); 108 if (env->ExceptionCheck() != 0) { 109 ALOGE("*** Uncaught exception returned from Java call!\n"); 110 env->ExceptionDescribe(); 111 } 112 return obj; 113} 114 115static jobject android_emoji_EmojiFactory_newInstance( 116 JNIEnv* env, jobject clazz, jstring name) { 117 if (NULL == name) { 118 return NULL; 119 } 120 pthread_once(&g_once, InitializeCaller); 121 if (!lib_emoji_factory_is_ready) { 122 return NULL; 123 } 124 125 ScopedUtfChars nameUtf(env, name); 126 127 EmojiFactory *factory = gCaller->TryCallGetImplementation(nameUtf.c_str()); 128 // EmojiFactory *factory = EmojiFactory::GetImplementation(str.string()); 129 if (NULL == factory) { 130 return NULL; 131 } 132 133 return create_java_EmojiFactory(env, factory, name); 134} 135 136static jobject android_emoji_EmojiFactory_newAvailableInstance( 137 JNIEnv* env, jobject clazz) { 138 pthread_once(&g_once, InitializeCaller); 139 if (!lib_emoji_factory_is_ready) { 140 return NULL; 141 } 142 143 EmojiFactory *factory = gCaller->TryCallGetAvailableImplementation(); 144 // EmojiFactory *factory = EmojiFactory::GetAvailableImplementation(); 145 if (NULL == factory) { 146 return NULL; 147 } 148 149 jstring jname = env->NewStringUTF(factory->Name()); 150 if (NULL == jname) { 151 return NULL; 152 } 153 154 return create_java_EmojiFactory(env, factory, jname); 155} 156 157static jobject android_emoji_EmojiFactory_getBitmapFromAndroidPua( 158 JNIEnv* env, jobject clazz, jlong nativeEmojiFactory, jint pua) { 159 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 160 161 int size; 162 const char *bytes = factory->GetImageBinaryFromAndroidPua(pua, &size); 163 if (bytes == NULL) { 164 return NULL; 165 } 166 167 SkBitmap *bitmap = new SkBitmap; 168 if (!SkImageDecoder::DecodeMemory(bytes, size, bitmap)) { 169 ALOGE("SkImageDecoder::DecodeMemory() failed."); 170 return NULL; 171 } 172 173 return GraphicsJNI::createBitmap(env, bitmap, 174 GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL); 175} 176 177static void android_emoji_EmojiFactory_destructor( 178 JNIEnv* env, jobject obj, jlong nativeEmojiFactory) { 179 /* 180 // Must not delete this object!! 181 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 182 delete factory; 183 */ 184} 185 186static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis( 187 JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jchar sjis) { 188 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 189 return factory->GetAndroidPuaFromVendorSpecificSjis(sjis); 190} 191 192static jint android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua( 193 JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint pua) { 194 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 195 return factory->GetVendorSpecificSjisFromAndroidPua(pua); 196} 197 198static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua( 199 JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint vsu) { 200 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 201 return factory->GetAndroidPuaFromVendorSpecificPua(vsu); 202} 203 204static jint android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua( 205 JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint pua) { 206 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 207 return factory->GetVendorSpecificPuaFromAndroidPua(pua); 208} 209 210static jint android_emoji_EmojiFactory_getMaximumVendorSpecificPua( 211 JNIEnv* env, jobject obj, jlong nativeEmojiFactory) { 212 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 213 return factory->GetMaximumVendorSpecificPua(); 214} 215 216static jint android_emoji_EmojiFactory_getMinimumVendorSpecificPua( 217 JNIEnv* env, jobject obj, jlong nativeEmojiFactory) { 218 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 219 return factory->GetMinimumVendorSpecificPua(); 220} 221 222static jint android_emoji_EmojiFactory_getMaximumAndroidPua( 223 JNIEnv* env, jobject obj, jlong nativeEmojiFactory) { 224 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 225 return factory->GetMaximumAndroidPua(); 226} 227 228static jint android_emoji_EmojiFactory_getMinimumAndroidPua( 229 JNIEnv* env, jobject obj, jlong nativeEmojiFactory) { 230 EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory); 231 return factory->GetMinimumAndroidPua(); 232} 233 234static JNINativeMethod gMethods[] = { 235 { "newInstance", "(Ljava/lang/String;)Landroid/emoji/EmojiFactory;", 236 (void*)android_emoji_EmojiFactory_newInstance}, 237 { "newAvailableInstance", "()Landroid/emoji/EmojiFactory;", 238 (void*)android_emoji_EmojiFactory_newAvailableInstance}, 239 { "nativeDestructor", "(J)V", 240 (void*)android_emoji_EmojiFactory_destructor}, 241 { "nativeGetBitmapFromAndroidPua", "(JI)Landroid/graphics/Bitmap;", 242 (void*)android_emoji_EmojiFactory_getBitmapFromAndroidPua}, 243 { "nativeGetAndroidPuaFromVendorSpecificSjis", "(JC)I", 244 (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis}, 245 { "nativeGetVendorSpecificSjisFromAndroidPua", "(JI)I", 246 (void*)android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua}, 247 { "nativeGetAndroidPuaFromVendorSpecificPua", "(JI)I", 248 (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua}, 249 { "nativeGetVendorSpecificPuaFromAndroidPua", "(JI)I", 250 (void*)android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua}, 251 { "nativeGetMaximumVendorSpecificPua", "(J)I", 252 (void*)android_emoji_EmojiFactory_getMaximumVendorSpecificPua}, 253 { "nativeGetMinimumVendorSpecificPua", "(J)I", 254 (void*)android_emoji_EmojiFactory_getMinimumVendorSpecificPua}, 255 { "nativeGetMaximumAndroidPua", "(J)I", 256 (void*)android_emoji_EmojiFactory_getMaximumAndroidPua}, 257 { "nativeGetMinimumAndroidPua", "(J)I", 258 (void*)android_emoji_EmojiFactory_getMinimumAndroidPua} 259}; 260 261static jclass make_globalref(JNIEnv* env, const char classname[]) 262{ 263 jclass c = env->FindClass(classname); 264 SkASSERT(c); 265 return (jclass)env->NewGlobalRef(c); 266} 267 268static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, 269 const char fieldname[], const char type[]) 270{ 271 jfieldID id = env->GetFieldID(clazz, fieldname, type); 272 SkASSERT(id); 273 return id; 274} 275 276int register_android_emoji_EmojiFactory(JNIEnv* env) { 277 gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory"); 278 gEmojiFactory_constructorMethodID = env->GetMethodID( 279 gEmojiFactory_class, "<init>", "(JLjava/lang/String;)V"); 280 return jniRegisterNativeMethods(env, "android/emoji/EmojiFactory", 281 gMethods, NELEM(gMethods)); 282} 283 284} // namespace android 285