From c9037ca8d3c0738f1a044dd845bdc0dc646f3e97 Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Fri, 22 Nov 2019 16:51:30 +0900 Subject: [PATCH] ICU-11992 uprv_tzname doesn't return valid time zone on Android --- icu4c/source/common/putil.cpp | 52 +++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/icu4c/source/common/putil.cpp b/icu4c/source/common/putil.cpp index 905402c8385..40232fc2c12 100644 --- a/icu4c/source/common/putil.cpp +++ b/icu4c/source/common/putil.cpp @@ -118,11 +118,15 @@ # ifndef _XPG4_2 # define _XPG4_2 # endif +# elif U_PLATFORM == U_PF_ANDROID +# include +# include # endif #elif U_PLATFORM == U_PF_QNX # include #endif + /* * Only include langinfo.h if we have a way to get the codeset. If we later * depend on more feature, we can test on U_HAVE_NL_LANGINFO. @@ -1043,9 +1047,53 @@ static char* searchForTZFile(const char* path, DefaultTZInfo* tzInfo) { } #endif +#if U_PLATFORM == U_PF_ANDROID +typedef int(system_property_read_callback)(const prop_info* info, + void (*callback)(void* cookie, + const char* name, + const char* value, + uint32_t serial), + void* cookie); +typedef int(system_property_get)(const char*, char*); + +static char gAndroidTimeZone[PROP_VALUE_MAX] = { '\0' }; + +static void u_property_read(void* cookie, const char* name, const char* value, + uint32_t serial) { + uprv_strcpy((char* )cookie, value); +} +#endif + U_CAPI void U_EXPORT2 uprv_tzname_clear_cache(void) { +#if U_PLATFORM == U_PF_ANDROID + /* Android's timezone is stored in system property. */ + gAndroidTimeZone[0] = '\0'; + void* libc = dlopen("libc.so", RTLD_NOLOAD); + if (libc) { + /* Android API 26+ has new API to get system property and old API + * (__system_property_get) is deprecated */ + system_property_read_callback* property_read_callback = + (system_property_read_callback*)dlsym( + libc, "__system_property_read_callback"); + if (property_read_callback) { + const prop_info* info = + __system_property_find("persist.sys.timezone"); + if (info) { + property_read_callback(info, &u_property_read, gAndroidTimeZone); + } + } else { + system_property_get* property_get = + (system_property_get*)dlsym(libc, "__system_property_get"); + if (property_get) { + property_get("persist.sys.timezone", gAndroidTimeZone); + } + } + dlclose(libc); + } +#endif + #if defined(CHECK_LOCALTIME_LINK) && !defined(DEBUG_SKIP_LOCALTIME_LINK) gTimeZoneBufferPtr = NULL; #endif @@ -1084,7 +1132,11 @@ uprv_tzname(int n) /* This code can be temporarily disabled to test tzname resolution later on. */ #ifndef DEBUG_TZNAME +#if U_PLATFORM == U_PF_ANDROID + tzid = gAndroidTimeZone; +#else tzid = getenv("TZ"); +#endif if (tzid != NULL && isValidOlsonID(tzid) #if U_PLATFORM == U_PF_SOLARIS /* When TZ equals localtime on Solaris, check the /etc/localtime file. */