summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeil Fuller <nfuller@google.com>2015-03-02 17:44:43 +0000
committerNeil Fuller <nfuller@google.com>2015-03-26 13:23:54 +0000
commit317d6e12782e069e4fde06ed0f9a976a7c49f580 (patch)
tree38d03e805aac04ac69fef321e83df035df4bd6d2
parentdb4499e1983c9649c8de7697d10825028fd8094d (diff)
downloadlibcore-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.java3
-rw-r--r--luni/src/main/native/libcore_icu_ICU.cpp80
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));
}