summaryrefslogtreecommitdiffstats
path: root/luni/src/main/native
diff options
context:
space:
mode:
authorNeil Fuller <nfuller@google.com>2015-04-07 12:54:40 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-04-07 12:54:41 +0000
commit345d118df6eef599a1ad0ea18022ad1f74633f10 (patch)
tree9c43cd67897f7354fc9d416b0d522a5fbf6d47e7 /luni/src/main/native
parente25881196b4cb5f056619bf2883b10bb861dd704 (diff)
parent317d6e12782e069e4fde06ed0f9a976a7c49f580 (diff)
downloadlibcore-345d118df6eef599a1ad0ea18022ad1f74633f10.zip
libcore-345d118df6eef599a1ad0ea18022ad1f74633f10.tar.gz
libcore-345d118df6eef599a1ad0ea18022ad1f74633f10.tar.bz2
Merge "Changes to enable timezone data overrides for ICU and libcore"
Diffstat (limited to 'luni/src/main/native')
-rw-r--r--luni/src/main/native/libcore_icu_ICU.cpp80
1 files changed, 62 insertions, 18 deletions
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index ff76a16..0e744b7 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -815,22 +815,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) {
@@ -852,18 +848,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));
}