commit 6099f062f5d0e79586149d9a8963525a59f89557 Author: Makoto Kato Date: Fri Nov 22 16:51:30 2019 +0900 ICU-11992 uprv_tzname doesn't return valid time zone on Android # ICU bug report: # https://unicode-org.atlassian.net/browse/ICU-11992 # # Pull request: # https://github.com/unicode-org/icu/pull/605 # # Commit: # https://github.com/unicode-org/icu/commit/c9037ca8d3c0738f1a044dd845bdc0dc646f3e97.patch diff --git a/intl/icu/source/common/putil.cpp b/intl/icu/source/common/putil.cpp --- a/intl/icu/source/common/putil.cpp +++ b/intl/icu/source/common/putil.cpp @@ -116,15 +116,19 @@ # include # if U_PLATFORM == U_PF_SOLARIS # 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. * */ @@ -1041,13 +1045,57 @@ static char* searchForTZFile(const char* path, DefaultTZInfo* tzInfo) { } return result; } #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() { +#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 } @@ -1082,11 +1130,15 @@ uprv_tzname(int n) } #endif*/ /* 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. */ && uprv_strcmp(tzid, TZ_ENV_CHECK) != 0 #endif