17d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project/* 27d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * Copyright (C) 2009 The Android Open Source Project 37d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * 47d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 57d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * you may not use this file except in compliance with the License. 67d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * You may obtain a copy of the License at 77d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * 87d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 97d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * 107d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 117d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 127d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * See the License for the specific language governing permissions and 147d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project * limitations under the License. 157d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project */ 167d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 177d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project#include "EmojiFactory.h" 187d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 197d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project#define LOG_TAG "EmojiFactory" 207d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project#include <utils/Log.h> 217d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project#include <utils/Vector.h> 227d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 237d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project#include <cutils/properties.h> 247d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 257d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project#include <dlfcn.h> 267d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project#include <stdlib.h> 277d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project#include <string.h> 287d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project#include <pthread.h> 297d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 307d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 317d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Projectnamespace android { 327d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 337d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Projectstatic pthread_once_t g_once = PTHREAD_ONCE_INIT; 347d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Projectstatic Vector<EmojiFactory *> *g_factories = NULL; 357d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Projectstatic Vector<void *> *g_handles = NULL; 367d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 377d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Projectclass EmojiFactoryManager { 387d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project public: 39e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawa void Init(); 407d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project virtual ~EmojiFactoryManager(); 417d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project private: 427d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project void TryRegisterEmojiFactory(const char *library_name); 437d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project}; 447d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 457d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project// Note: I previously did this procedure in the construcor. However, 467d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project// property_get() didn't return a correct value in that context. I guess 477d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project// property_get() does not return correct values before AndroidRuntime 487d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project// instance (or exactly, AppRuntime in instance app_main.cpp) is 497d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project// fully ready (see AndroidRunitem.cpp and app_main.cpp). 507d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project// So, instead of doing this in constructor, I decided this shoud be done 517d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project// when a user requires to EmojiFactory, which makes better sense to me. 52e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawavoid EmojiFactoryManager::Init() { 537d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project g_handles = new Vector<void *>(); 547d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project g_factories = new Vector<EmojiFactory *>(); 557d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 567d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project char *emoji_libraries = new char[PROPERTY_VALUE_MAX]; 577d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project int len = property_get("ro.config.libemoji", emoji_libraries, ""); 587d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project // LOGD("ro.config.libemoji: %s", emoji_libraries); 597d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project if (len > 0) { 607d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project char *saveptr, *ptr; 617d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project ptr = emoji_libraries; 627d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project while (true) { 637d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project ptr = strtok_r(ptr, ":", &saveptr); 647d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project if (NULL == ptr) { 657d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project break; 667d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 677d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project TryRegisterEmojiFactory(ptr); 687d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project ptr = NULL; 697d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 707d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 717d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 727d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project delete [] emoji_libraries; 737d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project} 747d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 757d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Projectvoid EmojiFactoryManager::TryRegisterEmojiFactory(const char *library_name) { 767d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project void *handle = dlopen(library_name, RTLD_LAZY | RTLD_LOCAL); 77e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawa if (handle == NULL) { 78e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawa const char* error_str = dlerror(); 79e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawa if (error_str) { 80e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawa error_str = "Unknown reason"; 81e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawa } 827d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project LOGE("Failed to load shared library %s: %s", library_name, error_str); 837d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project return; 847d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 857d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project EmojiFactory *(*get_emoji_factory)() = 867d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project reinterpret_cast<EmojiFactory *(*)()>(dlsym(handle, 877d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project "GetEmojiFactory")); 88e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawa if (get_emoji_factory == NULL) { 89e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawa const char* error_str = dlerror(); 90e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawa if (error_str) { 91e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawa error_str = "Unknown reason"; 92e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawa } 937d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project LOGE("Failed to call GetEmojiFactory: %s", error_str); 947d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project dlclose(handle); 957d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project return; 967d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 977d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 987d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project EmojiFactory *factory = (*get_emoji_factory)(); 997d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project if (NULL == factory) { 1007d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project LOGE("Returned factory is NULL"); 1017d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project dlclose(handle); 1027d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project return; 1037d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 1047d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 1057d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project const char *name = factory->Name(); 1067d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 1077d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project size_t size = g_factories->size(); 1087d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project for (size_t i = 0; i < size; ++i) { 1097d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project EmojiFactory *f = g_factories->itemAt(i); 1107d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project if (!strcmp(name, f->Name())) { 1117d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project LOGE("Same EmojiFactory was found: %s", name); 1127d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project delete factory; 1137d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project dlclose(handle); 1147d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project return; 1157d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 1167d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 1177d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project g_factories->push(factory); 1187d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project // dlclose() must not be called here, since returned factory may point to 1197d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project // static data in the shared library (like "static const char* = "emoji";") 1207d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project g_handles->push(handle); 1217d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project} 1227d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 1237d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source ProjectEmojiFactoryManager::~EmojiFactoryManager() { 1247d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project if (g_factories != NULL) { 1257d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project size_t size = g_factories->size(); 1267d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project for (size_t i = 0; i < size; ++i) { 1277d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project delete g_factories->itemAt(i); 1287d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 1297d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project delete g_factories; 1307d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 1317d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 1327d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project if (g_handles != NULL) { 1337d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project size_t size = g_handles->size(); 1347d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project for (size_t i = 0; i < size; ++i) { 1357d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project dlclose(g_handles->itemAt(i)); 1367d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 1377d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project delete g_handles; 1387d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 1397d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project} 1407d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 1417d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Projectstatic EmojiFactoryManager g_registrar; 1427d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 1437d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Projectstatic void InitializeEmojiFactory() { 144e77fc97dc6438110fd5205db2b5c5b799014a0b9Daisuke Miyakawa g_registrar.Init(); 1457d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project} 1467d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 1477d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project/* static */ 1487d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source ProjectEmojiFactory *EmojiFactory::GetImplementation(const char *name) { 1497d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project pthread_once(&g_once, InitializeEmojiFactory); 1507d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project if (NULL == name) { 1517d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project return NULL; 1527d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 1537d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project size_t size = g_factories->size(); 1547d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project for (size_t i = 0; i < size; ++i) { 1557d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project EmojiFactory *factory = g_factories->itemAt(i); 1567d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project if (!strcmp(name, factory->Name())) { 1577d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project return factory; 1587d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 1597d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 1607d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project return NULL; 1617d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project} 1627d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 1637d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project/* static */ 1647d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source ProjectEmojiFactory *EmojiFactory::GetAvailableImplementation() { 1657d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project pthread_once(&g_once, InitializeEmojiFactory); 1667d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project size_t size = g_factories->size(); 1677d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project for (size_t i = 0; i < size; ++i) { 1687d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project EmojiFactory *factory = g_factories->itemAt(i); 1697d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project return factory; 1707d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project } 1717d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project return NULL; 1727d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project} 1737d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 1747d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project} // namespace android 1757d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 1767d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Projectextern "C" android::EmojiFactory *GetImplementation( 1777d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project const char *name) { 1787d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project return android::EmojiFactory::GetImplementation(name); 1797d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project} 1807d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project 1817d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Projectextern "C" android::EmojiFactory *GetAvailableImplementation() { 1827d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project return android::EmojiFactory::GetAvailableImplementation(); 1837d814fb9f0fd40667bb0338b7ca2cebfcc331dcThe Android Open Source Project} 184