diff options
author | Neil Fuller <nfuller@google.com> | 2015-03-02 17:44:43 +0000 |
---|---|---|
committer | Neil Fuller <nfuller@google.com> | 2015-03-26 13:23:54 +0000 |
commit | 317d6e12782e069e4fde06ed0f9a976a7c49f580 (patch) | |
tree | 38d03e805aac04ac69fef321e83df035df4bd6d2 | |
parent | db4499e1983c9649c8de7697d10825028fd8094d (diff) | |
download | libcore-317d6e12782e069e4fde06ed0f9a976a7c49f580.zip libcore-317d6e12782e069e4fde06ed0f9a976a7c49f580.tar.gz libcore-317d6e12782e069e4fde06ed0f9a976a7c49f580.tar.bz2 |
Changes to enable timezone data overrides for ICU and libcore
Bug: 19941636
Change-Id: Id587be99f645978c2e1067c9f8eef26d6d63ec27
-rw-r--r-- | luni/src/main/java/libcore/util/ZoneInfoDB.java | 3 | ||||
-rw-r--r-- | luni/src/main/native/libcore_icu_ICU.cpp | 80 |
2 files changed, 64 insertions, 19 deletions
diff --git a/luni/src/main/java/libcore/util/ZoneInfoDB.java b/luni/src/main/java/libcore/util/ZoneInfoDB.java index 906ec14..b8e1dad 100644 --- a/luni/src/main/java/libcore/util/ZoneInfoDB.java +++ b/luni/src/main/java/libcore/util/ZoneInfoDB.java @@ -41,7 +41,8 @@ import libcore.io.MemoryMappedFile; */ public final class ZoneInfoDB { private static final TzData DATA = - new TzData(System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo/tzdata"); + new TzData(System.getenv("ANDROID_DATA") + "/misc/zoneinfo/current/tzdata", + System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo/tzdata"); public static class TzData { /** diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp index 34b8ee0..221d1b3 100644 --- a/luni/src/main/native/libcore_icu_ICU.cpp +++ b/luni/src/main/native/libcore_icu_ICU.cpp @@ -804,22 +804,18 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(ICU, toLowerCase, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), NATIVE_METHOD(ICU, toUpperCase, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"), }; -void register_libcore_icu_ICU(JNIEnv* env) { - std::string path; - path = u_getDataDirectory(); - path += "/"; - path += U_ICUDATA_NAME; - path += ".dat"; - - #define FAIL_WITH_STRERROR(s) \ - ALOGE("Couldn't " s " '%s': %s", path.c_str(), strerror(errno)); \ - abort(); - #define MAYBE_FAIL_WITH_ICU_ERROR(s) \ - if (status != U_ZERO_ERROR) {\ - ALOGE("Couldn't initialize ICU (" s "): %s (%s)", u_errorName(status), path.c_str()); \ - abort(); \ - } +#define FAIL_WITH_STRERROR(s) \ + ALOGE("Couldn't " s " '%s': %s", path.c_str(), strerror(errno)); \ + return FALSE; + +#define MAYBE_FAIL_WITH_ICU_ERROR(s) \ + if (status != U_ZERO_ERROR) {\ + ALOGE("Couldn't initialize ICU (" s "): %s (%s)", u_errorName(status), path.c_str()); \ + return FALSE; \ + } + +static bool mapIcuData(const std::string& path) { // Open the file and get its length. ScopedFd fd(open(path.c_str(), O_RDONLY)); if (fd.get() == -1) { @@ -841,18 +837,66 @@ void register_libcore_icu_ICU(JNIEnv* env) { FAIL_WITH_STRERROR("madvise(MADV_RANDOM)"); } - // Tell ICU to use our memory-mapped data. UErrorCode status = U_ZERO_ERROR; + + // Tell ICU to use our memory-mapped data. udata_setCommonData(data, &status); MAYBE_FAIL_WITH_ICU_ERROR("udata_setCommonData"); + + return TRUE; +} + +void register_libcore_icu_ICU(JNIEnv* env) { + // Check the timezone override file exists. If it does, map it first so we use it in preference + // to the one that shipped with the device. + const char* dataPathPrefix = getenv("ANDROID_DATA"); + if (dataPathPrefix == NULL) { + ALOGE("ANDROID_DATA environment variable not set"); \ + abort(); + } + + UErrorCode status = U_ZERO_ERROR; // Tell ICU it can *only* use our memory-mapped data. udata_setFileAccess(UDATA_NO_FILES, &status); - MAYBE_FAIL_WITH_ICU_ERROR("udata_setFileAccess"); + if (status != U_ZERO_ERROR) { + ALOGE("Couldn't initialize ICU (s_setFileAccess): %s", u_errorName(status)); + abort(); + } + + // Map in optional TZ data files. + std::string dataPath; + dataPath = dataPathPrefix; + dataPath += "/misc/zoneinfo/current/icu/icu_tzdata.dat"; + + struct stat sb; + if (stat(dataPath.c_str(), &sb) == 0) { + ALOGD("Timezone override file found: %s", dataPath.c_str()); + if (!mapIcuData(dataPath)) { + ALOGW("TZ override file %s exists but could not be loaded. Skipping.", dataPath.c_str()); + } + } else { + ALOGD("No timezone override file found: %s", dataPath.c_str()); + } + + // Use the ICU data files that shipped with the device for everything else. + std::string systemPath; + systemPath = u_getDataDirectory(); + systemPath += "/"; + systemPath += U_ICUDATA_NAME; + systemPath += ".dat"; + + if (!mapIcuData(systemPath)) { + abort(); + } // Failures to find the ICU data tend to be somewhat obscure because ICU loads its data on first // use, which can be anywhere. Force initialization up front so we can report a nice clear error // and bail. u_init(&status); - MAYBE_FAIL_WITH_ICU_ERROR("u_init"); + if (status != U_ZERO_ERROR) {\ + ALOGE("Couldn't initialize ICU (u_init): %s", u_errorName(status)); + abort(); + } + jniRegisterNativeMethods(env, "libcore/icu/ICU", gMethods, NELEM(gMethods)); } |