From 7d814fb9f0fd40667bb0338b7ca2cebfcc331dcd Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 10 Mar 2009 16:20:55 -0700 Subject: auto import from //branches/cupcake/...@137197 --- Android.mk | 42 +++++++++++++ EmojiFactory.cpp | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ EmojiFactory.h | 100 ++++++++++++++++++++++++++++++ 3 files changed, 325 insertions(+) create mode 100644 Android.mk create mode 100644 EmojiFactory.cpp create mode 100644 EmojiFactory.h diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000..c5a4658 --- /dev/null +++ b/Android.mk @@ -0,0 +1,42 @@ +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := EmojiFactory.cpp + +LOCAL_MODULE := libemoji + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils + +ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true) +LOCAL_LDLIBS += -ldl +endif +ifneq ($(TARGET_SIMULATOR),true) +LOCAL_SHARED_LIBRARIES += libdl +endif + +LOCAL_CFLAGS += -Wall -Werror + +LOCAL_LDLIBS += -lpthread + +LOCAL_C_INCLUDES += \ + $(base)/include/utils + +LOCAL_PRELINK_MODULE := false + +include $(BUILD_SHARED_LIBRARY) diff --git a/EmojiFactory.cpp b/EmojiFactory.cpp new file mode 100644 index 0000000..b52a02b --- /dev/null +++ b/EmojiFactory.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "EmojiFactory.h" + +#define LOG_TAG "EmojiFactory" +#include +#include + +#include + +#include +#include +#include +#include + + +namespace android { + +static pthread_once_t g_once = PTHREAD_ONCE_INIT; +static Vector *g_factories = NULL; +static Vector *g_handles = NULL; + +class EmojiFactoryManager { + public: + void init(); + virtual ~EmojiFactoryManager(); + private: + void TryRegisterEmojiFactory(const char *library_name); +}; + +// Note: I previously did this procedure in the construcor. However, +// property_get() didn't return a correct value in that context. I guess +// property_get() does not return correct values before AndroidRuntime +// instance (or exactly, AppRuntime in instance app_main.cpp) is +// fully ready (see AndroidRunitem.cpp and app_main.cpp). +// So, instead of doing this in constructor, I decided this shoud be done +// when a user requires to EmojiFactory, which makes better sense to me. +void EmojiFactoryManager::init() { + g_handles = new Vector(); + g_factories = new Vector(); + + char *emoji_libraries = new char[PROPERTY_VALUE_MAX]; + int len = property_get("ro.config.libemoji", emoji_libraries, ""); + // LOGD("ro.config.libemoji: %s", emoji_libraries); + if (len > 0) { + char *saveptr, *ptr; + ptr = emoji_libraries; + while (true) { + ptr = strtok_r(ptr, ":", &saveptr); + if (NULL == ptr) { + break; + } + TryRegisterEmojiFactory(ptr); + ptr = NULL; + } + } + + delete [] emoji_libraries; +} + +void EmojiFactoryManager::TryRegisterEmojiFactory(const char *library_name) { + void *handle = dlopen(library_name, RTLD_LAZY | RTLD_LOCAL); + const char* error_str = dlerror(); + if (error_str) { + LOGE("Failed to load shared library %s: %s", library_name, error_str); + return; + } + EmojiFactory *(*get_emoji_factory)() = + reinterpret_cast(dlsym(handle, + "GetEmojiFactory")); + error_str = dlerror(); + if (error_str) { + LOGE("Failed to call GetEmojiFactory: %s", error_str); + dlclose(handle); + return; + } + + EmojiFactory *factory = (*get_emoji_factory)(); + if (NULL == factory) { + LOGE("Returned factory is NULL"); + dlclose(handle); + return; + } + + const char *name = factory->Name(); + + size_t size = g_factories->size(); + for (size_t i = 0; i < size; ++i) { + EmojiFactory *f = g_factories->itemAt(i); + if (!strcmp(name, f->Name())) { + LOGE("Same EmojiFactory was found: %s", name); + delete factory; + dlclose(handle); + return; + } + } + g_factories->push(factory); + // dlclose() must not be called here, since returned factory may point to + // static data in the shared library (like "static const char* = "emoji";") + g_handles->push(handle); + // LOGD("successufl: %s", library_name); // to delete +} + +EmojiFactoryManager::~EmojiFactoryManager() { + if (g_factories != NULL) { + size_t size = g_factories->size(); + for (size_t i = 0; i < size; ++i) { + delete g_factories->itemAt(i); + } + delete g_factories; + } + + if (g_handles != NULL) { + size_t size = g_handles->size(); + for (size_t i = 0; i < size; ++i) { + dlclose(g_handles->itemAt(i)); + } + delete g_handles; + } +} + +static EmojiFactoryManager g_registrar; + +static void InitializeEmojiFactory() { + g_registrar.init(); +} + +/* static */ +EmojiFactory *EmojiFactory::GetImplementation(const char *name) { + pthread_once(&g_once, InitializeEmojiFactory); + if (NULL == name) { + return NULL; + } + size_t size = g_factories->size(); + for (size_t i = 0; i < size; ++i) { + EmojiFactory *factory = g_factories->itemAt(i); + if (!strcmp(name, factory->Name())) { + return factory; + } + } + return NULL; +} + +/* static */ +EmojiFactory *EmojiFactory::GetAvailableImplementation() { + pthread_once(&g_once, InitializeEmojiFactory); + size_t size = g_factories->size(); + // LOGD("size: %d", size); // to delete + for (size_t i = 0; i < size; ++i) { + EmojiFactory *factory = g_factories->itemAt(i); + return factory; + } + return NULL; +} + +} // namespace android + +/* +// These ware for dlopen(). However, bionic libc does not allow dlopen() in +// dlopen() context. That means this library cannot be dlopen()-ed. +extern "C" android::EmojiFactory *GetImplementation( + const char *name) { + return android::EmojiFactory::GetImplementation(name); +} + +extern "C" android::EmojiFactory *GetAvailableImplementation() { + return android::EmojiFactory::GetAvailableImplementation(); +} +*/ diff --git a/EmojiFactory.h b/EmojiFactory.h new file mode 100644 index 0000000..1d3fa06 --- /dev/null +++ b/EmojiFactory.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_EMOJI_FACTORY_H +#define ANDROID_EMOJI_FACTORY_H + +namespace android { + +// Abstract class for EmojiFactory. +// +// Here, PUA (or Android PUA) means Unicode PUA defined for various emoji. The +// PUA supports emoji of DoCoMo, KDDI, Softbank and Goomoji. Each PUA defined +// by the other vendors (careers) are called Vendor Specific PUA (vsp). +// For more information, go +// http://unicode.org/~mdavis/08080r-emoji-proposal/ (tentative) +class EmojiFactory { + public: + virtual ~EmojiFactory() {} + // Returns binary image data corresponding to "pua". The size of binary is + // stored to "size". Returns NULL if there's no mapping from the "pua" to a + // specific image. Currently, image format is all (animated) gif. + // + // TODO(dmiyakawa): there should be a way to tell users the format of the + // binary. + virtual const char *GetImageBinaryFromAndroidPua(int pua, int *size) = 0; + + // Returns binary image data corresponding to "sjis", which is defined by + // each career. Returns NULL when there's no mapping for "sjis". + virtual const char *GetImageBinaryFromVendorSpecificSjis(unsigned short sjis, + int *size) { + return GetImageBinaryFromAndroidPua( + GetAndroidPuaFromVendorSpecificSjis(sjis), size); + } + + // Returns binary image data corresponding to Vendor-specific PUA "vsp". + // Returns NULL when there's no mapping for "vsp". + virtual const char *GetImageBinaryFromVendorSpecificPua(int vsp, + int *size) { + return GetImageBinaryFromAndroidPua( + GetAndroidPuaFromVendorSpecificPua(vsp), size); + } + + // Returns Android PUA corresponding to "sjis". Returns -1 when there's no + // mapping from "sjis" to a Android PUA. + virtual int GetAndroidPuaFromVendorSpecificSjis(unsigned short sjis) = 0; + + // Returns Vendor-specific Shift jis code corresponding to "pua". Returns -1 + // when ther's no mapping from "pua" to a specific sjis. + virtual int GetVendorSpecificSjisFromAndroidPua(int pua) = 0; + + // Returns maximum Vendor-Specific PUA. This is the last valid value. + virtual int GetMaximumVendorSpecificPua() = 0; + + // Returns minimum Vendor-Specific PUA. + virtual int GetMinimumVendorSpecificPua() = 0; + + // Returns maximum Android PUA. This the last valid value. + virtual int GetMaximumAndroidPua() = 0; + + // Returns minimum Android PUA. + virtual int GetMinimumAndroidPua() = 0; + + // Returns Android PUA corresponding to Vendor-Specific Unicode "vsp". Returns + // -1 when there's no mapping from "vsp" to a Android PUA. + virtual int GetAndroidPuaFromVendorSpecificPua(int vsp) = 0; + + // Returns Vendor-specific PUA corresponding to "pua". Returns -1 when + // there's no mapping from "pua" to a specific unicode. + virtual int GetVendorSpecificPuaFromAndroidPua(int pua) = 0; + + // Returns non NULL string which defines the name of this factory. + // e.g. "docomo", "goomoji" + virtual const char *Name() const = 0; + + // Get a specific implementation of EmojiFactory. If there's no implementation + // for "name", returns NULL. + static EmojiFactory *GetImplementation(const char *name); + + // Get an implementation of EmojiFactory. This assumes that, usually, there + // should be only one possible EmojiFactory implementation. If there are more + // than one implementations, most prefered one is returned. + static EmojiFactory *GetAvailableImplementation(); +}; + +} // namespace android + +#endif // ANDROID_EMOJI_FACTORY_H -- cgit v1.2.3