summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlmaz Mingaleev <mingaleev@google.com>2024-06-05 09:13:02 +0000
committerAlmaz Mingaleev <mingaleev@google.com>2024-06-05 16:20:08 +0100
commitb3fab5322586985e718fd4d597616f3b28ab6959 (patch)
treef4205c5520570c2d9c8a41e58cc4c890efcc1a23
parenta98bbf49a102b0a9fa5ba4f647e236684e586785 (diff)
downloadicu-b3fab5322586985e718fd4d597616f3b28ab6959.tar.gz
Revert^4 "Read files from versioned tzdata paths."
Reverts aosp/3112092. NO_IFTTT=Introducing linter checks. Test: verified on -next target on goog/main Test: see system/timezone Change-Id: I49787b41a9e771ff3fe331ba340eddcb64c5f279
-rw-r--r--android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/TimeZoneDataFiles.java17
-rw-r--r--android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/TzDataSetVersion.java14
-rw-r--r--android_icu4j/src/main/java/android/icu/platform/AndroidDataFiles.java25
-rw-r--r--android_icu4j/testing/src/android/icu/extratest/platform/AndroidDataFilesTest.java24
-rw-r--r--android_icu4j/testing/src/com/android/i18n/test/timezone/TimeZoneDataFilesTest.java14
-rw-r--r--android_icu4j/testing/src/com/android/i18n/test/timezone/TzDataSetVersionTest.java25
-rw-r--r--libandroidicuinit/IcuRegistration.cpp32
-rw-r--r--libandroidicuinit/IcuRegistration.h5
8 files changed, 133 insertions, 23 deletions
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/TimeZoneDataFiles.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/TimeZoneDataFiles.java
index 6f3b16eac..2ffdef015 100644
--- a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/TimeZoneDataFiles.java
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/TimeZoneDataFiles.java
@@ -39,14 +39,27 @@ public final class TimeZoneDataFiles {
* Returns time zone file paths for the specified file name in an array in the order they
* should be tried. See {@link AndroidDataFiles#generateIcuDataPath()} for ICU files instead.
* <ul>
- * <li>[0] - the location of the file from the time zone module under /apex (must exist).</li>
+ * <li>[0] - the location of the versioned file from the time zone module under /apex
+ * (must exist).</li>
+ * <li>[1] - old, unversioned location of the file from the time zone module under /apex. Will
+ * be removed once prebuilts are updated.</>
* </ul>
*/
// VisibleForTesting
public static String[] getTimeZoneFilePaths(String fileName) {
- return new String[] { getTimeZoneModuleTzFile(fileName) };
+ return new String[] {
+ // TODO(b/319103072) There should be only versioned path.
+ getTimeZoneModuleTzFile(fileName),
+ getVersionedTimeZoneModuleTzFile(fileName) };
}
+ // TODO(b/319103072) This should be removed once prebuilts are updated.
+ public static String getVersionedTimeZoneModuleTzFile(String fileName) {
+ return getTimeZoneModuleFile("tz/versioned/"
+ + TzDataSetVersion.currentFormatMajorVersion() + "/" + fileName);
+ }
+
+ // TODO(b/319103072) This method should read from versioned directory.
public static String getTimeZoneModuleTzFile(String fileName) {
return getTimeZoneModuleFile("tz/" + fileName);
}
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/TzDataSetVersion.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/TzDataSetVersion.java
index c91745cbd..e3dd27581 100644
--- a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/TzDataSetVersion.java
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/TzDataSetVersion.java
@@ -61,7 +61,9 @@ public final class TzDataSetVersion {
* version to 1 when doing so.
*/
// @VisibleForTesting : Keep this inline-able: it is used from CTS tests.
+ // LINT.IfChange
public static final int CURRENT_FORMAT_MAJOR_VERSION = 8; // Android V
+ // LINT.ThenChange(external/icu/android_icu4j/src/main/java/android/icu/platform/AndroidDataFiles.java)
/**
* Returns the major tz data format version supported by this device.
@@ -86,12 +88,9 @@ public final class TzDataSetVersion {
return CURRENT_FORMAT_MINOR_VERSION;
}
- /** The full major + minor tz data format version for this device. */
- private static final String FULL_CURRENT_FORMAT_VERSION_STRING =
- toFormatVersionString(CURRENT_FORMAT_MAJOR_VERSION, CURRENT_FORMAT_MINOR_VERSION);
-
- private static final int FORMAT_VERSION_STRING_LENGTH =
- FULL_CURRENT_FORMAT_VERSION_STRING.length();
+ /** The full major + minor tz data format version's length for this device. */
+ // @VisibleForTesting
+ public static final int FORMAT_VERSION_STRING_LENGTH = 7;
private static final Pattern FORMAT_VERSION_PATTERN = Pattern.compile("(\\d{3})\\.(\\d{3})");
/** A pattern that matches the IANA rules value of a rules update. e.g. "2016g" */
@@ -287,7 +286,8 @@ public final class TzDataSetVersion {
return value;
}
- private static String toFormatVersionString(int majorFormatVersion, int minorFormatVersion) {
+ // @VisibleForTesting
+ public static String toFormatVersionString(int majorFormatVersion, int minorFormatVersion) {
return to3DigitVersionString(majorFormatVersion)
+ "." + to3DigitVersionString(minorFormatVersion);
}
diff --git a/android_icu4j/src/main/java/android/icu/platform/AndroidDataFiles.java b/android_icu4j/src/main/java/android/icu/platform/AndroidDataFiles.java
index 74ab82fc3..121197863 100644
--- a/android_icu4j/src/main/java/android/icu/platform/AndroidDataFiles.java
+++ b/android_icu4j/src/main/java/android/icu/platform/AndroidDataFiles.java
@@ -38,8 +38,19 @@ public class AndroidDataFiles {
public static final String ANDROID_I18N_ROOT_ENV = "ANDROID_I18N_ROOT";
public static final String ANDROID_TZDATA_ROOT_ENV = "ANDROID_TZDATA_ROOT";
+ /**
+ * This is identical to
+ * {@link com.android.i18n.timezone.TzDataSetVersion#CURRENT_FORMAT_MAJOR_VERSION}, but because
+ * dependency is in the opposite direction we can't refer to that field from this class.
+ * TzDataSetVersionTest ensures that their values are the same.
+ */
+ // VisibleForTesting
+ // LINT.IfChange
+ public static final int CURRENT_MAJOR_VERSION = 8;
+ // LINT.ThenChange(external/icu/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/TzDataSetVersion.java)
+
// VisibleForTesting
- public static String getTimeZoneModuleIcuFile(String fileName) {
+ public static String getTimeZoneModuleIcuFileAtOldLocation(String fileName) {
return getTimeZoneModuleFile("icu/" + fileName);
}
@@ -47,6 +58,10 @@ public class AndroidDataFiles {
return System.getenv(ANDROID_TZDATA_ROOT_ENV) + "/etc/" + fileName;
}
+ private static String getTimeZoneModuleIcuFile(String fileName) {
+ return getTimeZoneModuleFile("tz/versioned/" + CURRENT_MAJOR_VERSION + "/icu/" + fileName);
+ }
+
// VisibleForTesting
public static String getI18nModuleIcuFile(String fileName) {
return getI18nModuleFile("icu/" + fileName);
@@ -64,7 +79,13 @@ public class AndroidDataFiles {
// ICU should look for a mounted time zone module file in /apex. This is used for
// (optional) time zone data that can be updated with an APEX file.
- String timeZoneModuleIcuDataPath = getTimeZoneModuleIcuFile("");
+ paths.add(getTimeZoneModuleIcuFile(""));
+
+ // TODO (b/319103072): remove this path once prebuilts are updated.
+ // Starting from V content of the tzdata module is versioned so it can be used across
+ // multiple Android releases. timeZoneModuleIcuDataPath will be removed once all prebuilts
+ // are updated. Production tzdata6 won't have ICU files under etc/icu.
+ String timeZoneModuleIcuDataPath = getTimeZoneModuleIcuFileAtOldLocation("");
paths.add(timeZoneModuleIcuDataPath);
// ICU should always look in the i18n module path as this is where most of the data
diff --git a/android_icu4j/testing/src/android/icu/extratest/platform/AndroidDataFilesTest.java b/android_icu4j/testing/src/android/icu/extratest/platform/AndroidDataFilesTest.java
index 190fb3d1b..f91fbcac1 100644
--- a/android_icu4j/testing/src/android/icu/extratest/platform/AndroidDataFilesTest.java
+++ b/android_icu4j/testing/src/android/icu/extratest/platform/AndroidDataFilesTest.java
@@ -48,11 +48,21 @@ import java.util.stream.Stream;
public class AndroidDataFilesTest {
private static final Set<String> TZDATA_RES_FILES =
- Set.of(
+ Stream.of(
+ "/apex/com.android.tzdata/etc/tz/versioned/%d/icu/metaZones.res",
+ "/apex/com.android.tzdata/etc/tz/versioned/%d/icu/windowsZones.res",
+ "/apex/com.android.tzdata/etc/tz/versioned/%d/icu/zoneinfo64.res",
+ "/apex/com.android.tzdata/etc/tz/versioned/%d/icu/timezoneTypes.res")
+ .map(path -> path.formatted(AndroidDataFiles.CURRENT_MAJOR_VERSION))
+ .collect(toSet());
+
+ private static final Set<String> TZDATA_RES_FILES_AT_OLD_LOCATION =
+ Stream.of(
"/apex/com.android.tzdata/etc/icu/metaZones.res",
"/apex/com.android.tzdata/etc/icu/windowsZones.res",
"/apex/com.android.tzdata/etc/icu/zoneinfo64.res",
- "/apex/com.android.tzdata/etc/icu/timezoneTypes.res");
+ "/apex/com.android.tzdata/etc/icu/timezoneTypes.res")
+ .collect(toSet());
private static final String ICU_DAT_PATH =
"/apex/com.android.i18n/etc/icu/icudt" + VersionInfo.ICU_VERSION.getMajor() + "l.dat";
@@ -80,12 +90,16 @@ public class AndroidDataFilesTest {
.map(f -> f.getPath())
.collect(toSet());
- for (String resFile : TZDATA_RES_FILES) {
- assertContains(icuFiles, resFile);
- }
+ assertTrue(containsAllResFiles(icuFiles));
+
assertContains(icuFiles, ICU_DAT_PATH);
}
+ private static boolean containsAllResFiles(Set<String> existingFiles) {
+ return existingFiles.containsAll(TZDATA_RES_FILES)
+ || existingFiles.containsAll(TZDATA_RES_FILES_AT_OLD_LOCATION);
+ }
+
private static boolean isIcuFile(File file) {
return file.getName().endsWith(".res") || file.getName().endsWith(".dat");
}
diff --git a/android_icu4j/testing/src/com/android/i18n/test/timezone/TimeZoneDataFilesTest.java b/android_icu4j/testing/src/com/android/i18n/test/timezone/TimeZoneDataFilesTest.java
index 064c7bbe0..3b5aff459 100644
--- a/android_icu4j/testing/src/com/android/i18n/test/timezone/TimeZoneDataFilesTest.java
+++ b/android_icu4j/testing/src/com/android/i18n/test/timezone/TimeZoneDataFilesTest.java
@@ -41,7 +41,7 @@ public class TimeZoneDataFilesTest {
@Test
public void getTimeZoneFilePaths() {
String[] paths = TimeZoneDataFiles.getTimeZoneFilePaths("foo");
- assertEquals(1, paths.length);
+ assertEquals(2, paths.length);
assertTrue(paths[0].startsWith(System.getenv(ANDROID_TZDATA_ROOT_ENV)));
assertTrue(paths[0].endsWith("/foo"));
@@ -53,13 +53,19 @@ public class TimeZoneDataFilesTest {
String icuDataPath = AndroidDataFiles.generateIcuDataPath();
String[] paths = icuDataPath.split(":");
- assertEquals(2, paths.length);
+ assertEquals(3, paths.length);
+
+ String versionedTzdataModulePath = paths[0];
+ assertTrue(versionedTzdataModulePath + " invalid",
+ versionedTzdataModulePath.startsWith(System.getenv(ANDROID_TZDATA_ROOT_ENV)));
+ assertTrue(versionedTzdataModulePath + " should be versioned",
+ versionedTzdataModulePath.contains("versioned"));
- String tzdataModulePath = paths[0];
+ String tzdataModulePath = paths[1];
assertTrue(tzdataModulePath + " invalid",
tzdataModulePath.startsWith(System.getenv(ANDROID_TZDATA_ROOT_ENV)));
- String runtimeModulePath = paths[1];
+ String runtimeModulePath = paths[2];
assertTrue(runtimeModulePath + " invalid",
runtimeModulePath.startsWith(System.getenv(ANDROID_I18N_ROOT_ENV)));
assertTrue(runtimeModulePath + " invalid", runtimeModulePath.contains("/etc/icu"));
diff --git a/android_icu4j/testing/src/com/android/i18n/test/timezone/TzDataSetVersionTest.java b/android_icu4j/testing/src/com/android/i18n/test/timezone/TzDataSetVersionTest.java
index fdf7294bf..937ad5c12 100644
--- a/android_icu4j/testing/src/com/android/i18n/test/timezone/TzDataSetVersionTest.java
+++ b/android_icu4j/testing/src/com/android/i18n/test/timezone/TzDataSetVersionTest.java
@@ -16,12 +16,24 @@
package com.android.i18n.test.timezone;
+import static com.android.i18n.timezone.TzDataSetVersion.CURRENT_FORMAT_MAJOR_VERSION;
+import static com.android.i18n.timezone.TzDataSetVersion.CURRENT_FORMAT_MINOR_VERSION;
+import static com.android.i18n.timezone.TzDataSetVersion.FORMAT_VERSION_STRING_LENGTH;
+import static com.android.i18n.timezone.TzDataSetVersion.toFormatVersionString;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import android.icu.platform.AndroidDataFiles;
import android.icu.testsharding.MainTestShard;
-import junit.framework.TestCase;
import com.android.i18n.timezone.TzDataSetVersion;
import com.android.i18n.timezone.TzDataSetVersion.TzDataSetException;
+import junit.framework.TestCase;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+
@MainTestShard
public class TzDataSetVersionTest extends TestCase {
@@ -100,6 +112,17 @@ public class TzDataSetVersionTest extends TestCase {
assertFalse(TzDataSetVersion.isCompatibleWithThisDevice(olderMinor));
}
+ public void testConsistency() {
+ String msg = "Major versions in TzDataSetVersion and AndroidDataFiles differ";
+ assertEquals(msg, CURRENT_FORMAT_MAJOR_VERSION, AndroidDataFiles.CURRENT_MAJOR_VERSION);
+ }
+
+ public void testFormatLength() {
+ String formatVersion = toFormatVersionString(CURRENT_FORMAT_MAJOR_VERSION,
+ CURRENT_FORMAT_MINOR_VERSION);
+ assertEquals(FORMAT_VERSION_STRING_LENGTH, formatVersion.length());
+ }
+
private TzDataSetVersion createTzDataSetVersion(int majorFormatVersion, int minorFormatVersion)
throws TzDataSetException {
return new TzDataSetVersion(majorFormatVersion, minorFormatVersion, VALID_RULES_VERSION, 3);
diff --git a/libandroidicuinit/IcuRegistration.cpp b/libandroidicuinit/IcuRegistration.cpp
index 63397fd20..752527418 100644
--- a/libandroidicuinit/IcuRegistration.cpp
+++ b/libandroidicuinit/IcuRegistration.cpp
@@ -216,8 +216,9 @@ IcuRegistration::IcuRegistration() {
// If it does, map it so we use its data in preference to later ones.
// However, I18N apex is not expected to have the time zone data resources.
// http://b/171542040
- std::string tzModulePath = getTimeZoneModulePath();
+ std::string tzModulePath = getPreVTimeZoneModulePath();
std::string tzIcuDataPath = tzModulePath + "icu_tzdata.dat";
+ std::string versionedTzIcuDataPath = getTimeZoneModulePath();
if (pathExists(tzIcuDataPath)) {
AICU_LOGD("Time zone APEX ICU file found: %s", tzIcuDataPath.c_str());
icu_datamap_from_tz_module_ = impl::IcuDataMap::Create(tzIcuDataPath);
@@ -225,6 +226,15 @@ IcuRegistration::IcuRegistration() {
AICU_LOGW("TZ module .dat file %s exists but could not be loaded. Skipping.",
tzIcuDataPath.c_str());
}
+ } else if (pathExists(versionedTzIcuDataPath)) {
+ UErrorCode status = U_ZERO_ERROR;
+ u_setTimeZoneFilesDirectory(versionedTzIcuDataPath.c_str(), &status);
+ if (U_SUCCESS(status)) {
+ AICU_LOGD("u_setTimeZoneFilesDirectory(\"%s\") succeeded. ", versionedTzIcuDataPath.c_str());
+ } else {
+ AICU_LOGE("u_setTimeZoneFilesDirectory(\"%s\") failed: %s",
+ versionedTzIcuDataPath.c_str(), u_errorName(status));
+ }
} else {
UErrorCode status = U_ZERO_ERROR;
u_setTimeZoneFilesDirectory(tzModulePath.c_str(), &status);
@@ -261,7 +271,7 @@ bool IcuRegistration::pathExists(const std::string& path) {
// Returns a string containing the expected path of the /apex tz
// module ICU data directory
-std::string IcuRegistration::getTimeZoneModulePath() {
+std::string IcuRegistration::getPreVTimeZoneModulePath() {
const char* tzdataModulePathPrefix = getenv("ANDROID_TZDATA_ROOT");
if (tzdataModulePathPrefix == NULL) {
AICU_LOGE("ANDROID_TZDATA_ROOT environment variable not set");
@@ -274,6 +284,24 @@ std::string IcuRegistration::getTimeZoneModulePath() {
return tzdataModulePath;
}
+// Identical to TzDataSetVersion#CURRENT_MAJOR_FORMAT_VERSION.
+// LINT.IfChange
+static const std::string CURRENT_MAJOR_FORMAT_VERSION = "8";
+// LINT.ThenChange(external/icu/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/TzDataSetVersion.java)
+
+std::string IcuRegistration::getTimeZoneModulePath() {
+ const char* tzdataModulePathPrefix = getenv("ANDROID_TZDATA_ROOT");
+ if (tzdataModulePathPrefix == NULL) {
+ AICU_LOGE("ANDROID_TZDATA_ROOT environment variable not set");
+ abort();
+ }
+
+ std::string tzdataModulePath;
+ tzdataModulePath = tzdataModulePathPrefix;
+ tzdataModulePath += "/etc/tz/versioned/" + CURRENT_MAJOR_FORMAT_VERSION + "/icu";
+ return tzdataModulePath;
+}
+
std::string IcuRegistration::getI18nModulePath() {
const char* i18nModulePathPrefix = getenv("ANDROID_I18N_ROOT");
if (i18nModulePathPrefix == NULL) {
diff --git a/libandroidicuinit/IcuRegistration.h b/libandroidicuinit/IcuRegistration.h
index e968dbdd6..b9065daed 100644
--- a/libandroidicuinit/IcuRegistration.h
+++ b/libandroidicuinit/IcuRegistration.h
@@ -127,6 +127,11 @@ class IcuRegistration final {
IcuRegistration();
static bool pathExists(const std::string& path);
+ // TODO (b/319103072): remove this method once prebuilts are updated.
+ // Production tzdata6 will have versioned files only. Keeping this method while there are
+ // prebuilts which have ICU file(s) under /etc/icu and not /etc/tz/versioned/*/icu directory in
+ // the tzdata APEX.
+ static std::string getPreVTimeZoneModulePath();
static std::string getTimeZoneModulePath();
static std::string getI18nModulePath();