Move libcore.timezone classes to I18n module
Note that this CL does not miminize @IntraCoreApi surface.
Bug: 141747409
Test: atest CtsLibcoreOjTestCases CtsLibcoreTestCases CtsIcuTestCases
Merged-In: I8da8fe64c3ecf94f5de3e597dd98cdbd5c1eecf5
Change-Id: I8da8fe64c3ecf94f5de3e597dd98cdbd5c1eecf5
diff --git a/android_icu4j/Android.bp b/android_icu4j/Android.bp
index 5f40abe..6749993 100644
--- a/android_icu4j/Android.bp
+++ b/android_icu4j/Android.bp
@@ -50,6 +50,18 @@
path: "libcore_bridge/src/java",
}
+// timezone-related source that is also used in host tests / tools and its
+// dependencies.
+filegroup {
+ name: "timezone_host_files",
+ srcs: [
+ "libcore_bridge/src/java/com/android/i18n/timezone/TimeZoneDataFiles.java",
+ "libcore_bridge/src/java/com/android/i18n/timezone/TzDataSetVersion.java",
+ ],
+ path: "libcore_bridge/src/java",
+ visibility: ["//libcore"],
+}
+
// core-repackaged-icu4j contains only the repackaged ICU4J that does not
// use any internal or android specific code. If it ever did then it could depend on
// art-module-intra-core-api-stubs-system-modules (a superset) instead.
@@ -94,6 +106,7 @@
permitted_packages: [
"android.icu",
"com.android.icu",
+ "com.android.i18n.timezone",
],
installable: true,
hostdex: false,
@@ -309,6 +322,7 @@
static_libs: [
"junit",
"junit-params",
+ "tzdata-testing",
],
patch_module: "java.base",
diff --git a/android_icu4j/api/intra/current.txt b/android_icu4j/api/intra/current.txt
index 850884b..7c43c6d 100644
--- a/android_icu4j/api/intra/current.txt
+++ b/android_icu4j/api/intra/current.txt
@@ -188,6 +188,44 @@
}
+package com.android.i18n.timezone {
+
+ public final class TimeZoneDataFiles {
+ method public static String generateIcuDataPath();
+ method public static String getSystemTzFile(String);
+ method public static String[] getTimeZoneFilePaths(String);
+ method public static String getTimeZoneModuleTzFile(String);
+ }
+
+ public final class ZoneInfoData implements java.lang.Cloneable {
+ ctor public ZoneInfoData(com.android.i18n.timezone.ZoneInfoData);
+ method public static com.android.i18n.timezone.ZoneInfoData createFromSerializationFields(String, java.io.ObjectInputStream.GetField) throws java.io.IOException;
+ method public static com.android.i18n.timezone.ZoneInfoData createZoneInfo(String, long, java.nio.ByteBuffer) throws java.io.IOException;
+ method public int getDSTSavings();
+ method public String getID();
+ method public int getOffset(int, int, int, int, int, int);
+ method public int getOffset(long);
+ method public int getOffsetsByUtcTime(long, int[]);
+ method public int getRawOffset();
+ method public long[] getTransitionsForAppCompat();
+ method public boolean hasSameRules(com.android.i18n.timezone.ZoneInfoData);
+ method public boolean inDaylightTime(java.util.Date);
+ method public void setRawOffset(int);
+ method public boolean useDaylightTime();
+ method public void writeToSerializationFields(java.io.ObjectOutputStream.PutField);
+ field public static final java.io.ObjectStreamField[] ZONEINFO_SERIALIZED_FIELDS;
+ }
+
+ public final class ZoneInfoDb implements java.lang.AutoCloseable {
+ method public String[] getAvailableIDs();
+ method public String[] getAvailableIDs(int);
+ method public static com.android.i18n.timezone.ZoneInfoDb getInstance();
+ method public String getVersion();
+ method public com.android.i18n.timezone.ZoneInfoData makeZoneInfoData(String);
+ }
+
+}
+
package com.android.icu.charset {
public final class CharsetICU extends java.nio.charset.Charset {
diff --git a/android_icu4j/api/legacy_platform/current.txt b/android_icu4j/api/legacy_platform/current.txt
index 41e67f5..25f801e 100644
--- a/android_icu4j/api/legacy_platform/current.txt
+++ b/android_icu4j/api/legacy_platform/current.txt
@@ -50,6 +50,92 @@
}
+package com.android.i18n.timezone {
+
+ public class DebugInfo {
+ ctor public DebugInfo();
+ method public com.android.i18n.timezone.DebugInfo addStringEntry(String, String);
+ method public com.android.i18n.timezone.DebugInfo addStringEntry(String, int);
+ method public java.util.List<com.android.i18n.timezone.DebugInfo.DebugEntry> getDebugEntries();
+ }
+
+ public static class DebugInfo.DebugEntry {
+ ctor public DebugInfo.DebugEntry(String, String);
+ method public String getKey();
+ method public String getStringValue();
+ }
+
+ public class I18nModuleDebug {
+ method public static com.android.i18n.timezone.DebugInfo getDebugInfo();
+ }
+
+ public final class TimeZoneDataFiles {
+ method public static String getDataTimeZoneFile(String);
+ method public static String getDataTimeZoneRootDir();
+ method public static String getTimeZoneModuleTzVersionFile();
+ }
+
+ public final class TzDataSetVersion {
+ ctor public TzDataSetVersion(int, int, String, int) throws com.android.i18n.timezone.TzDataSetVersion.TzDataSetException;
+ method public static int currentFormatMajorVersion();
+ method public static int currentFormatMinorVersion();
+ method public int getFormatMajorVersion();
+ method public int getFormatMinorVersion();
+ method public int getRevision();
+ method public String getRulesVersion();
+ method public static boolean isCompatibleWithThisDevice(com.android.i18n.timezone.TzDataSetVersion);
+ method public static com.android.i18n.timezone.TzDataSetVersion readFromFile(java.io.File) throws java.io.IOException, com.android.i18n.timezone.TzDataSetVersion.TzDataSetException;
+ method public static com.android.i18n.timezone.TzDataSetVersion readTimeZoneModuleVersion() throws java.io.IOException, com.android.i18n.timezone.TzDataSetVersion.TzDataSetException;
+ method public byte[] toBytes();
+ field public static final String DEFAULT_FILE_NAME = "tz_version";
+ }
+
+ public static class TzDataSetVersion.TzDataSetException extends java.lang.Exception {
+ ctor public TzDataSetVersion.TzDataSetException(String);
+ ctor public TzDataSetVersion.TzDataSetException(String, Throwable);
+ }
+
+ public final class ZoneInfoData implements java.lang.Cloneable {
+ method public String getID();
+ }
+
+ public static class ZoneInfoData.WallTime {
+ ctor public ZoneInfoData.WallTime();
+ method public int getGmtOffset();
+ method public int getHour();
+ method public int getIsDst();
+ method public int getMinute();
+ method public int getMonth();
+ method public int getMonthDay();
+ method public int getSecond();
+ method public int getWeekDay();
+ method public int getYear();
+ method public int getYearDay();
+ method public void localtime(int, com.android.i18n.timezone.ZoneInfoData);
+ method public int mktime(com.android.i18n.timezone.ZoneInfoData);
+ method public void setGmtOffset(int);
+ method public void setHour(int);
+ method public void setIsDst(int);
+ method public void setMinute(int);
+ method public void setMonth(int);
+ method public void setMonthDay(int);
+ method public void setSecond(int);
+ method public void setWeekDay(int);
+ method public void setYear(int);
+ method public void setYearDay(int);
+ }
+
+ public final class ZoneInfoDb implements java.lang.AutoCloseable {
+ method public static com.android.i18n.timezone.ZoneInfoDb getInstance();
+ method public String getVersion();
+ method public boolean hasTimeZone(String);
+ method public static com.android.i18n.timezone.ZoneInfoDb loadTzData(String);
+ method public com.android.i18n.timezone.ZoneInfoData makeZoneInfoData(String);
+ method public void validate() throws java.io.IOException;
+ }
+
+}
+
package com.android.icu.text {
public class DateSorterBridge {
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/DebugInfo.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/DebugInfo.java
index 78baa71..a9516f1 100644
--- a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/DebugInfo.java
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/DebugInfo.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package libcore.util;
+package com.android.i18n.timezone;
import java.util.ArrayList;
import java.util.List;
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/CoreLibraryDebug.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/I18nModuleDebug.java
similarity index 90%
rename from android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/CoreLibraryDebug.java
rename to android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/I18nModuleDebug.java
index 0d6ee46..1dd8fe2 100644
--- a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/CoreLibraryDebug.java
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/I18nModuleDebug.java
@@ -14,30 +14,27 @@
* limitations under the License.
*/
-package libcore.util;
+package com.android.i18n.timezone;
+import com.android.i18n.timezone.TzDataSetVersion.TzDataSetException;
+import com.android.i18n.util.Log;
import com.android.icu.util.Icu4cMetadata;
-import libcore.timezone.TimeZoneDataFiles;
-import libcore.timezone.TzDataSetVersion;
-import libcore.timezone.TzDataSetVersion.TzDataSetException;
-import libcore.timezone.ZoneInfoDb;
-
import java.io.File;
import java.io.IOException;
/**
- * Provides APIs for obtaining metadata for the managed core library and lower-level
- * components like bionic and the runtime.
+ * Provides APIs for obtaining metadata for the i18n library and lower-level
+ * components like timezone.
*
* @hide
*/
@libcore.api.CorePlatformApi
-public class CoreLibraryDebug {
+public class I18nModuleDebug {
private static final String CORE_LIBRARY_TIMEZONE_DEBUG_PREFIX = "core_library.timezone.";
- private CoreLibraryDebug() {}
+ private I18nModuleDebug() {}
/**
* Returns information about the Core Library for debugging.
@@ -95,7 +92,7 @@
debugInfo.addStringEntry(statusKey, "ERROR");
debugInfo.addStringEntry(debugKeyPrefix + "exception_class", e.getClass().getName());
debugInfo.addStringEntry(debugKeyPrefix + "exception_msg", e.getMessage());
- System.logE("Error reading " + file, e);
+ Log.e("Error reading " + file, e);
}
} else {
debugInfo.addStringEntry(statusKey, "NOT_FOUND");
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 b4c8976..1506b46 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
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package libcore.timezone;
+package com.android.i18n.timezone;
import java.util.ArrayList;
import java.util.List;
@@ -25,6 +25,7 @@
* @hide
*/
@libcore.api.CorePlatformApi
+@libcore.api.IntraCoreApi
public final class TimeZoneDataFiles {
private static final String ANDROID_ROOT_ENV = "ANDROID_ROOT";
private static final String ANDROID_I18N_ROOT_ENV = "ANDROID_I18N_ROOT";
@@ -42,6 +43,7 @@
* </ul>
*/
// VisibleForTesting
+ @libcore.api.IntraCoreApi
public static String[] getTimeZoneFilePaths(String fileName) {
return new String[] {
getDataTimeZoneFile(fileName),
@@ -61,6 +63,7 @@
return getDataTimeZoneRootDir() + "current/" + fileName;
}
+ @libcore.api.IntraCoreApi
public static String getTimeZoneModuleTzFile(String fileName) {
return getTimeZoneModuleFile("tz/" + fileName);
}
@@ -88,6 +91,7 @@
return System.getenv(ANDROID_I18N_ROOT_ENV) + "/etc/" + fileName;
}
+ @libcore.api.IntraCoreApi
public static String getSystemTzFile(String fileName) {
return getEnvironmentPath(ANDROID_ROOT_ENV, "/usr/share/zoneinfo/" + fileName);
}
@@ -96,6 +100,7 @@
return getEnvironmentPath(ANDROID_ROOT_ENV, "/usr/icu/" + fileName);
}
+ @libcore.api.IntraCoreApi
public static String generateIcuDataPath() {
List<String> paths = new ArrayList<>(3);
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 1a1d156..89ee560 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
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package libcore.timezone;
+package com.android.i18n.timezone;
import java.io.File;
import java.io.FileInputStream;
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/ZoneInfoData.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/ZoneInfoData.java
index 85bf1bc..5612195 100644
--- a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/ZoneInfoData.java
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/ZoneInfoData.java
@@ -20,19 +20,22 @@
* This file is in the public domain, so clarified as of
* 1996-06-05 by Arthur David Olson.
*/
-package libcore.util;
+package com.android.i18n.timezone;
-import android.compat.annotation.UnsupportedAppUsage;
-
+import com.android.i18n.timezone.internal.BufferIterator;
+import com.android.i18n.timezone.internal.ByteBufferIterator;
import java.io.IOException;
import java.io.ObjectInputStream;
+import java.io.ObjectInputStream.GetField;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamField;
+import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
-import libcore.io.BufferIterator;
-import libcore.timezone.ZoneInfoDb;
+import libcore.api.IntraCoreApi;
/**
* Our concrete TimeZone implementation, backed by zoneinfo data.
@@ -47,19 +50,17 @@
* reading the index and creating a {@link BufferIterator} that provides access to an entry for a
* specific file. This class is responsible for reading the data from that {@link BufferIterator}
* and storing it a representation to support the {@link TimeZone} and {@link GregorianCalendar}
- * implementations. See {@link ZoneInfo#readTimeZone(String, BufferIterator, long)}.
+ * implementations. See {@link ZoneInfoData#readTimeZone(String, BufferIterator, long)}.
*
* <p>This class does not use all the information from the {@code tzfile}; it uses:
* {@code tzh_timecnt} and the associated transition times and type information. For each type
* (described by {@code struct ttinfo}) it uses {@code tt_gmtoff} and {@code tt_isdst}.
*
- * <p>This class should be in libcore.timezone but this class is Serializable so cannot
- * be moved there without breaking apps that have (for some reason) serialized TimeZone objects.
- *
- * @hide - used to implement TimeZone
+ * @hide
*/
+@libcore.api.IntraCoreApi
@libcore.api.CorePlatformApi
-public final class ZoneInfo extends TimeZone {
+public final class ZoneInfoData implements Cloneable {
private static final long MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
private static final long MILLISECONDS_PER_400_YEARS =
MILLISECONDS_PER_DAY * (400 * 365 + 100 - 3);
@@ -74,8 +75,22 @@
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
};
- // Proclaim serialization compatibility with pre-OpenJDK AOSP
- static final long serialVersionUID = -4598738130123921552L;
+ /**
+ * The serialized fields in {@link libcore.util.ZoneInfo} kept for backward app compatibility.
+ */
+ @IntraCoreApi
+ public static final ObjectStreamField[] ZONEINFO_SERIALIZED_FIELDS = new ObjectStreamField[] {
+ new ObjectStreamField("mRawOffset", int.class),
+ new ObjectStreamField("mEarliestRawOffset", int.class),
+ new ObjectStreamField("mUseDst", boolean.class),
+ new ObjectStreamField("mDstSavings", int.class),
+ new ObjectStreamField("mTransitions", long[].class),
+ new ObjectStreamField("mTypes", byte[].class),
+ new ObjectStreamField("mOffsets", int[].class),
+ new ObjectStreamField("mIsDsts", byte[].class),
+ };
+
+ private final String mId;
/**
* The (best guess) non-DST offset used "today". It is stored in milliseconds.
@@ -109,8 +124,9 @@
* Implements {@link #getDSTSavings()}
*
* <p>This should be final but is not because it may need to be fixed up by
- * {@link #readObject(ObjectInputStream)} to correct an inconsistency in the previous version
- * of the code whereby this was set to a non-zero value even though DST was not actually used.
+ * {@link #createFromSerializationFields(String, GetField)} to correct an inconsistency in
+ * the previous version of the code whereby this was set to a non-zero value even though DST was
+ * not actually used.
*
* @see #mUseDst
*/
@@ -121,13 +137,13 @@
* in the offset from UTC or a change in the DST.
*
* <p>These times are pre-calculated externally from a set of rules (both historical and
- * future) and stored in a file from which {@link ZoneInfo#readTimeZone(String, BufferIterator,
+ * future) and stored in a file from which {@link ZoneInfoData#readTimeZone(String, BufferIterator,
* long)} reads the data. That is quite different to {@link java.util.SimpleTimeZone}, which has
* essentially human readable rules (e.g. DST starts at 01:00 on the first Sunday in March and
* ends at 01:00 on the last Sunday in October) that can be used to determine the DST transition
* times across a number of years
*
- * <p>In terms of {@link ZoneInfo tzfile} structure this array is of length {@code tzh_timecnt}
+ * <p>In terms of {@link ZoneInfoData tzfile} structure this array is of length {@code tzh_timecnt}
* and contains the times in seconds converted to long to make them safer to use.
*
* <p>They are stored in order from earliest (lowest) time to latest (highest). A transition is
@@ -137,7 +153,6 @@
*
* @see #mTypes
*/
- @UnsupportedAppUsage
private final long[] mTransitions;
/**
@@ -148,7 +163,7 @@
* index. The type is an index into the arrays {@link #mOffsets} and {@link #mIsDsts} that each
* contain one part of the pair.
*
- * <p>In the {@link ZoneInfo tzfile} structure the type array only contains unique instances of
+ * <p>In the {@link ZoneInfoData tzfile} structure the type array only contains unique instances of
* the {@code struct ttinfo} to save space and each type may be referenced by multiple
* transitions. However, the type pairs stored in this class are not guaranteed unique because
* they do not include the {@code tt_abbrind}, which is the abbreviated identifier to use for
@@ -185,7 +200,39 @@
*/
private final byte[] mIsDsts;
- public static ZoneInfo readTimeZone(String id, BufferIterator it, long currentTimeMillis)
+ private ZoneInfoData(String id, int rawOffset, int earliestRawOffset, boolean useDst,
+ int dstSavings, long[] transitions, byte[] types, int[] offsets, byte[] isDsts) {
+ mId = id;
+ mRawOffset = rawOffset;
+ mEarliestRawOffset = earliestRawOffset;
+ mUseDst = useDst;
+ mDstSavings = dstSavings;
+ mTransitions = transitions;
+ mTypes = types;
+ mOffsets = offsets;
+ mIsDsts = isDsts;
+ }
+
+ /**
+ * Copy constructor
+ */
+ @IntraCoreApi
+ public ZoneInfoData(ZoneInfoData that) {
+ if (that == null) {
+ throw new NullPointerException("ZoneInfoData can't be null");
+ }
+ mId = that.mId;
+ mRawOffset = that.mRawOffset;
+ mDstSavings = that.mDstSavings;
+ mEarliestRawOffset = that.mEarliestRawOffset;
+ mUseDst = that.mUseDst;
+ mTransitions = that.mTransitions == null ? null : that.mTransitions.clone();
+ mTypes = that.mTypes == null ? null : that.mTypes.clone();
+ mOffsets = that.mOffsets == null ? null : that.mOffsets.clone();
+ mIsDsts = that.mIsDsts == null ? null : that.mIsDsts.clone();
+
+ }
+ public static ZoneInfoData readTimeZone(String id, BufferIterator it, long currentTimeMillis)
throws IOException {
// Skip over the superseded 32-bit header and data.
@@ -251,7 +298,7 @@
* Read the 64-bit header and data for {@code id} from the current position of {@code it} and
* return a ZoneInfo.
*/
- private static ZoneInfo read64BitData(String id, BufferIterator it, long currentTimeMillis)
+ private static ZoneInfoData read64BitData(String id, BufferIterator it, long currentTimeMillis)
throws IOException {
// Variable names beginning tzh_ correspond to those in "tzfile.h".
@@ -330,7 +377,7 @@
// for any locale. (The RI doesn't do any better than us here either.)
it.skip(1);
}
- return new ZoneInfo(id, transitions64, types, gmtOffsets, isDsts, currentTimeMillis);
+ return new ZoneInfoData(id, transitions64, types, gmtOffsets, isDsts, currentTimeMillis);
}
private static void checkTzifVersionAcceptable(String id, byte tzh_version) throws IOException {
@@ -345,7 +392,7 @@
}
}
- private ZoneInfo(String name, long[] transitions, byte[] types, int[] gmtOffsets, byte[] isDsts,
+ private ZoneInfoData(String name, long[] transitions, byte[] types, int[] gmtOffsets, byte[] isDsts,
long currentTimeMillis) {
if (gmtOffsets.length == 0) {
throw new IllegalArgumentException("ZoneInfo requires at least one offset "
@@ -354,7 +401,7 @@
mTransitions = transitions;
mTypes = types;
mIsDsts = isDsts;
- setID(name);
+ mId = name;
// Find the latest daylight and standard offsets (if any).
int lastStdTransitionIndex = -1;
@@ -456,17 +503,49 @@
}
/**
- * Ensure that when deserializing an instance that {@link #mDstSavings} is always 0 when
- * {@link #mUseDst} is false.
+ * Create an instance from the serialized fields from {@link libcore.util.ZoneInfo}
+ * for backward app compatibility.
*/
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
- in.defaultReadObject();
- if (!mUseDst && mDstSavings != 0) {
- mDstSavings = 0;
+ @libcore.api.IntraCoreApi
+ public static ZoneInfoData createFromSerializationFields(String id,
+ ObjectInputStream.GetField getField) throws IOException {
+ int rawOffset = getField.get("mRawOffset", 0);
+ int earliestRawOffset = getField.get("mEarliestRawOffset", 0);
+ boolean useDst = getField.get("mUseDst", false);
+ int dstSavings = getField.get("mDstSavings", 0);
+ long[] transitions = (long[]) getField.get("mTransitions", null);
+ byte[] types = (byte[]) getField.get("mTypes", null);
+ int[] offsets = (int[]) getField.get("mOffsets", null);
+ byte[] isDsts = (byte[]) getField.get("mIsDsts", null);
+ /** For pre-OpenJDK compatibility, ensure that when deserializing an instance that
+ * {@link #mDstSavings} is always 0 when {@link #mUseDst} is false
+ */
+ if (!useDst && dstSavings != 0) {
+ dstSavings = 0;
}
+
+ return new ZoneInfoData(
+ id, rawOffset, earliestRawOffset,
+ useDst, dstSavings, transitions, types,
+ offsets, isDsts);
}
- @Override
+ /**
+ * Serialize {@link libcore.util.ZoneInfo} into backward app compatible form.
+ */
+ @libcore.api.IntraCoreApi
+ public void writeToSerializationFields(ObjectOutputStream.PutField putField) {
+ putField.put("mRawOffset", mRawOffset);
+ putField.put("mEarliestRawOffset", mEarliestRawOffset);
+ putField.put("mUseDst", mUseDst);
+ putField.put("mDstSavings", mDstSavings);
+ putField.put("mTransitions", mTransitions);
+ putField.put("mTypes", mTypes);
+ putField.put("mOffsets", mOffsets);
+ putField.put("mIsDsts", mIsDsts);
+ }
+
+ @libcore.api.IntraCoreApi
public int getOffset(int era, int year, int month, int day, int dayOfWeek, int millis) {
// XXX This assumes Gregorian always; Calendar switches from
// Julian to Gregorian in 1582. What calendar system are the
@@ -619,6 +698,7 @@
* @param offsets the array whose length must be greater than or equal to 2.
* @return the total offset which is the sum of the raw and DST offsets.
*/
+ @libcore.api.IntraCoreApi
public int getOffsetsByUtcTime(long utcTimeInMillis, int[] offsets) {
int transitionIndex = findTransitionIndex(roundDownMillisToSeconds(utcTimeInMillis));
int totalOffset;
@@ -666,7 +746,7 @@
return totalOffset;
}
- @Override
+ @libcore.api.IntraCoreApi
public int getOffset(long when) {
int offsetIndex = findOffsetIndexForTimeInMilliseconds(when);
if (offsetIndex == -1) {
@@ -678,7 +758,8 @@
return mRawOffset + mOffsets[offsetIndex] * 1000;
}
- @Override public boolean inDaylightTime(Date time) {
+ @libcore.api.IntraCoreApi
+ public boolean inDaylightTime(Date time) {
long when = time.getTime();
int offsetIndex = findOffsetIndexForTimeInMilliseconds(when);
if (offsetIndex == -1) {
@@ -691,27 +772,28 @@
return mIsDsts[offsetIndex] == 1;
}
- @Override public int getRawOffset() {
+ @libcore.api.IntraCoreApi
+ public int getRawOffset() {
return mRawOffset;
}
- @Override public void setRawOffset(int off) {
+ @libcore.api.IntraCoreApi
+ public void setRawOffset(int off) {
mRawOffset = off;
}
- @Override public int getDSTSavings() {
+ @libcore.api.IntraCoreApi
+ public int getDSTSavings() {
return mDstSavings;
}
- @Override public boolean useDaylightTime() {
+ @libcore.api.IntraCoreApi
+ public boolean useDaylightTime() {
return mUseDst;
}
- @Override public boolean hasSameRules(TimeZone timeZone) {
- if (!(timeZone instanceof ZoneInfo)) {
- return false;
- }
- ZoneInfo other = (ZoneInfo) timeZone;
+ @libcore.api.IntraCoreApi
+ public boolean hasSameRules(ZoneInfoData other) {
if (mUseDst != other.mUseDst) {
return false;
}
@@ -727,10 +809,10 @@
}
@Override public boolean equals(Object obj) {
- if (!(obj instanceof ZoneInfo)) {
+ if (!(obj instanceof ZoneInfoData)) {
return false;
}
- ZoneInfo other = (ZoneInfo) obj;
+ ZoneInfoData other = (ZoneInfoData) obj;
return getID().equals(other.getID()) && hasSameRules(other);
}
@@ -750,7 +832,7 @@
@Override
public String toString() {
- return getClass().getName() + "[id=\"" + getID() + "\"" +
+ return "[id=\"" + getID() + "\"" +
",mRawOffset=" + mRawOffset +
",mEarliestRawOffset=" + mEarliestRawOffset +
",mUseDst=" + mUseDst +
@@ -759,13 +841,15 @@
"]";
}
- @Override
- public Object clone() {
- // Overridden for documentation. The default clone() behavior is exactly what we want.
- // Though mutable, the arrays of offset data are treated as immutable. Only ID and
- // mRawOffset are mutable in this class, and those are an immutable object and a primitive
- // respectively.
- return super.clone();
+ @libcore.api.CorePlatformApi
+ @libcore.api.IntraCoreApi
+ public String getID() {
+ return mId;
+ }
+
+ @libcore.api.IntraCoreApi
+ public long[] getTransitionsForAppCompat() {
+ return mTransitions;
}
/**
@@ -826,7 +910,7 @@
* is only one offset rule acting at any given instant. We do not consider leap seconds.
*/
@libcore.api.CorePlatformApi
- public void localtime(int timeSeconds, ZoneInfo zoneInfo) {
+ public void localtime(int timeSeconds, ZoneInfoData zoneInfo) {
try {
int offsetSeconds = zoneInfo.mRawOffset / 1000;
@@ -887,7 +971,7 @@
* occur for other reasons such as when a zone changes its raw offset.
*/
@libcore.api.CorePlatformApi
- public int mktime(ZoneInfo zoneInfo) {
+ public int mktime(ZoneInfoData zoneInfo) {
// Normalize isDst to -1, 0 or 1 to simplify isDst equality checks below.
this.isDst = this.isDst > 0 ? this.isDst = 1 : this.isDst < 0 ? this.isDst = -1 : 0;
@@ -978,7 +1062,7 @@
* {@code targetInterval}, apply it, and see if we are still in {@code targetInterval}. If
* we are, then we have found an adjustment.
*/
- private Integer tryOffsetAdjustments(ZoneInfo zoneInfo, int oldWallTimeSeconds,
+ private Integer tryOffsetAdjustments(ZoneInfoData zoneInfo, int oldWallTimeSeconds,
OffsetInterval targetInterval, int transitionIndex, int isDstToFind)
throws CheckedArithmeticException {
@@ -1011,7 +1095,7 @@
* The {@code startIndex} is used as a starting point so transitions nearest
* to that index are returned first.
*/
- private static int[] getOffsetsOfType(ZoneInfo zoneInfo, int startIndex, int isDst) {
+ private static int[] getOffsetsOfType(ZoneInfoData zoneInfo, int startIndex, int isDst) {
// +1 to account for the synthetic transition we invent before the first recorded one.
int[] offsets = new int[zoneInfo.mOffsets.length + 1];
boolean[] seen = new boolean[zoneInfo.mOffsets.length];
@@ -1075,7 +1159,7 @@
* in seconds if a match has been found and modifies fields, or it returns {@code null} and
* leaves the field state unmodified.
*/
- private Integer doWallTimeSearch(ZoneInfo zoneInfo, int initialTransitionIndex,
+ private Integer doWallTimeSearch(ZoneInfoData zoneInfo, int initialTransitionIndex,
int wallTimeSeconds, boolean mustMatchDst) throws CheckedArithmeticException {
// The loop below starts at the initialTransitionIndex and radiates out from that point
@@ -1351,7 +1435,7 @@
* </li>
* </ol>
*/
- public static OffsetInterval create(ZoneInfo timeZone, int transitionIndex) {
+ public static OffsetInterval create(ZoneInfoData timeZone, int transitionIndex) {
if (transitionIndex < -1 || transitionIndex >= timeZone.mTransitions.length) {
return null;
}
@@ -1468,4 +1552,16 @@
}
return (int) result;
}
+
+ /**
+ * IntraCoreApi made visible for testing in libcore
+ */
+ @libcore.api.IntraCoreApi
+ public static ZoneInfoData createZoneInfo(String name, long timeInMilli, ByteBuffer buf)
+ throws IOException {
+ ByteBufferIterator bufferIterator = new ByteBufferIterator(buf);
+ return ZoneInfoData.readTimeZone(
+ "TimeZone for '" + name + "'", bufferIterator, timeInMilli);
+ }
+
}
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/ZoneInfoDb.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/ZoneInfoDb.java
index c2a028d..30eee3a 100644
--- a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/ZoneInfoDb.java
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/ZoneInfoDb.java
@@ -14,20 +14,19 @@
* limitations under the License.
*/
-package libcore.timezone;
+package com.android.i18n.timezone;
import android.system.ErrnoException;
-import dalvik.annotation.optimization.ReachabilitySensitive;
+import com.android.i18n.timezone.internal.BasicLruCache;
+import com.android.i18n.timezone.internal.BufferIterator;
+import com.android.i18n.timezone.internal.MemoryMappedFile;
+import dalvik.annotation.optimization.ReachabilitySensitive;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import libcore.io.BufferIterator;
-import libcore.io.MemoryMappedFile;
-import libcore.util.BasicLruCache;
-import libcore.util.ZoneInfo;
/**
* A class used to initialize the time zone database. This implementation uses the
@@ -38,6 +37,7 @@
* @hide - used to implement TimeZone
*/
@libcore.api.CorePlatformApi
+@libcore.api.IntraCoreApi
public final class ZoneInfoDb implements AutoCloseable {
// VisibleForTesting
@@ -91,12 +91,12 @@
* See http://b/8270865 for context.
*/
private final static int CACHE_SIZE = 1;
- private final BasicLruCache<String, ZoneInfo> cache =
- new BasicLruCache<String, ZoneInfo>(CACHE_SIZE) {
+ private final BasicLruCache<String, ZoneInfoData> cache =
+ new BasicLruCache<String, ZoneInfoData>(CACHE_SIZE) {
@Override
- protected ZoneInfo create(String id) {
+ protected ZoneInfoData create(String id) {
try {
- return makeTimeZoneUncached(id);
+ return makeZoneInfoDataUncached(id);
} catch (IOException e) {
throw new IllegalStateException("Unable to load timezone for ID=" + id, e);
}
@@ -107,6 +107,7 @@
* Obtains the singleton instance.
*/
@libcore.api.CorePlatformApi
+ @libcore.api.IntraCoreApi
public static ZoneInfoDb getInstance() {
return DATA;
}
@@ -127,7 +128,7 @@
// We didn't find any usable tzdata on disk, so let's just hard-code knowledge of "GMT".
// This is actually implemented in TimeZone itself, so if this is the only time zone
// we report, we won't be asked any more questions.
- System.logE("Couldn't find any " + TZDATA_FILE_NAME + " file!");
+ // !! System.logE("Couldn't find any " + TZDATA_FILE_NAME + " file!");
return ZoneInfoDb.createFallback();
}
@@ -197,7 +198,7 @@
// Something's wrong with the file.
// Log the problem and return false so we try the next choice.
- System.logE(TZDATA_FILE_NAME + " file \"" + path + "\" was present but invalid!", ex);
+ // !! System.logE(TZDATA_FILE_NAME + " file \"" + path + "\" was present but invalid!", ex);
return false;
}
}
@@ -303,27 +304,30 @@
checkNotClosed();
// Validate the data in the tzdata file by loading each and every zone.
for (String id : getAvailableIDs()) {
- ZoneInfo zoneInfo = makeTimeZoneUncached(id);
- if (zoneInfo == null) {
+ ZoneInfoData zoneInfoData = makeZoneInfoDataUncached(id);
+ if (zoneInfoData == null) {
throw new IOException("Unable to find data for ID=" + id);
}
}
}
- ZoneInfo makeTimeZoneUncached(String id) throws IOException {
+ @libcore.api.IntraCoreApi
+ ZoneInfoData makeZoneInfoDataUncached(String id) throws IOException {
BufferIterator it = getBufferIterator(id);
if (it == null) {
return null;
}
- return ZoneInfo.readTimeZone(id, it, System.currentTimeMillis());
+ return ZoneInfoData.readTimeZone(id, it, System.currentTimeMillis());
}
+ @libcore.api.IntraCoreApi
public String[] getAvailableIDs() {
checkNotClosed();
return ids.clone();
}
+ @libcore.api.IntraCoreApi
public String[] getAvailableIDs(int rawUtcOffset) {
checkNotClosed();
List<String> matches = new ArrayList<String>();
@@ -356,6 +360,7 @@
* Returns the tzdb version in use.
*/
@libcore.api.CorePlatformApi
+ @libcore.api.IntraCoreApi
public String getVersion() {
checkNotClosed();
return version;
@@ -367,11 +372,12 @@
}
@libcore.api.CorePlatformApi
- public ZoneInfo makeTimeZone(String id) {
+ @libcore.api.IntraCoreApi
+ public ZoneInfoData makeZoneInfoData(String id) {
checkNotClosed();
- ZoneInfo zoneInfo = cache.get(id);
+ ZoneInfoData zoneInfoData = cache.get(id);
// The object from the cache is cloned because TimeZone / ZoneInfo are mutable.
- return zoneInfo == null ? null : (ZoneInfo) zoneInfo.clone();
+ return zoneInfoData == null ? null : new ZoneInfoData(zoneInfoData);
}
@libcore.api.CorePlatformApi
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/BasicLruCache.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/BasicLruCache.java
index e3ddc64..a6d9a48 100644
--- a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/BasicLruCache.java
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/BasicLruCache.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package libcore.util;
+package com.android.i18n.timezone.internal;
-import android.compat.annotation.UnsupportedAppUsage;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -26,17 +25,28 @@
* @hide
*/
public class BasicLruCache<K, V> {
- @UnsupportedAppUsage
- private final LinkedHashMap<K, V> map;
- private final int maxSize;
+ private static class CacheMap<K, V> extends LinkedHashMap<K, V> {
- @UnsupportedAppUsage
+ private final int maxSize;
+
+ private CacheMap(int maxSize) {
+ super(0, 0.75f, true);
+ this.maxSize = maxSize;
+ }
+
+ @Override
+ protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
+ return this.size() > maxSize;
+ }
+ }
+
+ private final CacheMap<K, V> map;
+
public BasicLruCache(int maxSize) {
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
- this.maxSize = maxSize;
- this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
+ this.map = new CacheMap<K, V>(maxSize);
}
/**
@@ -45,7 +55,6 @@
* head of the queue. This returns null if a value is not cached and cannot
* be created.
*/
- @UnsupportedAppUsage
public final V get(K key) {
if (key == null) {
throw new NullPointerException("key == null");
@@ -70,7 +79,6 @@
// isn't design for such usage anyway).
if (result != null) {
map.put(key, result);
- trimToSize(maxSize);
}
}
@@ -82,9 +90,8 @@
* the queue.
*
* @return the previous value mapped by {@code key}. Although that entry is
- * no longer cached, it has not been passed to {@link #entryEvicted}.
+ * no longer cached, it has not been evicted.
*/
- @UnsupportedAppUsage
public synchronized final V put(K key, V value) {
if (key == null) {
throw new NullPointerException("key == null");
@@ -93,28 +100,9 @@
}
V previous = map.put(key, value);
- trimToSize(maxSize);
return previous;
}
- private void trimToSize(int maxSize) {
- while (map.size() > maxSize) {
- Map.Entry<K, V> toEvict = map.eldest();
-
- K key = toEvict.getKey();
- V value = toEvict.getValue();
- map.remove(key);
-
- entryEvicted(key, value);
- }
- }
-
- /**
- * Called for entries that have reached the tail of the least recently used
- * queue and are be removed. The default implementation does nothing.
- */
- protected void entryEvicted(K key, V value) {}
-
/**
* Called after a cache miss to compute a value for the corresponding key.
* Returns the computed value or null if no value can be computed. The
@@ -125,18 +113,9 @@
}
/**
- * Returns a copy of the current contents of the cache, ordered from least
- * recently accessed to most recently accessed.
- */
- public synchronized final Map<K, V> snapshot() {
- return new LinkedHashMap<K, V>(map);
- }
-
- /**
* Clear the cache, calling {@link #entryEvicted} on each removed entry.
*/
- @UnsupportedAppUsage
public synchronized final void evictAll() {
- trimToSize(0);
+ map.clear();
}
}
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/BufferIterator.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/BufferIterator.java
index fb97250..c12d3df 100644
--- a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/BufferIterator.java
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/BufferIterator.java
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package libcore.io;
-
-import android.compat.annotation.UnsupportedAppUsage;
+package com.android.i18n.timezone.internal;
/**
* Iterates over big- or little-endian bytes. See {@link MemoryMappedFile#bigEndianIterator} and
@@ -29,13 +27,11 @@
* Seeks to the absolute position {@code offset}, measured in bytes from the start of the
* buffer.
*/
- @UnsupportedAppUsage
public abstract void seek(int offset);
/**
* Skips forwards or backwards {@code byteCount} bytes from the current position.
*/
- @UnsupportedAppUsage
public abstract void skip(int byteCount);
/**
@@ -49,7 +45,6 @@
*
* @throws IndexOutOfBoundsException if the read / write would be outside of the buffer / array
*/
- @UnsupportedAppUsage
public abstract void readByteArray(byte[] bytes, int arrayOffset, int byteCount);
/**
@@ -57,7 +52,6 @@
*
* @throws IndexOutOfBoundsException if the read would be outside of the buffer
*/
- @UnsupportedAppUsage
public abstract byte readByte();
/**
@@ -65,7 +59,6 @@
*
* @throws IndexOutOfBoundsException if the read would be outside of the buffer
*/
- @UnsupportedAppUsage
public abstract int readInt();
/**
@@ -74,7 +67,6 @@
*
* @throws IndexOutOfBoundsException if the read / write would be outside of the buffer / array
*/
- @UnsupportedAppUsage
public abstract void readIntArray(int[] ints, int arrayOffset, int intCount);
/**
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/ByteBufferIterator.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/ByteBufferIterator.java
new file mode 100644
index 0000000..e3cf9e4
--- /dev/null
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/ByteBufferIterator.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.i18n.timezone.internal;
+
+import java.nio.ByteBuffer;
+
+/**
+ * A {@link BufferIterator} that wraps a {@link ByteBuffer}.
+ */
+public class ByteBufferIterator extends BufferIterator {
+
+ private final ByteBuffer buffer;
+
+ public ByteBufferIterator(ByteBuffer buffer) {
+ this.buffer = buffer;
+ }
+
+ @Override
+ public void seek(int offset) {
+ buffer.position(offset);
+ }
+
+ @Override
+ public void skip(int byteCount) {
+ buffer.position(buffer.position() + byteCount);
+ }
+
+ @Override
+ public int pos() {
+ return buffer.position();
+ }
+
+ @Override
+ public void readByteArray(byte[] bytes, int arrayOffset, int byteCount) {
+ buffer.get(bytes, arrayOffset, byteCount);
+ }
+
+ @Override
+ public byte readByte() {
+ return buffer.get();
+ }
+
+ @Override
+ public int readInt() {
+ int value = buffer.asIntBuffer().get();
+ // Using a separate view does not update the position of this buffer so do it
+ // explicitly.
+ skip(Integer.BYTES);
+ return value;
+ }
+
+ @Override
+ public void readIntArray(int[] ints, int arrayOffset, int intCount) {
+ buffer.asIntBuffer().get(ints, arrayOffset, intCount);
+ // Using a separate view does not update the position of this buffer so do it
+ // explicitly.
+ skip(Integer.BYTES * intCount);
+ }
+
+ @Override
+ public void readLongArray(long[] longs, int arrayOffset, int longCount) {
+ buffer.asLongBuffer().get(longs, arrayOffset, longCount);
+ // Using a separate view does not update the position of this buffer so do it
+ // explicitly.
+ skip(Long.BYTES * longCount);
+ }
+
+ @Override
+ public short readShort() {
+ short value = buffer.asShortBuffer().get();
+ // Using a separate view does not update the position of this buffer so do it
+ // explicitly.
+ skip(Short.BYTES);
+ return value;
+ }
+}
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/Memory.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/Memory.java
index 9e7f4ea..846044a 100644
--- a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/Memory.java
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/Memory.java
@@ -15,38 +15,19 @@
* limitations under the License.
*/
-package libcore.io;
-
-import android.compat.annotation.UnsupportedAppUsage;
-
-import java.nio.ByteOrder;
+package com.android.i18n.timezone.internal;
import dalvik.annotation.optimization.FastNative;
+import java.nio.ByteOrder;
/**
* Unsafe access to memory.
*
* @hide
*/
-@libcore.api.CorePlatformApi
public final class Memory {
private Memory() { }
- /**
- * Used to optimize nio heap buffer bulk get operations. 'dst' must be a primitive array.
- * 'dstOffset' is measured in units of 'sizeofElements' bytes.
- */
- public static native void unsafeBulkGet(Object dst, int dstOffset, int byteCount,
- byte[] src, int srcOffset, int sizeofElements, boolean swap);
-
- /**
- * Used to optimize nio heap buffer bulk put operations. 'src' must be a primitive array.
- * 'srcOffset' is measured in units of 'sizeofElements' bytes.
- */
- public static native void unsafeBulkPut(byte[] dst, int dstOffset, int byteCount,
- Object src, int srcOffset, int sizeofElements, boolean swap);
-
- @libcore.api.CorePlatformApi
public static int peekInt(byte[] src, int offset, ByteOrder order) {
if (order == ByteOrder.BIG_ENDIAN) {
return (((src[offset++] & 0xff) << 24) |
@@ -85,7 +66,6 @@
}
}
- @libcore.api.CorePlatformApi
public static short peekShort(byte[] src, int offset, ByteOrder order) {
if (order == ByteOrder.BIG_ENDIAN) {
return (short) ((src[offset] << 8) | (src[offset + 1] & 0xff));
@@ -94,7 +74,7 @@
}
}
- @libcore.api.CorePlatformApi
+
public static void pokeInt(byte[] dst, int offset, int value, ByteOrder order) {
if (order == ByteOrder.BIG_ENDIAN) {
dst[offset++] = (byte) ((value >> 24) & 0xff);
@@ -108,8 +88,6 @@
dst[offset ] = (byte) ((value >> 24) & 0xff);
}
}
-
- @libcore.api.CorePlatformApi
public static void pokeLong(byte[] dst, int offset, long value, ByteOrder order) {
if (order == ByteOrder.BIG_ENDIAN) {
int i = (int) (value >> 32);
@@ -135,8 +113,6 @@
dst[offset ] = (byte) ((i >> 24) & 0xff);
}
}
-
- @libcore.api.CorePlatformApi
public static void pokeShort(byte[] dst, int offset, short value, ByteOrder order) {
if (order == ByteOrder.BIG_ENDIAN) {
dst[offset++] = (byte) ((value >> 8) & 0xff);
@@ -147,24 +123,8 @@
}
}
- /**
- * Copies 'byteCount' bytes from the source to the destination. The objects are either
- * instances of DirectByteBuffer or byte[]. The offsets in the byte[] case must include
- * the Buffer.arrayOffset if the array came from a Buffer.array call. We could make this
- * private and provide the four type-safe variants, but then ByteBuffer.put(ByteBuffer)
- * would need to work out which to call based on whether the source and destination buffers
- * are direct or not.
- *
- * @hide make type-safe before making public?
- */
- @libcore.api.CorePlatformApi
- public static native void memmove(Object dstObject, int dstOffset, Object srcObject, int srcOffset, long byteCount);
-
- @UnsupportedAppUsage
@FastNative
public static native byte peekByte(long address);
-
- @UnsupportedAppUsage
public static int peekInt(long address, boolean swap) {
int result = peekIntNative(address);
if (swap) {
@@ -174,8 +134,6 @@
}
@FastNative
private static native int peekIntNative(long address);
-
- @UnsupportedAppUsage
public static long peekLong(long address, boolean swap) {
long result = peekLongNative(address);
if (swap) {
@@ -195,8 +153,6 @@
}
@FastNative
private static native short peekShortNative(long address);
-
- @UnsupportedAppUsage
public static native void peekByteArray(long address, byte[] dst, int dstOffset, int byteCount);
public static native void peekCharArray(long address, char[] dst, int dstOffset, int charCount, boolean swap);
public static native void peekDoubleArray(long address, double[] dst, int dstOffset, int doubleCount, boolean swap);
@@ -204,12 +160,8 @@
public static native void peekIntArray(long address, int[] dst, int dstOffset, int intCount, boolean swap);
public static native void peekLongArray(long address, long[] dst, int dstOffset, int longCount, boolean swap);
public static native void peekShortArray(long address, short[] dst, int dstOffset, int shortCount, boolean swap);
-
- @UnsupportedAppUsage
@FastNative
public static native void pokeByte(long address, byte value);
-
- @UnsupportedAppUsage
public static void pokeInt(long address, int value, boolean swap) {
if (swap) {
value = Integer.reverseBytes(value);
@@ -218,8 +170,6 @@
}
@FastNative
private static native void pokeIntNative(long address, int value);
-
- @UnsupportedAppUsage
public static void pokeLong(long address, long value, boolean swap) {
if (swap) {
value = Long.reverseBytes(value);
@@ -237,8 +187,6 @@
}
@FastNative
private static native void pokeShortNative(long address, short value);
-
- @UnsupportedAppUsage
public static native void pokeByteArray(long address, byte[] src, int offset, int count);
public static native void pokeCharArray(long address, char[] src, int offset, int count, boolean swap);
public static native void pokeDoubleArray(long address, double[] src, int offset, int count, boolean swap);
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/MemoryMappedFile.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/MemoryMappedFile.java
index 5e003ea..d2c2811 100644
--- a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/MemoryMappedFile.java
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/MemoryMappedFile.java
@@ -14,22 +14,19 @@
* limitations under the License.
*/
-package libcore.io;
+package com.android.i18n.timezone.internal;
-import android.compat.annotation.UnsupportedAppUsage;
import android.system.ErrnoException;
-
+import android.system.Os;
import java.io.FileDescriptor;
import java.nio.ByteOrder;
-import static android.system.OsConstants.MAP_SHARED;
-import static android.system.OsConstants.O_RDONLY;
-import static android.system.OsConstants.PROT_READ;
-
/**
* A memory-mapped file. Use {@link #mmapRO} to map a file, {@link #close} to unmap a file,
* and either {@link #bigEndianIterator} or {@link #littleEndianIterator} to get a seekable
* {@link BufferIterator} over the mapped data. This class is not thread safe.
+ *
+ * @hide
*/
public final class MemoryMappedFile implements AutoCloseable {
private boolean closed;
@@ -49,15 +46,14 @@
/**
* Use this to mmap the whole file read-only.
*/
- @UnsupportedAppUsage
public static MemoryMappedFile mmapRO(String path) throws ErrnoException {
- FileDescriptor fd = Libcore.os.open(path, O_RDONLY, 0);
+ FileDescriptor fd = Os.open(path, 0 /* O_RDONLY */, 0);
try {
- long size = Libcore.os.fstat(fd).st_size;
- long address = Libcore.os.mmap(0L, size, PROT_READ, MAP_SHARED, fd, 0);
+ long size = Os.fstat(fd).st_size;
+ long address = Os.mmap(0L, size, 0x1 /* PROT_READ */, 0x01 /* MAP_SHARED */, fd, 0);
return new MemoryMappedFile(address, size);
} finally {
- Libcore.os.close(fd);
+ Os.close(fd);
}
}
@@ -72,7 +68,7 @@
public void close() throws ErrnoException {
if (!closed) {
closed = true;
- Libcore.os.munmap(address, size);
+ Os.munmap(address, size);
}
}
@@ -83,7 +79,6 @@
/**
* Returns a new iterator that treats the mapped data as big-endian.
*/
- @UnsupportedAppUsage
public BufferIterator bigEndianIterator() {
return new NioBufferIterator(
this, address, size, ByteOrder.nativeOrder() != ByteOrder.BIG_ENDIAN);
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/NioBufferIterator.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/NioBufferIterator.java
index 1554519..83c0ec6 100644
--- a/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/NioBufferIterator.java
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/timezone/internal/NioBufferIterator.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package libcore.io;
+package com.android.i18n.timezone.internal;
/**
* Iterates over big- or little-endian bytes on the native heap.
diff --git a/android_icu4j/libcore_bridge/src/java/com/android/i18n/util/Log.java b/android_icu4j/libcore_bridge/src/java/com/android/i18n/util/Log.java
new file mode 100644
index 0000000..6d960b9
--- /dev/null
+++ b/android_icu4j/libcore_bridge/src/java/com/android/i18n/util/Log.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.i18n.util;
+
+/**
+ * Log utility class only used by i18n module.
+ *
+ * @hide
+ */
+public class Log {
+ // liblog's log priorities from android_LogPriority in log.h.
+ private static int VERBOSE = 2;
+ private static int DEBUG = 3;
+ private static int INFO = 4;
+ private static int WARN = 5;
+ private static int ERROR = 6;
+ private static int FATAL = 7;
+
+ public static void e(String msg, Throwable e) {
+ log(ERROR, msg, e);
+ }
+
+ private static native void log(int priority, String msg, Throwable th);
+}
diff --git a/android_icu4j/libcore_bridge/src/native/Register.cpp b/android_icu4j/libcore_bridge/src/native/Register.cpp
index 7997077..4313345 100644
--- a/android_icu4j/libcore_bridge/src/native/Register.cpp
+++ b/android_icu4j/libcore_bridge/src/native/Register.cpp
@@ -35,6 +35,8 @@
#define REGISTER(FN) extern void FN(JNIEnv*); FN(env)
REGISTER(register_com_android_icu_text_TimeZoneNamesNative);
+ REGISTER(register_com_android_i18n_timezone_internal_Memory);
+ REGISTER(register_com_android_i18n_util_Log);
REGISTER(register_com_android_icu_util_CaseMapperNative);
REGISTER(register_com_android_icu_util_Icu4cMetadata);
REGISTER(register_com_android_icu_util_LocaleNative);
diff --git a/android_icu4j/libcore_bridge/src/native/com_android_i18n_timezone_internal_Memory.cpp b/android_icu4j/libcore_bridge/src/native/com_android_i18n_timezone_internal_Memory.cpp
index a5b7b72..d38bcfb 100644
--- a/android_icu4j/libcore_bridge/src/native/com_android_i18n_timezone_internal_Memory.cpp
+++ b/android_icu4j/libcore_bridge/src/native/com_android_i18n_timezone_internal_Memory.cpp
@@ -16,6 +16,7 @@
#define LOG_TAG "Memory"
+#include <byteswap.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -27,7 +28,6 @@
#include <nativehelper/jni_macros.h>
#include "JniConstants.h"
-#include "Portability.h"
// Use packed structures for access to unaligned data on targets with alignment restrictions.
// The compiler will generate appropriate code to access these structures without
@@ -92,18 +92,6 @@
}
}
-static void Memory_memmove(JNIEnv* env, jclass, jobject dstObject, jint dstOffset, jobject srcObject, jint srcOffset, jlong length) {
- ScopedBytesRW dstBytes(env, dstObject);
- if (dstBytes.get() == NULL) {
- return;
- }
- ScopedBytesRO srcBytes(env, srcObject);
- if (srcBytes.get() == NULL) {
- return;
- }
- memmove(dstBytes.get() + dstOffset, srcBytes.get() + srcOffset, length);
-}
-
static jbyte Memory_peekByte(JNIEnv*, jclass, jlong srcAddress) {
return *cast<const jbyte*>(srcAddress);
}
@@ -233,64 +221,7 @@
put_unaligned<jlong>(cast<jlong*>(dstAddress), value);
}
-static void unsafeBulkCopy(jbyte* dst, const jbyte* src, jint byteCount,
- jint sizeofElement, jboolean swap) {
- if (!swap) {
- memcpy(dst, src, byteCount);
- return;
- }
-
- if (sizeofElement == 2) {
- jshort* dstShorts = reinterpret_cast<jshort*>(dst);
- const jshort* srcShorts = reinterpret_cast<const jshort*>(src);
- swapShorts(dstShorts, srcShorts, byteCount / 2);
- } else if (sizeofElement == 4) {
- jint* dstInts = reinterpret_cast<jint*>(dst);
- const jint* srcInts = reinterpret_cast<const jint*>(src);
- swapInts(dstInts, srcInts, byteCount / 4);
- } else if (sizeofElement == 8) {
- jlong* dstLongs = reinterpret_cast<jlong*>(dst);
- const jlong* srcLongs = reinterpret_cast<const jlong*>(src);
- swapLongs(dstLongs, srcLongs, byteCount / 8);
- }
-}
-
-static void Memory_unsafeBulkGet(JNIEnv* env, jclass, jobject dstObject, jint dstOffset,
- jint byteCount, jbyteArray srcArray, jint srcOffset, jint sizeofElement, jboolean swap) {
- ScopedByteArrayRO srcBytes(env, srcArray);
- if (srcBytes.get() == NULL) {
- return;
- }
- jarray dstArray = reinterpret_cast<jarray>(dstObject);
- jbyte* dstBytes = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(dstArray, NULL));
- if (dstBytes == NULL) {
- return;
- }
- jbyte* dst = dstBytes + dstOffset*sizeofElement;
- const jbyte* src = srcBytes.get() + srcOffset;
- unsafeBulkCopy(dst, src, byteCount, sizeofElement, swap);
- env->ReleasePrimitiveArrayCritical(dstArray, dstBytes, 0);
-}
-
-static void Memory_unsafeBulkPut(JNIEnv* env, jclass, jbyteArray dstArray, jint dstOffset,
- jint byteCount, jobject srcObject, jint srcOffset, jint sizeofElement, jboolean swap) {
- ScopedByteArrayRW dstBytes(env, dstArray);
- if (dstBytes.get() == NULL) {
- return;
- }
- jarray srcArray = reinterpret_cast<jarray>(srcObject);
- jbyte* srcBytes = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(srcArray, NULL));
- if (srcBytes == NULL) {
- return;
- }
- jbyte* dst = dstBytes.get() + dstOffset;
- const jbyte* src = srcBytes + srcOffset*sizeofElement;
- unsafeBulkCopy(dst, src, byteCount, sizeofElement, swap);
- env->ReleasePrimitiveArrayCritical(srcArray, srcBytes, 0);
-}
-
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Memory, memmove, "(Ljava/lang/Object;ILjava/lang/Object;IJ)V"),
FAST_NATIVE_METHOD(Memory, peekByte, "(J)B"),
NATIVE_METHOD(Memory, peekByteArray, "(J[BII)V"),
NATIVE_METHOD(Memory, peekCharArray, "(J[CIIZ)V"),
@@ -313,9 +244,7 @@
NATIVE_METHOD(Memory, pokeLongArray, "(J[JIIZ)V"),
FAST_NATIVE_METHOD(Memory, pokeShortNative, "(JS)V"),
NATIVE_METHOD(Memory, pokeShortArray, "(J[SIIZ)V"),
- NATIVE_METHOD(Memory, unsafeBulkGet, "(Ljava/lang/Object;II[BIIZ)V"),
- NATIVE_METHOD(Memory, unsafeBulkPut, "([BIILjava/lang/Object;IIZ)V"),
};
-void register_libcore_io_Memory(JNIEnv* env) {
- jniRegisterNativeMethods(env, "libcore/io/Memory", gMethods, NELEM(gMethods));
+void register_com_android_i18n_timezone_internal_Memory(JNIEnv* env) {
+ jniRegisterNativeMethods(env, "com/android/i18n/timezone/internal/Memory", gMethods, NELEM(gMethods));
}
diff --git a/android_icu4j/libcore_bridge/src/native/com_android_i18n_util_Log.cpp b/android_icu4j/libcore_bridge/src/native/com_android_i18n_util_Log.cpp
new file mode 100644
index 0000000..a5a2d61
--- /dev/null
+++ b/android_icu4j/libcore_bridge/src/native/com_android_i18n_util_Log.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Log"
+
+#include <memory>
+
+#include "jni.h"
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/jni_macros.h>
+
+typedef std::unique_ptr<char const[], std::function<void(char const*)>> jni_string;
+
+static void Log_log(JNIEnv* env, jclass, jint priority, jstring msg, jthrowable throwable) {
+ if (msg == NULL) {
+ jniThrowNullPointerException(env, "Log needs a message");
+ return;
+ }
+
+ std::unique_ptr<char const[], std::function<void(char const*)>> message(
+ env->GetStringUTFChars(msg, 0),
+ [=](char const* p) mutable{ env->ReleaseStringUTFChars(msg, p); }
+ );
+
+ LOG_PRI(priority, "Log", "%s", message.get());
+
+ if (throwable != NULL) {
+ jniLogException(env, priority, "Log", throwable);
+ }
+}
+
+static JNINativeMethod gMethods[] = {
+ NATIVE_METHOD(Log, log, "(ILjava/lang/String;Ljava/lang/Throwable;)V"),
+};
+void register_com_android_i18n_util_Log(JNIEnv* env) {
+ jniRegisterNativeMethods(env, "com/android/i18n/util/Log", gMethods, NELEM(gMethods));
+}
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 a74ba30..13884bf 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
@@ -14,16 +14,17 @@
* limitations under the License.
*/
-package libcore.libcore.timezone;
-
-import org.junit.Test;
-
-import libcore.timezone.TimeZoneDataFiles;
+package com.android.i18n.test.timezone;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import android.icu.testsharding.MainTestShard;
+import com.android.i18n.timezone.TimeZoneDataFiles;
+import org.junit.Test;
+
+@MainTestShard
public class TimeZoneDataFilesTest {
private static final String ANDROID_TZDATA_ROOT_ENV = "ANDROID_TZDATA_ROOT";
diff --git a/android_icu4j/testing/src/com/android/i18n/test/timezone/TimeZoneIntegrationTest.java b/android_icu4j/testing/src/com/android/i18n/test/timezone/TimeZoneIntegrationTest.java
index f24d8b1..57f0c6b 100644
--- a/android_icu4j/testing/src/com/android/i18n/test/timezone/TimeZoneIntegrationTest.java
+++ b/android_icu4j/testing/src/com/android/i18n/test/timezone/TimeZoneIntegrationTest.java
@@ -14,8 +14,14 @@
* limitations under the License.
*/
-package libcore.libcore.icu;
+package com.android.i18n.test.timezone;
+import android.icu.testsharding.MainTestShard;
+import com.android.i18n.timezone.I18nModuleDebug;
+import com.android.i18n.timezone.DebugInfo;
+import com.android.i18n.timezone.TimeZoneDataFiles;
+import com.android.i18n.timezone.TzDataSetVersion;
+import com.android.i18n.timezone.ZoneInfoDb;
import org.junit.Test;
import android.icu.text.TimeZoneNames;
@@ -39,12 +45,7 @@
import java.util.function.Function;
import java.util.stream.Collectors;
-import libcore.timezone.TimeZoneDataFiles;
import libcore.timezone.TimeZoneFinder;
-import libcore.timezone.TzDataSetVersion;
-import libcore.timezone.ZoneInfoDb;
-import libcore.util.CoreLibraryDebug;
-import libcore.util.DebugInfo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -54,6 +55,7 @@
/**
* Tests that compare ICU and libcore time zone behavior and similar cross-cutting concerns.
*/
+@MainTestShard
public class TimeZoneIntegrationTest {
// http://b/28949992
@@ -259,7 +261,7 @@
*/
@Test
public void testTimeZoneDebugInfo() throws Exception {
- DebugInfo debugInfo = CoreLibraryDebug.getDebugInfo();
+ DebugInfo debugInfo = I18nModuleDebug.getDebugInfo();
// Devices are expected to have a time zone module which overrides or extends the data in
// the runtime module depending on the file. It's not actually mandatory for all Android
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 a653301..fdf7294 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
@@ -14,13 +14,15 @@
* limitations under the License.
*/
-package libcore.libcore.timezone;
+package com.android.i18n.test.timezone;
+import android.icu.testsharding.MainTestShard;
import junit.framework.TestCase;
-import libcore.timezone.TzDataSetVersion;
-import libcore.timezone.TzDataSetVersion.TzDataSetException;
+import com.android.i18n.timezone.TzDataSetVersion;
+import com.android.i18n.timezone.TzDataSetVersion.TzDataSetException;
+@MainTestShard
public class TzDataSetVersionTest extends TestCase {
private static final int INVALID_VERSION_LOW = -1;
diff --git a/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDataTest.java b/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDataTest.java
index 8b9715f..2957128 100644
--- a/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDataTest.java
+++ b/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDataTest.java
@@ -13,36 +13,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package libcore.libcore.util;
+package com.android.i18n.test.timezone;
-import junit.framework.TestCase;
-
+import android.icu.testsharding.MainTestShard;
+import com.android.i18n.timezone.ZoneInfoData;
+import com.android.i18n.timezone.ZoneInfoDb;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.Date;
-import libcore.io.BufferIterator;
-import libcore.timezone.ZoneInfoDb;
+import junit.framework.TestCase;
+import com.android.i18n.timezone.internal.BufferIterator;
import libcore.timezone.testing.ZoneInfoTestHelper;
-import libcore.util.ZoneInfo;
/**
- * Tests for {@link ZoneInfo}
+ * Tests for {@link ZoneInfoData}
*/
-public class ZoneInfoTest extends TestCase {
+@MainTestShard
+public class ZoneInfoDataTest extends TestCase {
/**
- * Checks that a {@link ZoneInfo} cannot be created without any types.
+ * Checks that a {@link ZoneInfoData} cannot be created without any types.
*/
public void testMakeTimeZone_NoTypes() throws Exception {
long[][] transitions = {};
int[][] types = {};
try {
- createZoneInfo(transitions, types);
+ createZoneInfoData(transitions, types);
fail();
} catch (IOException expected) {
}
@@ -56,7 +55,7 @@
int[][] types = {
{ 4800, 0 }
};
- ZoneInfo zoneInfo = createZoneInfo(transitions, types);
+ ZoneInfoData zoneInfoData = createZoneInfoData(transitions, types);
// If there are no transitions then the offset should be constant irrespective of the time.
Instant[] times = {
@@ -64,14 +63,14 @@
Instant.ofEpochMilli(0),
Instant.ofEpochMilli(Long.MAX_VALUE),
};
- assertOffsetAt(zoneInfo, offsetFromSeconds(4800), times);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(4800), times);
// No transitions means no DST.
- assertFalse("Doesn't use DST", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, offsetFromSeconds(0));
+ assertFalse("Doesn't use DST", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, offsetFromSeconds(0));
// The raw offset should be the offset of the first type.
- assertRawOffset(zoneInfo, offsetFromSeconds(4800));
+ assertRawOffset(zoneInfoData, offsetFromSeconds(4800));
}
/**
@@ -84,18 +83,18 @@
int[][] types = {
{ 3600, 0 }
};
- ZoneInfo zoneInfo = createZoneInfo(transitions, types);
+ ZoneInfoData zoneInfoData = createZoneInfoData(transitions, types);
// Any time before the first transition is assumed to use the first standard transition.
Instant[] times = { timeFromSeconds(-2), timeFromSeconds(0), timeFromSeconds(2) };
- assertOffsetAt(zoneInfo, offsetFromSeconds(3600), times);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(3600), times);
// No transitions means no DST.
- assertFalse("Doesn't use DST", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, offsetFromSeconds(0));
+ assertFalse("Doesn't use DST", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, offsetFromSeconds(0));
// The raw offset should be the offset of the first type.
- assertRawOffset(zoneInfo, offsetFromSeconds(3600));
+ assertRawOffset(zoneInfoData, offsetFromSeconds(3600));
}
/**
@@ -109,7 +108,7 @@
{ 3600, 1 }
};
try {
- createZoneInfo(transitions, types);
+ createZoneInfoData(transitions, types);
fail("Did not detect no non-DST transitions");
} catch (IllegalStateException expected) {
}
@@ -130,26 +129,26 @@
{ 3600, 1 },
{ 5400, 0 }
};
- ZoneInfo zoneInfo = createZoneInfo(transitions, types);
+ ZoneInfoData zoneInfoData = createZoneInfoData(transitions, types);
Instant transitionTime = timeFromSeconds(-5);
// Even a millisecond before a transition means that the transition is not active.
Instant beforeTransitionTime = transitionTime.minusMillis(1);
- assertOffsetAt(zoneInfo, offsetFromSeconds(1800), beforeTransitionTime);
- assertInDaylightTime(zoneInfo, beforeTransitionTime, false);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(1800), beforeTransitionTime);
+ assertInDaylightTime(zoneInfoData, beforeTransitionTime, false);
// A time equal to the transition point activates the transition.
- assertOffsetAt(zoneInfo, offsetFromSeconds(3600), transitionTime);
- assertInDaylightTime(zoneInfo, transitionTime, true);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(3600), transitionTime);
+ assertInDaylightTime(zoneInfoData, transitionTime, true);
// A time after the transition point but before the next activates the transition.
Instant afterTransitionTime = transitionTime.plusMillis(1);
- assertOffsetAt(zoneInfo, offsetFromSeconds(3600), afterTransitionTime);
- assertInDaylightTime(zoneInfo, afterTransitionTime, true);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(3600), afterTransitionTime);
+ assertInDaylightTime(zoneInfoData, afterTransitionTime, true);
- assertFalse("Doesn't use DST", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, offsetFromSeconds(0));
- assertRawOffset(zoneInfo, offsetFromSeconds(5400));
+ assertFalse("Doesn't use DST", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, offsetFromSeconds(0));
+ assertRawOffset(zoneInfoData, offsetFromSeconds(5400));
}
/**
@@ -167,27 +166,27 @@
{ 3600, 1 },
{ 5400, 0 }
};
- ZoneInfo zoneInfo = createZoneInfo(transitions, types);
+ ZoneInfoData zoneInfoData = createZoneInfoData(transitions, types);
Instant transitionTime = timeFromSeconds(5);
// Even a millisecond before a transition means that the transition is not active.
Instant beforeTransitionTime = transitionTime.minusMillis(1);
- assertOffsetAt(zoneInfo, offsetFromSeconds(1800), beforeTransitionTime);
- assertInDaylightTime(zoneInfo, beforeTransitionTime, false);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(1800), beforeTransitionTime);
+ assertInDaylightTime(zoneInfoData, beforeTransitionTime, false);
// A time equal to the transition point activates the transition.
- assertOffsetAt(zoneInfo, offsetFromSeconds(3600), transitionTime);
- assertInDaylightTime(zoneInfo, transitionTime, true);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(3600), transitionTime);
+ assertInDaylightTime(zoneInfoData, transitionTime, true);
// A time after the transition point but before the next activates the transition.
Instant afterTransitionTime = transitionTime.plusMillis(1);
- assertOffsetAt(zoneInfo, offsetFromSeconds(3600), afterTransitionTime);
- assertInDaylightTime(zoneInfo, afterTransitionTime, true);
+ assertOffsetAt(zoneInfoData, offsetFromSeconds(3600), afterTransitionTime);
+ assertInDaylightTime(zoneInfoData, afterTransitionTime, true);
- assertFalse("Doesn't use DST", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, offsetFromSeconds(0));
- assertRawOffset(zoneInfo, offsetFromSeconds(5400));
+ assertFalse("Doesn't use DST", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, offsetFromSeconds(0));
+ assertRawOffset(zoneInfoData, offsetFromSeconds(5400));
}
/**
@@ -210,17 +209,17 @@
// Or in other words (5400 - 3600) * 1000
Duration expectedDSTSavings = offsetFromSeconds(5400 - 3600);
- ZoneInfo zoneInfo = createZoneInfo(transitions, types, timeFromSeconds(-700));
+ ZoneInfoData zoneInfoData = createZoneInfoData(transitions, types, timeFromSeconds(-700));
- assertTrue("Should use DST but doesn't", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, expectedDSTSavings);
+ assertTrue("Should use DST but doesn't", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, expectedDSTSavings);
// Now create one a few milliseconds before the DST transition to make sure that rounding
// errors don't cause a problem.
- zoneInfo = createZoneInfo(transitions, types, timeFromSeconds(-100).minusMillis(5));
+ zoneInfoData = createZoneInfoData(transitions, types, timeFromSeconds(-100).minusMillis(5));
- assertTrue("Should use DST but doesn't", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, expectedDSTSavings);
+ assertTrue("Should use DST but doesn't", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, expectedDSTSavings);
}
/**
@@ -243,17 +242,18 @@
// Or in other words (7200 - 3600) * 1000
Duration expectedDSTSavings = offsetFromSeconds(7200 - 3600);
- ZoneInfo zoneInfo = createZoneInfo(transitions, types, timeFromSeconds(4500) /* currentTime */);
+ ZoneInfoData zoneInfoData = createZoneInfoData(transitions, types,
+ timeFromSeconds(4500) /* currentTime */);
- assertTrue("Should use DST but doesn't", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, expectedDSTSavings);
+ assertTrue("Should use DST but doesn't", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, expectedDSTSavings);
// Now create one a few milliseconds before the DST transition to make sure that rounding
// errors don't cause a problem.
- zoneInfo = createZoneInfo(transitions, types, timeFromSeconds(6000).minusMillis(5));
+ zoneInfoData = createZoneInfoData(transitions, types, timeFromSeconds(6000).minusMillis(5));
- assertTrue("Should use DST but doesn't", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, expectedDSTSavings);
+ assertTrue("Should use DST but doesn't", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, expectedDSTSavings);
}
/**
@@ -272,17 +272,18 @@
{ 1800, 1 },
{ 5400, 0 }
};
- ZoneInfo zoneInfo = createZoneInfo(transitions, types, timeFromSeconds(-1) /* currentTime */);
+ ZoneInfoData zoneInfoData = createZoneInfoData(transitions, types,
+ timeFromSeconds(-1) /* currentTime */);
- assertFalse("Shouldn't use DST but does", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, offsetFromSeconds(0));
+ assertFalse("Shouldn't use DST but does", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, offsetFromSeconds(0));
// Now create one a few milliseconds after the DST transition to make sure that rounding
// errors don't cause a problem.
- zoneInfo = createZoneInfo(transitions, types, timeFromSeconds(-2000).plusMillis(5));
+ zoneInfoData = createZoneInfoData(transitions, types, timeFromSeconds(-2000).plusMillis(5));
- assertFalse("Shouldn't use DST but does", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, offsetFromSeconds(0));
+ assertFalse("Shouldn't use DST but does", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, offsetFromSeconds(0));
}
/**
@@ -301,17 +302,17 @@
{ 1800, 1 },
{ 5400, 0 }
};
- ZoneInfo zoneInfo = createZoneInfo(transitions, types, timeFromSeconds(4700));
+ ZoneInfoData zoneInfoData = createZoneInfoData(transitions, types, timeFromSeconds(4700));
- assertFalse("Shouldn't use DST but does", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, offsetFromSeconds(0));
+ assertFalse("Shouldn't use DST but does", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, offsetFromSeconds(0));
// Now create one a few milliseconds after the DST transition to make sure that rounding
// errors don't cause a problem.
- zoneInfo = createZoneInfo(transitions, types, timeFromSeconds(4000).plusMillis(5));
+ zoneInfoData = createZoneInfoData(transitions, types, timeFromSeconds(4000).plusMillis(5));
- assertFalse("Shouldn't use DST but does", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, offsetFromSeconds(0));
+ assertFalse("Shouldn't use DST but does", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, offsetFromSeconds(0));
}
/**
@@ -356,15 +357,15 @@
long[][] transitions = {
{ timeToSeconds(firstRealTransitionTime), 2 /* type 2 */ },
};
- ZoneInfo oldZoneInfo = createZoneInfo(transitions, types, currentTime);
- assertRawOffset(oldZoneInfo, type2Offset);
+ ZoneInfoData oldZoneInfoData = createZoneInfoData(transitions, types, currentTime);
+ assertRawOffset(oldZoneInfoData, type2Offset);
// We use the first non-DST type for times before the first transition.
- assertOffsetAt(oldZoneInfo, type0Offset, before32BitTime);
- assertOffsetAt(oldZoneInfo, type0Offset, earlyTimes);
+ assertOffsetAt(oldZoneInfoData, type0Offset, before32BitTime);
+ assertOffsetAt(oldZoneInfoData, type0Offset, earlyTimes);
// This is after the first transition, so type 2.
- assertOffsetAt(oldZoneInfo, type2Offset, afterFirstRealTransitionTimes);
+ assertOffsetAt(oldZoneInfoData, type2Offset, afterFirstRealTransitionTimes);
}
// Simulation a zone where there is an explicit transition at Integer.MIN_VALUE seconds. This
@@ -374,17 +375,17 @@
{ Integer.MIN_VALUE, 1 /* type 1 */ },
{ timeToSeconds(firstRealTransitionTime), 2 /* type 2 */ },
};
- ZoneInfo newZoneInfo = createZoneInfo(transitions, types, currentTime);
- assertRawOffset(newZoneInfo, type2Offset);
+ ZoneInfoData newZoneInfoData = createZoneInfoData(transitions, types, currentTime);
+ assertRawOffset(newZoneInfoData, type2Offset);
// We use the first non-DST type for times before the first transition.
- assertOffsetAt(newZoneInfo, type0Offset, before32BitTime);
+ assertOffsetAt(newZoneInfoData, type0Offset, before32BitTime);
// After the first transition, so type 1.
- assertOffsetAt(newZoneInfo, type1Offset, earlyTimes);
+ assertOffsetAt(newZoneInfoData, type1Offset, earlyTimes);
// This is after the second transition, so type 2.
- assertOffsetAt(newZoneInfo, type2Offset, afterFirstRealTransitionTimes);
+ assertOffsetAt(newZoneInfoData, type2Offset, afterFirstRealTransitionTimes);
}
}
@@ -418,8 +419,8 @@
{ 1000, 0 },
{ 2000, 1 },
};
- ZoneInfo oldZoneInfo = createZoneInfo(transitions, types, currentTime);
- assertOffsetAt(oldZoneInfo, expectedLateOffset, timesToCheck);
+ ZoneInfoData oldZoneInfoData = createZoneInfoData(transitions, types, currentTime);
+ assertOffsetAt(oldZoneInfoData, expectedLateOffset, timesToCheck);
}
// Create a simulation of a zone where there is an explicit transition at Integer.MAX_VALUE
@@ -430,13 +431,13 @@
{ 2000, 1 },
{ Integer.MAX_VALUE, 1}, // The extra transition.
};
- ZoneInfo newZoneInfo = createZoneInfo(transitions, types, currentTime);
- assertOffsetAt(newZoneInfo, expectedLateOffset, timesToCheck);
+ ZoneInfoData newZoneInfoData = createZoneInfoData(transitions, types, currentTime);
+ assertOffsetAt(newZoneInfoData, expectedLateOffset, timesToCheck);
}
}
/**
- * Checks to make sure that ZoneInfo can handle up to 256 types.
+ * Checks to make sure that ZoneInfoData can handle up to 256 types.
*/
public void testReadTimeZone_MaxTypeCount() throws Exception {
long[][] transitions = {
@@ -448,23 +449,23 @@
Arrays.fill(types, new int[2]);
types[255] = new int[] { 3600, 0 };
- ZoneInfo zoneInfo = createZoneInfo(getName(), transitions, types,
+ ZoneInfoData zoneInfoData = createZoneInfoData(getName(), transitions, types,
timeFromSeconds(Integer.MIN_VALUE));
- assertFalse("Shouldn't use DST but does", zoneInfo.useDaylightTime());
- assertDSTSavings(zoneInfo, offsetFromSeconds(0));
+ assertFalse("Shouldn't use DST but does", zoneInfoData.useDaylightTime());
+ assertDSTSavings(zoneInfoData, offsetFromSeconds(0));
- // Make sure that WallTime works properly with a ZoneInfo with 256 types.
- ZoneInfo.WallTime wallTime = new ZoneInfo.WallTime();
- wallTime.localtime(0, zoneInfo);
- wallTime.mktime(zoneInfo);
+ // Make sure that WallTime works properly with a ZoneInfoData with 256 types.
+ ZoneInfoData.WallTime wallTime = new ZoneInfoData.WallTime();
+ wallTime.localtime(0, zoneInfoData);
+ wallTime.mktime(zoneInfoData);
}
/**
* Create an instance for every available time zone for which we have data to ensure that they
* can all be handled correctly.
*
- * <p>This is to ensure that ZoneInfo can read all time zone data without failing, it doesn't
+ * <p>This is to ensure that ZoneInfoData can read all time zone data without failing, it doesn't
* check that it reads it correctly or that the data itself is correct. This is a sanity test
* to ensure that any additional checks added to the code that reads the data source and
* creates the {@link ZoneInfo} instances does not prevent any of the time zones being loaded.
@@ -476,12 +477,12 @@
for (String id : availableIDs) {
BufferIterator bufferIterator = instance.getBufferIterator(id);
- // Create a ZoneInfo at the earliest possible time to allow us to use the
+ // Create a ZoneInfoData at the earliest possible time to allow us to use the
// useDaylightTime() method to check whether it ever has or ever will support daylight
// savings time.
- ZoneInfo zoneInfo = ZoneInfo.readTimeZone(id, bufferIterator, Long.MIN_VALUE);
- assertNotNull("TimeZone " + id + " was not created", zoneInfo);
- assertEquals(id, zoneInfo.getID());
+ ZoneInfoData zoneInfoData = ZoneInfoData.readTimeZone(id, bufferIterator, Long.MIN_VALUE);
+ assertNotNull("TimeZone " + id + " was not created", zoneInfoData);
+ assertEquals(id, zoneInfoData.getID());
}
}
@@ -489,7 +490,7 @@
ZoneInfoTestHelper.ZicDataBuilder builder =
new ZoneInfoTestHelper.ZicDataBuilder()
.initializeToValid();
- assertNotNull(createZoneInfo(getName(), Instant.now(), builder.build()));
+ assertNotNull(createZoneInfoData(getName(), Instant.now(), builder.build()));
}
public void testReadTimeZone_BadMagic() {
@@ -498,13 +499,13 @@
.initializeToValid()
.setMagic(0xdeadbeef); // Bad magic.
try {
- createZoneInfo(getName(), Instant.now(), builder.build());
+ createZoneInfoData(getName(), Instant.now(), builder.build());
fail();
} catch (IOException expected) {}
}
/**
- * Checks to make sure that ZoneInfo rejects more than 256 types.
+ * Checks to make sure that ZoneInfoData rejects more than 256 types.
*/
public void testReadTimeZone_TooManyTypes() {
int typeCount = 257; // Max types allowed is 256
@@ -517,14 +518,14 @@
.setTransitionsAndTypes(transitions, types);
byte[] bytes = builder.build();
try {
- createZoneInfo(getName(), Instant.now(), bytes);
+ createZoneInfoData(getName(), Instant.now(), bytes);
fail("Did not detect too many types");
} catch (IOException expected) {
}
}
/**
- * Checks to make sure that ZoneInfo rejects more than 2000 transitions.
+ * Checks to make sure that ZoneInfoData rejects more than 2000 transitions.
*/
public void testReadTimeZone_TooManyTransitions() {
int typeCount = 5;
@@ -537,7 +538,7 @@
.setTransitionsAndTypes(transitions, types);
byte[] bytes = builder.build();
try {
- createZoneInfo(getName(), Instant.now(), bytes);
+ createZoneInfoData(getName(), Instant.now(), bytes);
fail("Did not detect too many transitions");
} catch (IOException expected) {
}
@@ -561,7 +562,7 @@
byte[] bytes = builder.build();
try {
- createZoneInfo(getName(), Instant.now(), bytes);
+ createZoneInfoData(getName(), Instant.now(), bytes);
fail();
} catch (IOException expected) {
}
@@ -585,7 +586,7 @@
byte[] bytes = builder.build();
try {
- createZoneInfo(getName(), Instant.now(), bytes);
+ createZoneInfoData(getName(), Instant.now(), bytes);
fail();
} catch (IOException expected) {
}
@@ -609,69 +610,30 @@
byte[] bytes = builder.build();
try {
- createZoneInfo(getName(), Instant.now(), bytes);
+ createZoneInfoData(getName(), Instant.now(), bytes);
fail();
} catch (IOException expected) {
}
}
- /**
- * Checks that we can read the serialized form of a {@link ZoneInfo} created in pre-OpenJDK
- * AOSP.
- *
- * <p>One minor difference is that in pre-OpenJDK {@link ZoneInfo#mDstSavings} can be non-zero
- * even if {@link ZoneInfo#mUseDst} was false. That was not visible externally (except through
- * the {@link ZoneInfo#toString()} method) as the {@link ZoneInfo#getDSTSavings()} would check
- * {@link ZoneInfo#mUseDst} and if it was false then would return 0. This checks to make sure
- * that is handled properly. See {@link ZoneInfo#readObject(ObjectInputStream)}.
- */
- public void testReadSerialized() throws Exception {
- ZoneInfo zoneInfoRead;
- try (InputStream is = getClass().getResourceAsStream("ZoneInfoTest_ZoneInfo.golden.ser");
- ObjectInputStream ois = new ObjectInputStream(is)) {
- Object object = ois.readObject();
- assertTrue("Not a ZoneInfo instance", object instanceof ZoneInfo);
- zoneInfoRead = (ZoneInfo) object;
- }
-
- long[][] transitions = {
- { -5000, 0 },
- { -2000, 1 },
- { -500, 0 },
- { 0, 2 },
- };
- int[][] types = {
- { 3600, 0 },
- { 1800, 1 },
- { 5400, 0 }
- };
- ZoneInfo zoneInfoCreated = createZoneInfo(
- "test", transitions, types, timeFromSeconds(-1));
-
- assertEquals("Read ZoneInfo does not match created one", zoneInfoCreated, zoneInfoRead);
- assertEquals("useDaylightTime() mismatch",
- zoneInfoCreated.useDaylightTime(), zoneInfoRead.useDaylightTime());
- assertEquals("getDSTSavings() mismatch",
- zoneInfoCreated.getDSTSavings(), zoneInfoRead.getDSTSavings());
+ private static void assertRawOffset(ZoneInfoData zoneInfoData, Duration expectedOffset) {
+ assertEquals(expectedOffset.toMillis(), zoneInfoData.getRawOffset());
}
- private static void assertRawOffset(ZoneInfo zoneInfo, Duration expectedOffset) {
- assertEquals(expectedOffset.toMillis(), zoneInfo.getRawOffset());
+ private static void assertDSTSavings(ZoneInfoData zoneInfoData, Duration expectedDSTSavings) {
+ assertEquals(expectedDSTSavings.toMillis(), zoneInfoData.getDSTSavings());
}
- private static void assertDSTSavings(ZoneInfo zoneInfo, Duration expectedDSTSavings) {
- assertEquals(expectedDSTSavings.toMillis(), zoneInfo.getDSTSavings());
- }
-
- private static void assertInDaylightTime(ZoneInfo zoneInfo, Instant time, boolean expectedValue) {
- assertEquals(expectedValue, zoneInfo.inDaylightTime(new Date(time.toEpochMilli())));
+ private static void assertInDaylightTime(ZoneInfoData zoneInfoData, Instant time,
+ boolean expectedValue) {
+ assertEquals(expectedValue, zoneInfoData.inDaylightTime(new Date(time.toEpochMilli())));
}
private static void assertOffsetAt(
- ZoneInfo zoneInfo, Duration expectedOffset, Instant... times) {
+ ZoneInfoData zoneInfoData, Duration expectedOffset, Instant... times) {
for (Instant time : times) {
assertEquals("Unexpected offset at " + time,
- expectedOffset.toMillis(), zoneInfo.getOffset(time.toEpochMilli()));
+ expectedOffset.toMillis(), zoneInfoData.getOffset(time.toEpochMilli()));
}
}
@@ -695,29 +657,29 @@
return (int) seconds;
}
- private ZoneInfo createZoneInfo(long[][] transitions, int[][] types)
+ private ZoneInfoData createZoneInfoData(long[][] transitions, int[][] types)
throws Exception {
- return createZoneInfo(getName(), transitions, types, Instant.now());
+ return createZoneInfoData(getName(), transitions, types, Instant.now());
}
- private ZoneInfo createZoneInfo(long[][] transitions, int[][] types, Instant currentTime)
+ private ZoneInfoData createZoneInfoData(long[][] transitions, int[][] types, Instant currentTime)
throws Exception {
- return createZoneInfo(getName(), transitions, types, currentTime);
+ return createZoneInfoData(getName(), transitions, types, currentTime);
}
- private ZoneInfo createZoneInfo(String name, long[][] transitions, int[][] types,
+ private ZoneInfoData createZoneInfoData(String name, long[][] transitions, int[][] types,
Instant currentTime) throws Exception {
ZoneInfoTestHelper.ZicDataBuilder builder =
new ZoneInfoTestHelper.ZicDataBuilder()
.setTransitionsAndTypes(transitions, types);
- return createZoneInfo(name, currentTime, builder.build());
+ return createZoneInfoData(name, currentTime, builder.build());
}
- private static ZoneInfo createZoneInfo(String name, Instant currentTime, byte[] bytes)
+ private static ZoneInfoData createZoneInfoData(String name, Instant currentTime, byte[] bytes)
throws IOException {
ByteBufferIterator bufferIterator = new ByteBufferIterator(ByteBuffer.wrap(bytes));
- return ZoneInfo.readTimeZone(
+ return ZoneInfoData.readTimeZone(
"TimeZone for '" + name + "'", bufferIterator, currentTime.toEpochMilli());
}
diff --git a/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDbTest.java b/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDbTest.java
index 48eb286..a02ad84 100644
--- a/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDbTest.java
+++ b/android_icu4j/testing/src/com/android/i18n/test/timezone/ZoneInfoDbTest.java
@@ -14,19 +14,21 @@
* limitations under the License.
*/
-package libcore.libcore.timezone;
+package com.android.i18n.test.timezone;
+import static com.android.i18n.timezone.ZoneInfoDb.SIZEOF_INDEX_ENTRY;
+
+import android.icu.testsharding.MainTestShard;
+import android.icu.util.TimeZone;
+import com.android.i18n.timezone.TimeZoneDataFiles;
+import com.android.i18n.timezone.ZoneInfoData;
+import com.android.i18n.timezone.ZoneInfoDb;
import java.io.File;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;
-
-import libcore.timezone.TimeZoneDataFiles;
import libcore.timezone.testing.ZoneInfoTestHelper;
-import libcore.util.ZoneInfo;
-import libcore.timezone.ZoneInfoDb;
-import static libcore.timezone.ZoneInfoDb.SIZEOF_INDEX_ENTRY;
-
+@MainTestShard
public class ZoneInfoDbTest extends junit.framework.TestCase {
// The base tzdata file, always present on a device.
@@ -213,20 +215,16 @@
}
}
- // Confirms any caching that exists correctly handles TimeZone mutability.
+ // Confirms any caching that exists correctly handles ZoneInfoData mutability.
public void testMakeTimeZone_timeZoneMutability() throws Exception {
try (ZoneInfoDb data = ZoneInfoDb.loadTzData(TZDATA_FILE)) {
String tzId = "Europe/London";
- ZoneInfo first = data.makeTimeZone(tzId);
- ZoneInfo second = data.makeTimeZone(tzId);
+ ZoneInfoData first = data.makeZoneInfoData(tzId);
+ ZoneInfoData second = data.makeZoneInfoData(tzId);
assertNotSame(first, second);
assertTrue(first.hasSameRules(second));
- first.setID("Not Europe/London");
-
- assertFalse(first.getID().equals(second.getID()));
-
first.setRawOffset(3600);
assertFalse(first.getRawOffset() == second.getRawOffset());
}
@@ -234,14 +232,14 @@
public void testMakeTimeZone_notFound() throws Exception {
try (ZoneInfoDb data = ZoneInfoDb.loadTzData(TZDATA_FILE)) {
- assertNull(data.makeTimeZone("THIS_TZ_DOES_NOT_EXIST"));
+ assertNull(data.makeZoneInfoData("THIS_TZ_DOES_NOT_EXIST"));
assertFalse(data.hasTimeZone("THIS_TZ_DOES_NOT_EXIST"));
}
}
public void testMakeTimeZone_found() throws Exception {
try (ZoneInfoDb data = ZoneInfoDb.loadTzData(TZDATA_FILE)) {
- assertNotNull(data.makeTimeZone("Europe/London"));
+ assertNotNull(data.makeZoneInfoData("Europe/London"));
assertTrue(data.hasTimeZone("Europe/London"));
}
}
diff --git a/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/BasicLruCacheTest.java b/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/BasicLruCacheTest.java
index 707fdda..8d45083 100644
--- a/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/BasicLruCacheTest.java
+++ b/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/BasicLruCacheTest.java
@@ -14,16 +14,13 @@
* limitations under the License.
*/
-package libcore.libcore.util;
+package com.android.i18n.test.timezone.internal;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
+import android.icu.testsharding.MainTestShard;
+import com.android.i18n.timezone.internal.BasicLruCache;
import junit.framework.TestCase;
-import libcore.util.BasicLruCache;
-
+@MainTestShard
public final class BasicLruCacheTest extends TestCase {
public void testCreateOnCacheMiss() {
@@ -68,64 +65,8 @@
BasicLruCache<String, String> cache = new BasicLruCache<String, String>(1);
cache.put("a", "A");
cache.put("b", "B");
- assertSnapshot(cache, "b", "B");
}
- public void testEntryEvictedWhenFull() {
- List<String> expectedEvictionLog = new ArrayList<String>();
- final List<String> evictionLog = new ArrayList<String>();
- BasicLruCache<String, String> cache = new BasicLruCache<String, String>(3) {
- @Override protected void entryEvicted(String key, String value) {
- evictionLog.add(key + "=" + value);
- }
- };
-
- cache.put("a", "A");
- cache.put("b", "B");
- cache.put("c", "C");
- assertEquals(expectedEvictionLog, evictionLog);
-
- cache.put("d", "D");
- expectedEvictionLog.add("a=A");
- assertEquals(expectedEvictionLog, evictionLog);
- }
-
- /**
- * Replacing the value for a key doesn't cause an eviction but it does bring
- * the replaced entry to the front of the queue.
- */
- public void testPutDoesNotCauseEviction() {
- final List<String> evictionLog = new ArrayList<String>();
- List<String> expectedEvictionLog = new ArrayList<String>();
- BasicLruCache<String, String> cache = new BasicLruCache<String, String>(3) {
- @Override protected void entryEvicted(String key, String value) {
- evictionLog.add(key + "=" + value);
- }
- };
-
- cache.put("a", "A");
- cache.put("b", "B");
- cache.put("c", "C");
- cache.put("b", "B2");
- assertEquals(expectedEvictionLog, evictionLog);
- assertSnapshot(cache, "a", "A", "c", "C", "b", "B2");
- }
-
- public void testEvictAll() {
- final List<String> evictionLog = new ArrayList<String>();
- BasicLruCache<String, String> cache = new BasicLruCache<String, String>(10) {
- @Override protected void entryEvicted(String key, String value) {
- evictionLog.add(key + "=" + value);
- }
- };
-
- cache.put("a", "A");
- cache.put("b", "B");
- cache.put("c", "C");
- cache.evictAll();
- assertSnapshot(cache);
- assertEquals(Arrays.asList("a=A", "b=B", "c=C"), evictionLog);
- }
private BasicLruCache<String, String> newCreatingCache() {
return new BasicLruCache<String, String>(3) {
@@ -134,15 +75,4 @@
}
};
}
-
- private <T> void assertSnapshot(BasicLruCache<T, T> cache, T... keysAndValues) {
- List<T> actualKeysAndValues = new ArrayList<T>();
- for (Map.Entry<T, T> entry : cache.snapshot().entrySet()) {
- actualKeysAndValues.add(entry.getKey());
- actualKeysAndValues.add(entry.getValue());
- }
-
- // assert using lists because order is important for LRUs
- assertEquals(Arrays.asList(keysAndValues), actualKeysAndValues);
- }
}
diff --git a/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/MemoryMappedFileTest.java b/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/MemoryMappedFileTest.java
index 1936ea7..a018f41 100644
--- a/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/MemoryMappedFileTest.java
+++ b/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/MemoryMappedFileTest.java
@@ -14,13 +14,13 @@
* limitations under the License
*/
-package libcore.libcore.io;
+package com.android.i18n.test.timezone.internal;
-import junit.framework.TestCase;
-
+import android.icu.testsharding.MainTestShard;
import android.system.ErrnoException;
import android.system.OsConstants;
-
+import com.android.i18n.timezone.internal.BufferIterator;
+import com.android.i18n.timezone.internal.MemoryMappedFile;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
@@ -28,10 +28,9 @@
import java.nio.IntBuffer;
import java.util.Arrays;
import java.util.function.Function;
-import libcore.io.BufferIterator;
-import libcore.io.MemoryMappedFile;
-import libcore.testing.io.TestIoUtils;
+import junit.framework.TestCase;
+@MainTestShard
public class MemoryMappedFileTest extends TestCase {
private File tempDir;
diff --git a/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/MemoryTest.java b/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/MemoryTest.java
index 80ff4ea..ad4a279 100644
--- a/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/MemoryTest.java
+++ b/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/MemoryTest.java
@@ -15,14 +15,15 @@
* limitations under the License.
*/
-package libcore.libcore.io;
+package com.android.i18n.test.timezone.internal;
+import android.icu.testsharding.MainTestShard;
+import com.android.i18n.timezone.internal.Memory;
import dalvik.system.VMRuntime;
import java.util.Arrays;
import junit.framework.TestCase;
-import libcore.io.Memory;
-
+@MainTestShard
public class MemoryTest extends TestCase {
public void testSetIntArray() {
int[] values = { 3, 7, 31, 127, 8191, 131071, 524287, 2147483647 };
diff --git a/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/TestIoUtils.java b/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/TestIoUtils.java
index 34a2cf7..e72efdc 100644
--- a/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/TestIoUtils.java
+++ b/android_icu4j/testing/src/com/android/i18n/test/timezone/internal/TestIoUtils.java
@@ -14,28 +14,20 @@
* limitations under the License.
*/
-package libcore.testing.io;
+package com.android.i18n.test.timezone.internal;
+import android.icu.testsharding.MainTestShard;
import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Paths;
import java.util.Random;
+
+@MainTestShard
public class TestIoUtils {
private final static Random random = new Random();
private TestIoUtils() {}
/**
- * Returns the contents of 'path' as a string. The contents are assumed to be UTF-8.
- */
- public static String readFileAsString(String absolutePath) throws IOException {
- return new String(Files.readAllBytes(Paths.get(absolutePath)), StandardCharsets.UTF_8);
- }
-
- /**
* Creates a unique new temporary directory under "java.io.tmpdir".
*/
public static File createTemporaryDirectory(String prefix) {