Merge "Reference core-test-rules in MtsConscryptTestCases"
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index e5e2a69..6765907 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -223,7 +223,10 @@
installable: false,
- plugins: ["compat-changeid-annotation-processor"],
+ plugins: [
+ "compat-changeid-annotation-processor",
+ "unsupportedappusage-annotation-processor",
+ ],
}
platform_compat_config {
@@ -379,6 +382,7 @@
sdk_version: "none",
system_modules: "core-all-system-modules",
patch_module: "java.base",
+ plugins: ["unsupportedappusage-annotation-processor"],
}
//
@@ -490,6 +494,7 @@
"//frameworks/base/location/tests/locationtests",
"//frameworks/base/core/tests/coretests",
"//frameworks/base/wifi/tests",
+ "//cts/tests/tests/util",
],
hostdex: true,
srcs: [
diff --git a/NativeCode.bp b/NativeCode.bp
index 9619420..2041a92 100644
--- a/NativeCode.bp
+++ b/NativeCode.bp
@@ -92,6 +92,7 @@
name: "libandroidio",
visibility: [
"//art/build/apex",
+ "//art/build/sdk",
"//external/conscrypt",
],
apex_available: [
@@ -214,11 +215,17 @@
srcs: [
"luni/src/test/native/libcore_dalvik_system_JniTest.cpp",
+ "luni/src/test/native/libcore_libcore_icu_LocaleDataTest.cpp",
"luni/src/test/native/libcore_java_io_FileTest.cpp",
"luni/src/test/native/libcore_java_lang_ThreadTest.cpp",
"luni/src/test/native/libcore_java_nio_BufferTest.cpp",
"luni/src/test/native/libcore_libcore_util_NativeAllocationRegistryTest.cpp",
],
+ shared_libs: [
+ "libicui18n",
+ "libicuuc",
+ "liblog",
+ ],
target: {
android: {
shared_libs: ["libnativehelper_compat_libc++"],
@@ -228,6 +235,13 @@
},
},
+ cflags: [
+ // -DANDROID_LINK_SHARED_ICU4C to enable access to the full ICU4C.
+ // See external/icu/android_icu4c/include/uconfig_local.h
+ // for more information.
+ "-DANDROID_LINK_SHARED_ICU4C",
+ ],
+
strip: {
keep_symbols: true,
},
diff --git a/TEST_MAPPING b/TEST_MAPPING
index f8c149d..8c0baae 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -1,7 +1,90 @@
{
"presubmit": [
{
- "name": "CtsSaxTestCases"
+ "name": "CtsLibcoreTestCases",
+ "options": [
+ {
+ "exclude-filter": "com.android.org.conscrypt.java.security.AlgorithmParameterGeneratorTestDH"
+ },
+ {
+ "exclude-filter": "com.android.org.conscrypt.java.security.KeyPairGeneratorTest"
+ },
+ {
+ "exclude-filter": "com.android.org.conscrypt.java.security.SignatureTest"
+ },
+ {
+ "exclude-filter": "com.android.org.conscrypt.javax.crypto.CipherBasicsTest"
+ },
+ {
+ "exclude-filter": "com.android.org.conscrypt.javax.net.ssl.KeyManagerFactoryTest"
+ },
+ {
+ "exclude-filter": "com.android.org.conscrypt.javax.net.ssl.SSLSocketVersionCompatibilityTest"
+ },
+ {
+ "exclude-filter": "libcore.java.lang.OldRuntimeTest"
+ },
+ {
+ "exclude-filter": "libcore.java.lang.OldThreadTest"
+ },
+ {
+ "exclude-filter": "libcore.java.lang.ref.FinalizeTest"
+ },
+ {
+ "exclude-filter": "libcore.java.math.BigIntegerTest"
+ },
+ {
+ "exclude-filter": "libcore.java.net.ConcurrentCloseTest"
+ },
+ {
+ "exclude-filter": "libcore.java.net.OldSocketTest"
+ },
+ {
+ "exclude-filter": "libcore.java.net.URLConnectionTest"
+ },
+ {
+ "exclude-filter": "libcore.java.nio.channels.DatagramChannelMulticastTest"
+ },
+ {
+ "exclude-filter": "libcore.libcore.net.NetworkSecurityPolicyTest"
+ },
+ {
+ "exclude-filter": "libcore.libcore.util.NativeAllocationRegistryTest"
+ },
+ {
+ "exclude-filter": "org.apache.harmony.logging.tests.java.util.logging.SocketHandlerTest"
+ },
+ {
+ "exclude-filter": "org.apache.harmony.tests.java.lang.ObjectTest"
+ },
+ {
+ "exclude-filter": "org.apache.harmony.tests.java.lang.ProcessManagerTest"
+ },
+ {
+ "exclude-filter": "org.apache.harmony.tests.java.math.OldBigIntegerTest"
+ },
+ {
+ "exclude-filter": "org.apache.harmony.tests.java.net.InetAddressThreadTest"
+ },
+ {
+ "exclude-filter": "org.apache.harmony.tests.java.nio.channels.DatagramChannelTest"
+ },
+ {
+ "exclude-filter": "org.apache.harmony.tests.java.util.ScannerTest"
+ },
+ {
+ "exclude-filter": "org.apache.harmony.tests.java.util.TimerTest"
+ },
+ {
+ "exclude-filter": "org.apache.harmony.tests.java.util.WeakHashMapTest"
+ },
+ {
+ "exclude-filter": "org.apache.harmony.tests.javax.net.ssl.SSLSessionTest"
+ },
+ {
+ "exclude-filter": "tests.java.sql.StressTest"
+ }
+ ]
}
]
-}
+}
\ No newline at end of file
diff --git a/benchmarks/src/benchmarks/LocaleDataBenchmark.java b/benchmarks/src/benchmarks/LocaleDataBenchmark.java
new file mode 100644
index 0000000..adf6768
--- /dev/null
+++ b/benchmarks/src/benchmarks/LocaleDataBenchmark.java
@@ -0,0 +1,40 @@
+/*
+ * 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 benchmarks;
+
+import com.google.caliper.BeforeExperiment;
+import com.google.caliper.Benchmark;
+import java.util.Locale;
+import libcore.icu.LocaleData;
+
+public final class LocaleDataBenchmark {
+ private static final Locale[] TEST_LOCALES = new Locale[] {
+ Locale.forLanguageTag("en-US"),
+ Locale.forLanguageTag("jp-JP"),
+ Locale.forLanguageTag("es-419"),
+ Locale.forLanguageTag("ar-EG"),
+ Locale.forLanguageTag("zh-CN"),
+ };
+
+ public void timeInitLocaleData(int reps) {
+ for (int rep = 0; rep < reps; ++rep) {
+ for (Locale locale : TEST_LOCALES) {
+ LocaleData.initLocaleData(locale);
+ }
+ }
+ }
+}
diff --git a/dalvik/src/main/java/dalvik/system/ZygoteHooks.java b/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
index 0339b4d..475acd9 100644
--- a/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
+++ b/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
@@ -21,6 +21,7 @@
import android.icu.util.ULocale;
import java.io.File;
+import java.io.FileDescriptor;
/**
* Provides hooks for the zygote to call back into the runtime to perform
@@ -67,6 +68,11 @@
public static void onEndPreload() {
// All cache references created by ICU from this point will be soft.
CacheValue.setStrength(CacheValue.Strength.SOFT);
+
+ // Clone standard descriptors as originals closed / rebound during zygote post fork.
+ FileDescriptor.in.cloneForFork();
+ FileDescriptor.out.cloneForFork();
+ FileDescriptor.err.cloneForFork();
}
/**
diff --git a/expectations/virtualdeviceknownfailures.txt b/expectations/virtualdeviceknownfailures.txt
index 756aa53..4ab4074 100644
--- a/expectations/virtualdeviceknownfailures.txt
+++ b/expectations/virtualdeviceknownfailures.txt
@@ -24,15 +24,7 @@
},
{
description: "multicast not supported in virtual device testing infra",
- names: ["org.apache.harmony.tests.java.net.MulticastSocketTest#test_joinGroupLjava_net_InetAddress_IPv4",
- "org.apache.harmony.tests.java.net.MulticastSocketTest#test_joinGroupLjava_net_InetAddress_IPv6",
- "org.apache.harmony.tests.java.net.MulticastSocketTest#test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4_nullInterface",
- "org.apache.harmony.tests.java.net.MulticastSocketTest#test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6_nullInterface",
- "org.apache.harmony.tests.java.net.MulticastSocketTest#test_leaveGroupLjava_net_InetAddress_IPv4",
- "org.apache.harmony.tests.java.net.MulticastSocketTest#test_sendLjava_net_DatagramPacketB_IPv4",
- "org.apache.harmony.tests.java.net.MulticastSocketTest#test_sendLjava_net_DatagramPacketB_IPv6",
- "org.apache.harmony.tests.java.net.MulticastSocketTest#test_setLoopbackModeSendReceive_IPv4",
- "org.apache.harmony.tests.java.net.MulticastSocketTest#test_setLoopbackModeSendReceive_IPv6",
+ names: ["org.apache.harmony.tests.java.net.MulticastSocketTest",
"libcore.java.net.MulticastSocketTest#testGroupReceiveIPv6",
"libcore.java.nio.channels.DatagramChannelMulticastTest#test_joinAnySource_IPv4",
"libcore.java.nio.channels.DatagramChannelMulticastTest#test_joinAnySource_multicastLoopOption_IPv4",
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
index a24a67b..67eb932 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
@@ -17,6 +17,13 @@
package org.apache.harmony.tests.java.net;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import java.io.IOException;
import java.net.BindException;
import java.net.DatagramPacket;
@@ -32,12 +39,15 @@
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
-import libcore.junit.junit3.TestCaseWithRules;
+
import libcore.junit.util.ResourceLeakageDetector;
+
+import org.junit.Before;
import org.junit.Rule;
import org.junit.rules.TestRule;
+import org.junit.Test;
-public class MulticastSocketTest extends TestCaseWithRules {
+public class MulticastSocketTest {
@Rule
public TestRule guardRule = ResourceLeakageDetector.getRule();
@@ -63,8 +73,8 @@
private NetworkInterface ipv6NetworkInterface;
private boolean supportsMulticast;
- @Override
- protected void setUp() throws Exception {
+ @Before
+ public void setUp() throws Exception {
// The loopback interface isn't actually useful for sending/receiving multicast messages
// but it can be used as a dummy for tests where that does not matter.
loopbackInterface = NetworkInterface.getByInetAddress(InetAddress.getLoopbackAddress());
@@ -104,7 +114,8 @@
ipv4NetworkInterface != null && ipv6NetworkInterface != null);
}
- public void test_Constructor() throws IOException {
+ @Test
+ public void constructor() throws IOException {
if (!supportsMulticast) {
return;
}
@@ -116,7 +127,8 @@
s.close();
}
- public void test_ConstructorI() throws IOException {
+ @Test
+ public void constructorI() throws IOException {
if (!supportsMulticast) {
return;
}
@@ -130,7 +142,8 @@
dup.close();
}
- public void test_getInterface() throws Exception {
+ @Test
+ public void getInterface() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -157,7 +170,8 @@
mss.close();
}
- public void test_getNetworkInterface() throws IOException {
+ @Test
+ public void getNetworkInterface() throws IOException {
if (!supportsMulticast) {
return;
}
@@ -202,7 +216,8 @@
mss.close();
}
- public void test_getTimeToLive() throws Exception {
+ @Test
+ public void getTimeToLive() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -214,7 +229,8 @@
mss.close();
}
- public void test_getTTL() throws Exception {
+ @Test
+ public void getTTL() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -224,14 +240,16 @@
mss.close();
}
- public void test_joinGroupLjava_net_InetAddress_IPv4() throws Exception {
+ @Test
+ public void joinGroupLjava_net_InetAddress_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
test_joinGroupLjava_net_InetAddress(GOOD_IPv4);
}
- public void test_joinGroupLjava_net_InetAddress_IPv6() throws Exception {
+ @Test
+ public void joinGroupLjava_net_InetAddress_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -258,7 +276,8 @@
receivingSocket.close();
}
- public void test_joinGroup_null_null() throws Exception {
+ @Test
+ public void joinGroup_null_null() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -271,7 +290,8 @@
mss.close();
}
- public void test_joinGroup_non_multicast_address_IPv4() throws Exception {
+ @Test
+ public void joinGroup_non_multicast_address_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -284,7 +304,8 @@
mss.close();
}
- public void test_joinGroup_non_multicast_address_IPv6() throws Exception {
+ @Test
+ public void joinGroup_non_multicast_address_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -297,35 +318,39 @@
mss.close();
}
- public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
+ @Test
+ public void joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
throws Exception {
if (!supportsMulticast) {
return;
}
- test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+ check_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
}
- public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
+ @Test
+ public void joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
throws Exception {
if (!supportsMulticast) {
return;
}
- test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+ check_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
}
- public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4_nullInterface()
+ @Test
+ public void joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4_nullInterface()
throws Exception {
- test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(null, GOOD_IPv4, BAD_IPv4);
+ check_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(null, GOOD_IPv4, BAD_IPv4);
}
- public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6_nullInterface()
+ @Test
+ public void joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6_nullInterface()
throws Exception {
- test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(null, GOOD_IPv6, BAD_IPv6);
+ check_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(null, GOOD_IPv6, BAD_IPv6);
}
- private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+ private void check_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
NetworkInterface networkInterface, InetAddress group, InetAddress group2)
throws Exception {
// Create the sending socket and specify the interface to use as needed (otherwise use the
@@ -383,7 +408,8 @@
sendingSocket.close();
}
- public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() throws Exception {
+ @Test
+ public void joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -453,25 +479,27 @@
}
}
- public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv4()
+ @Test
+ public void joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv4()
throws Exception {
if (!supportsMulticast) {
return;
}
- test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
+ check_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
ipv4NetworkInterface, GOOD_IPv4);
}
- public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv6()
+ @Test
+ public void joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv6()
throws Exception {
if (!supportsMulticast) {
return;
}
- test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
+ check_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
ipv6NetworkInterface, GOOD_IPv6);
}
- private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
+ private void check_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
NetworkInterface networkInterface, InetAddress group) throws Exception {
// Validate that we can join the same address on two different interfaces but not on the
// same interface.
@@ -487,21 +515,23 @@
mss.close();
}
- public void test_leaveGroupLjava_net_InetAddress_IPv4() throws Exception {
+ @Test
+ public void leaveGroupLjava_net_InetAddress_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
- test_leaveGroupLjava_net_InetAddress(GOOD_IPv4);
+ check_leaveGroupLjava_net_InetAddress(GOOD_IPv4);
}
- public void test_leaveGroupLjava_net_InetAddress_IPv6() throws Exception {
+ @Test
+ public void leaveGroupLjava_net_InetAddress_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
- test_leaveGroupLjava_net_InetAddress(GOOD_IPv6);
+ check_leaveGroupLjava_net_InetAddress(GOOD_IPv6);
}
- private void test_leaveGroupLjava_net_InetAddress(InetAddress group) throws Exception {
+ private void check_leaveGroupLjava_net_InetAddress(InetAddress group) throws Exception {
String msg = "Hello World";
MulticastSocket mss = new MulticastSocket(0);
InetSocketAddress groupAddress = new InetSocketAddress(group, mss.getLocalPort());
@@ -516,7 +546,8 @@
mss.close();
}
- public void test_leaveGroup_null_null() throws Exception {
+ @Test
+ public void leaveGroup_null_null() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -529,7 +560,8 @@
mss.close();
}
- public void test_leaveGroup_non_multicast_address_IPv4() throws Exception {
+ @Test
+ public void leaveGroup_non_multicast_address_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -542,7 +574,8 @@
mss.close();
}
- public void test_leaveGroup_non_multicast_address_IPv6() throws Exception {
+ @Test
+ public void leaveGroup_non_multicast_address_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -555,25 +588,27 @@
mss.close();
}
- public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
+ @Test
+ public void leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
throws Exception {
if (!supportsMulticast) {
return;
}
- test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+ check_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
}
- public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
+ @Test
+ public void leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
throws Exception {
if (!supportsMulticast) {
return;
}
- test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+ check_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
}
- private void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+ private void check_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
NetworkInterface networkInterface, InetAddress group, InetAddress group2)
throws Exception {
SocketAddress groupSockAddr = null;
@@ -609,21 +644,23 @@
}
}
- public void test_sendLjava_net_DatagramPacketB_IPv4() throws Exception {
+ @Test
+ public void sendLjava_net_DatagramPacketB_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
- test_sendLjava_net_DatagramPacketB(GOOD_IPv4);
+ check_sendLjava_net_DatagramPacketB(GOOD_IPv4);
}
- public void test_sendLjava_net_DatagramPacketB_IPv6() throws Exception {
+ @Test
+ public void sendLjava_net_DatagramPacketB_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
- test_sendLjava_net_DatagramPacketB(GOOD_IPv6);
+ check_sendLjava_net_DatagramPacketB(GOOD_IPv6);
}
- private void test_sendLjava_net_DatagramPacketB(InetAddress group) throws Exception {
+ private void check_sendLjava_net_DatagramPacketB(InetAddress group) throws Exception {
String msg = "Hello World";
MulticastSocket sendingSocket = new MulticastSocket(0);
MulticastSocket receivingSocket = createReceivingSocket(sendingSocket.getLocalPort());
@@ -641,7 +678,8 @@
receivingSocket.close();
}
- public void test_setInterfaceLjava_net_InetAddress() throws Exception {
+ @Test
+ public void setInterfaceLjava_net_InetAddress() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -662,14 +700,16 @@
mss.close();
}
- public void test_setInterface_unbound_address_IPv4() throws Exception {
+ @Test
+ public void setInterface_unbound_address_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
test_setInterface_unbound_address(GOOD_IPv4);
}
- public void test_setInterface_unbound_address_IPv6() throws Exception {
+ @Test
+ public void setInterface_unbound_address_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -687,7 +727,8 @@
mss.close();
}
- public void test_setNetworkInterfaceLjava_net_NetworkInterface_null() throws Exception {
+ @Test
+ public void setNetworkInterfaceLjava_net_NetworkInterface_null() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -701,7 +742,8 @@
mss.close();
}
- public void test_setNetworkInterfaceLjava_net_NetworkInterface_round_trip() throws Exception {
+ @Test
+ public void setNetworkInterfaceLjava_net_NetworkInterface_round_trip() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -713,21 +755,23 @@
mss.close();
}
- public void test_setNetworkInterfaceLjava_net_NetworkInterface_IPv4() throws Exception {
+ @Test
+ public void setNetworkInterfaceLjava_net_NetworkInterface_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
- test_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv4);
+ check_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv4);
}
- public void test_setNetworkInterfaceLjava_net_NetworkInterface_IPv6() throws Exception {
+ @Test
+ public void setNetworkInterfaceLjava_net_NetworkInterface_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
- test_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv6);
+ check_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv6);
}
- private void test_setNetworkInterfaceLjava_net_NetworkInterface(InetAddress group)
+ private void check_setNetworkInterfaceLjava_net_NetworkInterface(InetAddress group)
throws IOException, InterruptedException {
// Set up the receiving socket and join the group.
Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
@@ -761,7 +805,8 @@
}
}
- public void test_setTimeToLiveI() throws Exception {
+ @Test
+ public void setTimeToLiveI() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -773,7 +818,8 @@
mss.close();
}
- public void test_setTTLB() throws Exception {
+ @Test
+ public void setTTLB() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -783,7 +829,8 @@
mss.close();
}
- public void test_ConstructorLjava_net_SocketAddress() throws Exception {
+ @Test
+ public void constructorLjava_net_SocketAddress() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -817,7 +864,8 @@
s.close();
}
- public void test_getLoopbackMode() throws Exception {
+ @Test
+ public void getLoopbackMode() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -829,7 +877,8 @@
assertTrue("should be closed", ms.isClosed());
}
- public void test_setLoopbackModeZ() throws Exception {
+ @Test
+ public void setLoopbackModeZ() throws Exception {
if (!supportsMulticast) {
return;
}
@@ -842,21 +891,23 @@
assertTrue("should be closed", ms.isClosed());
}
- public void test_setLoopbackModeSendReceive_IPv4() throws Exception {
+ @Test
+ public void setLoopbackModeSendReceive_IPv4() throws Exception {
if (!supportsMulticast) {
return;
}
- test_setLoopbackModeSendReceive(GOOD_IPv4);
+ check_setLoopbackModeSendReceive(GOOD_IPv4);
}
- public void test_setLoopbackModeSendReceive_IPv6() throws Exception {
+ @Test
+ public void setLoopbackModeSendReceive_IPv6() throws Exception {
if (!supportsMulticast) {
return;
}
- test_setLoopbackModeSendReceive(GOOD_IPv6);
+ check_setLoopbackModeSendReceive(GOOD_IPv6);
}
- private void test_setLoopbackModeSendReceive(InetAddress group) throws IOException {
+ private void check_setLoopbackModeSendReceive(InetAddress group) throws IOException {
// Test send receive.
final String message = "Hello, world!";
@@ -878,7 +929,8 @@
socket.close();
}
- public void test_setReuseAddressZ() throws Exception {
+ @Test
+ public void setReuseAddressZ() throws Exception {
if (!supportsMulticast) {
return;
}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/org/apache/harmony/kernel/dalvik/ThreadsTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/org/apache/harmony/kernel/dalvik/ThreadsTest.java
index 37c6086..e8f1bc5 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/org/apache/harmony/kernel/dalvik/ThreadsTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/org/apache/harmony/kernel/dalvik/ThreadsTest.java
@@ -81,6 +81,7 @@
public void test_parkFor_3() throws Exception {
CyclicBarrier barrier = new CyclicBarrier(1);
Parker parker = new Parker(barrier, false, 1000);
+ parker.disableRetry();
Thread parkerThread = new Thread(parker);
UNSAFE.unpark(parkerThread);
@@ -123,6 +124,7 @@
public void test_parkUntil_3() throws Exception {
CyclicBarrier barrier = new CyclicBarrier(1);
Parker parker = new Parker(barrier, true, 1000);
+ parker.disableRetry();
Thread parkerThread = new Thread(parker);
UNSAFE.unpark(parkerThread);
@@ -139,6 +141,8 @@
*/
private static class Parker implements Runnable {
+ private static final long NANOS_PER_MILLI = 1_000_000L;
+
private final CyclicBarrier barrier;
/** whether {@link #amount} is milliseconds to wait in an
@@ -146,6 +150,8 @@
* in a relative fashion (<code>false</code>) */
private final boolean absolute;
+ private boolean retryDisabled;
+
/** amount to wait (see above) */
private final long amount;
@@ -153,10 +159,10 @@
private boolean completed;
/** recorded start time */
- private long startMillis;
+ private long startNanos;
/** recorded end time */
- private long endMillis;
+ private long endNanos;
/**
* Construct an instance.
@@ -168,9 +174,17 @@
public Parker(CyclicBarrier barrier, boolean absolute, long parkMillis) {
this.barrier = barrier;
this.absolute = absolute;
-
+ // this.retryDisabled = false;
+ if (parkMillis < 10) {
+ // Doesn't work well with our retry logic, and likely to be flakey.
+ throw new AssertionError("Unexpectedly short park timeout.");
+ }
// Multiply by 1000000 because parkFor() takes nanoseconds.
- this.amount = absolute ? parkMillis : parkMillis * 1000000;
+ this.amount = absolute ? parkMillis : parkMillis * NANOS_PER_MILLI;
+ }
+
+ public void disableRetry() {
+ retryDisabled = true;
}
public void run() {
@@ -181,20 +195,29 @@
}
boolean absolute = this.absolute;
long amount = this.amount;
- long startNanos = System.nanoTime();
+ long startNs = System.nanoTime();
long start = System.currentTimeMillis();
- if (absolute) {
- UNSAFE.park(true, start + amount);
- } else {
- UNSAFE.park(false, amount);
+ for (int i = 0; i < 2; ++i) {
+ if (absolute) {
+ UNSAFE.park(true, start + amount);
+ } else {
+ UNSAFE.park(false, amount);
+ }
+ // park() may wake up spuriously. For our implementation, this
+ // should be unlikely, except there are cases in which the
+ // initial attempt returns immediately. Try a second time, but
+ // only in that case.
+ if (retryDisabled || System.currentTimeMillis() - start > 1L) {
+ break;
+ }
}
- long endNanos = System.nanoTime();
+ long endNs = System.nanoTime();
synchronized (this) {
- startMillis = startNanos / 1000000;
- endMillis = endNanos / 1000000;
+ startNanos = startNs;
+ endNanos = endNs;
completed = true;
notifyAll();
}
@@ -219,25 +242,23 @@
}
}
- return endMillis - startMillis;
+ return (endNanos - startNanos) / NANOS_PER_MILLI;
}
}
/**
- * Asserts that the actual duration is within 10% of the
+ * Asserts that the actual duration is within 150-200 msecs of the
* given expected time.
+ * Observe that small errors in either direction are normal here; for a
+ * number of tests the value will be too small if the Parker thread
+ * starts late, e.g. because it doesn't get a time slice soon enough.
*
* @param expectedMillis the expected duration, in milliseconds
*/
public void assertDurationIsInRange(long expectedMillis) {
- /*
- * Allow a bit more slop for the maximum on "expected
- * instantaneous" results.
- */
- long minimum = (long) ((double) expectedMillis * 0.80);
- long maximum =
- Math.max((long) ((double) expectedMillis * 1.20), 10);
- long waitMillis = Math.max(expectedMillis * 10, 1000);
+ long minimum = Math.max(expectedMillis - 150L, 0L);
+ long maximum = expectedMillis + 200L;
+ long waitMillis = Math.max(expectedMillis * 10L, 1000L);
long duration = getDurationMillis(waitMillis);
if (duration < minimum) {
diff --git a/jsr166-tests/src/test/java/jsr166/JSR166TestCase.java b/jsr166-tests/src/test/java/jsr166/JSR166TestCase.java
index ea6e576..c073f1d 100644
--- a/jsr166-tests/src/test/java/jsr166/JSR166TestCase.java
+++ b/jsr166-tests/src/test/java/jsr166/JSR166TestCase.java
@@ -956,7 +956,7 @@
* Uninteresting threads are filtered out.
*/
static void dumpTestThreads() {
- // Android-change no ThreadMXBean
+ // Android-removed: no ThreadMXBean.
// ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
// System.err.println("------ stacktrace dump start ------");
// for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
@@ -1089,7 +1089,7 @@
* getPolicy/setPolicy.
*/
public void runWithPermissions(Runnable r, Permission... permissions) {
- // Android-changed: no SecurityManager
+ // Android-removed: no SecurityManager.
// SecurityManager sm = System.getSecurityManager();
// if (sm == null) {
// r.run();
@@ -1107,7 +1107,7 @@
*/
public void runWithSecurityManagerWithPermissions(Runnable r,
Permission... permissions) {
- // Android-changed: no SecurityManager
+ // Android-removed: no SecurityManager.
// SecurityManager sm = System.getSecurityManager();
// if (sm == null) {
// Policy savedPolicy = Policy.getPolicy();
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index 970dcc2..482464f 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -28,6 +28,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
+import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
/**
diff --git a/libart/src/main/java/java/lang/DexCache.java b/libart/src/main/java/java/lang/DexCache.java
index f9e3ea3..e35a69d 100644
--- a/libart/src/main/java/java/lang/DexCache.java
+++ b/libart/src/main/java/java/lang/DexCache.java
@@ -39,6 +39,9 @@
* A dex cache holds resolved copies of strings, fields, methods, and classes from the dexfile.
*/
final class DexCache {
+ /** The classloader this dex cache is for. */
+ private ClassLoader classLoader;
+
/** The location of the associated dex file. */
private String location;
@@ -125,4 +128,3 @@
// Only created by the VM.
private DexCache() {}
}
-
diff --git a/luni/src/main/java/libcore/icu/ICU.java b/luni/src/main/java/libcore/icu/ICU.java
index f6e5fed..c23c91f7 100644
--- a/luni/src/main/java/libcore/icu/ICU.java
+++ b/luni/src/main/java/libcore/icu/ICU.java
@@ -373,8 +373,6 @@
private static native String[] getISOLanguagesNative();
private static native String[] getISOCountriesNative();
- static native boolean initLocaleDataNative(String languageTag, LocaleData result);
-
/**
* Takes a BCP-47 language tag (Locale.toLanguageTag()). e.g. en-US, not en_US
*/
diff --git a/luni/src/main/java/libcore/icu/LocaleData.java b/luni/src/main/java/libcore/icu/LocaleData.java
index ea6fe6f..9745bc0 100644
--- a/luni/src/main/java/libcore/icu/LocaleData.java
+++ b/luni/src/main/java/libcore/icu/LocaleData.java
@@ -19,7 +19,13 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.icu.impl.ICUData;
import android.icu.impl.ICUResourceBundle;
+import android.icu.text.DateFormatSymbols;
+import android.icu.text.DecimalFormat;
+import android.icu.text.DecimalFormatSymbols;
+import android.icu.text.NumberFormat;
import android.icu.text.NumberingSystem;
+import android.icu.util.Calendar;
+import android.icu.util.GregorianCalendar;
import android.icu.util.UResourceBundle;
import java.text.DateFormat;
@@ -92,11 +98,9 @@
@libcore.api.CorePlatformApi
public String[] tinyStandAloneWeekdayNames; // "S", ...
- // Used by frameworks/base DateSorter and DateUtils.
- @libcore.api.CorePlatformApi
- public String yesterday; // "Yesterday".
+ // today and tomorrow is only kept for @UnsupportedAppUsage.
+ // Their value is hard-coded, not localized.
@UnsupportedAppUsage
- @libcore.api.CorePlatformApi
public String today; // "Today".
@UnsupportedAppUsage
public String tomorrow; // "Tomorrow".
@@ -144,9 +148,6 @@
public String exponentSeparator;
public String infinity;
public String NaN;
- // Also used by Currency.
- public String currencySymbol;
- public String internationalCurrencySymbol;
// Used by DecimalFormat and NumberFormat.
public String numberPattern;
@@ -155,6 +156,8 @@
public String percentPattern;
private LocaleData() {
+ today = "Today";
+ tomorrow = "Tomorrow";
}
@UnsupportedAppUsage
@@ -241,11 +244,16 @@
throw new AssertionError();
}
- private static LocaleData initLocaleData(Locale locale) {
+ /*
+ * This method is made public for testing
+ */
+ public static LocaleData initLocaleData(Locale locale) {
LocaleData localeData = new LocaleData();
- if (!ICU.initLocaleDataNative(locale.toLanguageTag(), localeData)) {
- throw new AssertionError("couldn't initialize LocaleData for locale " + locale);
- }
+
+ localeData.initializeDateTimePatterns(locale);
+ localeData.initializeDateFormatData(locale);
+ localeData.initializeDecimalFormatData(locale);
+ localeData.initializeCalendarData(locale);
// Libcore localizes pattern separator while ICU doesn't. http://b/112080617
initializePatternSeparator(localeData, locale);
@@ -296,7 +304,7 @@
if (!"latn".equals(nsName)) {
try {
patternSeparator = rb.getStringWithFallback(
- "NumberElements/" + nsName +"/symbols/list");
+ "NumberElements/" + nsName + "/symbols/list");
} catch (MissingResourceException e) {
// Try Latin numbering system later
}
@@ -317,4 +325,123 @@
// Pattern separator in libcore supports single java character only.
localeData.patternSeparator = patternSeparator.charAt(0);
}
-}
+
+ private void initializeDateFormatData(Locale locale) {
+ DateFormatSymbols dfs = new DateFormatSymbols(GregorianCalendar.class, locale);
+
+ longMonthNames = dfs.getMonths(DateFormatSymbols.FORMAT, DateFormatSymbols.WIDE);
+ shortMonthNames = dfs.getMonths(DateFormatSymbols.FORMAT, DateFormatSymbols.ABBREVIATED);
+ tinyMonthNames = dfs.getMonths(DateFormatSymbols.FORMAT, DateFormatSymbols.NARROW);
+ longWeekdayNames = dfs.getWeekdays(DateFormatSymbols.FORMAT, DateFormatSymbols.WIDE);
+ shortWeekdayNames = dfs
+ .getWeekdays(DateFormatSymbols.FORMAT, DateFormatSymbols.ABBREVIATED);
+ tinyWeekdayNames = dfs.getWeekdays(DateFormatSymbols.FORMAT, DateFormatSymbols.NARROW);
+
+ longStandAloneMonthNames = dfs
+ .getMonths(DateFormatSymbols.STANDALONE, DateFormatSymbols.WIDE);
+ shortStandAloneMonthNames = dfs
+ .getMonths(DateFormatSymbols.STANDALONE, DateFormatSymbols.ABBREVIATED);
+ tinyStandAloneMonthNames = dfs
+ .getMonths(DateFormatSymbols.STANDALONE, DateFormatSymbols.NARROW);
+ longStandAloneWeekdayNames = dfs
+ .getWeekdays(DateFormatSymbols.STANDALONE, DateFormatSymbols.WIDE);
+ shortStandAloneWeekdayNames = dfs
+ .getWeekdays(DateFormatSymbols.STANDALONE, DateFormatSymbols.ABBREVIATED);
+ tinyStandAloneWeekdayNames = dfs
+ .getWeekdays(DateFormatSymbols.STANDALONE, DateFormatSymbols.NARROW);
+
+ String[] ampmNarrowStrings = dfs.getAmpmNarrowStrings();
+ narrowAm = ampmNarrowStrings[0];
+ narrowPm = ampmNarrowStrings[1];
+
+ amPm = dfs.getAmPmStrings();
+ eras = dfs.getEras();
+
+ }
+
+ private void initializeDecimalFormatData(Locale locale) {
+ DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale);
+
+ decimalSeparator = dfs.getDecimalSeparator();
+ groupingSeparator = dfs.getGroupingSeparator();
+ patternSeparator = dfs.getPatternSeparator();
+ percent = dfs.getPercentString();
+ perMill = dfs.getPerMillString();
+ monetarySeparator = dfs.getMonetaryDecimalSeparator();
+ minusSign = dfs.getMinusSignString();
+ exponentSeparator = dfs.getExponentSeparator();
+ infinity = dfs.getInfinity();
+ NaN = dfs.getNaN();
+ zeroDigit = dfs.getZeroDigit();
+
+ DecimalFormat df = (DecimalFormat) NumberFormat
+ .getInstance(locale, NumberFormat.NUMBERSTYLE);
+ numberPattern = df.toPattern();
+
+ df = (DecimalFormat) NumberFormat.getInstance(locale, NumberFormat.CURRENCYSTYLE);
+ currencyPattern = df.toPattern();
+
+ df = (DecimalFormat) NumberFormat.getInstance(locale, NumberFormat.PERCENTSTYLE);
+ percentPattern = df.toPattern();
+
+ }
+
+ private void initializeCalendarData(Locale locale) {
+ Calendar calendar = Calendar.getInstance(locale);
+
+ firstDayOfWeek = calendar.getFirstDayOfWeek();
+ minimalDaysInFirstWeek = calendar.getMinimalDaysInFirstWeek();
+ }
+
+ private void initializeDateTimePatterns(Locale locale) {
+ try {
+ ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(
+ ICUData.ICU_BASE_NAME, locale);
+ rb = rb.getWithFallback("calendar/gregorian/DateTimePatterns");
+ fullTimeFormat = getStringOrFirstArrayElement(rb, 0);
+ longTimeFormat = getStringOrFirstArrayElement(rb, 1);
+ mediumTimeFormat = getStringOrFirstArrayElement(rb, 2);
+ shortTimeFormat = getStringOrFirstArrayElement(rb, 3);
+ fullDateFormat = getStringOrFirstArrayElement(rb, 4);
+ longDateFormat = getStringOrFirstArrayElement(rb, 5);
+ mediumDateFormat = getStringOrFirstArrayElement(rb, 6);
+ shortDateFormat = getStringOrFirstArrayElement(rb, 7);
+ } catch (MissingResourceException e) {
+ // Preserve legacy behavior throwing AssertionError for missing resource.
+ throw new AssertionError(e);
+ }
+ }
+
+ private static String getStringOrFirstArrayElement(UResourceBundle rb, int index) {
+ try {
+ UResourceBundle currentBundle = rb.get(index);
+ int type = currentBundle.getType();
+ final String result;
+ switch(type) {
+ case UResourceBundle.STRING:
+ result = currentBundle.getString();
+ break;
+ case UResourceBundle.ARRAY:
+ // In case there is an array, Android currently only cares about the
+ // first string of that array, the rest of the array is used by ICU
+ // for additional data ignored by Android.
+ result = currentBundle.getString(0);
+ break;
+ default:
+ // Preserve legacy behavior of setting null
+ result = null;
+ System.logE(String.format(
+ "Unsupported type when setting String field from ICU resource (type %d)",
+ type)
+ );
+ }
+ return result;
+ } catch (MissingResourceException e) {
+ // Preserve legacy behavior of avoiding throwing for missing resource.
+ System.logE(String.format(
+ "Error setting String field from ICU resource (index %d)", index), e
+ );
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/luni/src/main/java/libcore/io/IoBridge.java b/luni/src/main/java/libcore/io/IoBridge.java
index aa66f14..0554d6d 100644
--- a/luni/src/main/java/libcore/io/IoBridge.java
+++ b/luni/src/main/java/libcore/io/IoBridge.java
@@ -469,16 +469,13 @@
/**
* java.io only throws FileNotFoundException when opening files, regardless of what actually
* went wrong. Additionally, java.io is more restrictive than POSIX when it comes to opening
- * directories: POSIX says read-only is okay, but java.io doesn't even allow that. We also
- * have an Android-specific hack to alter the default permissions.
+ * directories: POSIX says read-only is okay, but java.io doesn't even allow that.
*/
@libcore.api.CorePlatformApi
public static FileDescriptor open(String path, int flags) throws FileNotFoundException {
FileDescriptor fd = null;
try {
- // On Android, we don't want default permissions to allow global access.
- int mode = ((flags & O_ACCMODE) == O_RDONLY) ? 0 : 0600;
- fd = Libcore.os.open(path, flags, mode);
+ fd = Libcore.os.open(path, flags, 0666);
// Posix open(2) fails with EISDIR only if you ask for write permission.
// Java disallows reading directories too.
if (S_ISDIR(Libcore.os.fstat(fd).st_mode)) {
diff --git a/luni/src/main/java/libcore/timezone/CountryTimeZones.java b/luni/src/main/java/libcore/timezone/CountryTimeZones.java
index 4ff8470..3efe927 100644
--- a/luni/src/main/java/libcore/timezone/CountryTimeZones.java
+++ b/luni/src/main/java/libcore/timezone/CountryTimeZones.java
@@ -28,49 +28,13 @@
/**
* Information about a country's time zones.
+ *
* @hide
*/
@libcore.api.CorePlatformApi
public final class CountryTimeZones {
/**
- * The result of lookup up a time zone using offset information (and possibly more).
- * @hide
- */
- @libcore.api.CorePlatformApi
- public static final class OffsetResult {
-
- /** A zone that matches the supplied criteria. See also {@link #isOnlyMatch}. */
- private final TimeZone timeZone;
-
- /** True if there is one match for the supplied criteria */
- private final boolean isOnlyMatch;
-
- public OffsetResult(TimeZone timeZone, boolean isOnlyMatch) {
- this.timeZone = java.util.Objects.requireNonNull(timeZone);
- this.isOnlyMatch = isOnlyMatch;
- }
-
- @libcore.api.CorePlatformApi
- public TimeZone getTimeZone() {
- return timeZone;
- }
-
- @libcore.api.CorePlatformApi
- public boolean isOnlyMatch() {
- return isOnlyMatch;
- }
-
- @Override
- public String toString() {
- return "Result{"
- + "timeZone='" + timeZone + '\''
- + ", isOnlyMatch=" + isOnlyMatch
- + '}';
- }
- }
-
- /**
* A mapping to a time zone ID with some associated metadata.
*
* @hide
@@ -186,6 +150,44 @@
}
}
+ /**
+ * The result of lookup up a time zone using offset information (and possibly more).
+ *
+ * @hide
+ */
+ @libcore.api.CorePlatformApi
+ public static final class OffsetResult {
+
+ /** A zone that matches the supplied criteria. See also {@link #isOnlyMatch}. */
+ private final TimeZone timeZone;
+
+ /** True if there is one match for the supplied criteria */
+ private final boolean isOnlyMatch;
+
+ public OffsetResult(TimeZone timeZone, boolean isOnlyMatch) {
+ this.timeZone = Objects.requireNonNull(timeZone);
+ this.isOnlyMatch = isOnlyMatch;
+ }
+
+ @libcore.api.CorePlatformApi
+ public TimeZone getTimeZone() {
+ return timeZone;
+ }
+
+ @libcore.api.CorePlatformApi
+ public boolean isOnlyMatch() {
+ return isOnlyMatch;
+ }
+
+ @Override
+ public String toString() {
+ return "OffsetResult{"
+ + "timeZone(ID)='" + timeZone.getID() + '\''
+ + ", isOnlyMatch=" + isOnlyMatch
+ + '}';
+ }
+ }
+
private final String countryIso;
private final String defaultTimeZoneId;
/**
@@ -205,7 +207,7 @@
private CountryTimeZones(String countryIso, String defaultTimeZoneId,
boolean defaultTimeZoneBoosted, boolean everUsesUtc,
List<TimeZoneMapping> timeZoneMappings) {
- this.countryIso = java.util.Objects.requireNonNull(countryIso);
+ this.countryIso = Objects.requireNonNull(countryIso);
this.defaultTimeZoneId = defaultTimeZoneId;
this.defaultTimeZoneBoosted = defaultTimeZoneBoosted;
this.everUsesUtc = everUsesUtc;
@@ -260,16 +262,27 @@
}
/**
- * Returns true if the ISO code for the country is a match for the one specified.
+ * Returns true if the ISO code for the country is a case-insensitive match for the one
+ * supplied.
*/
@libcore.api.CorePlatformApi
- public boolean isForCountryCode(String countryIso) {
+ public boolean matchesCountryCode(String countryIso) {
return this.countryIso.equals(normalizeCountryIso(countryIso));
}
/**
- * Returns the default time zone for the country. Can return null in cases when no data is
- * available or the time zone ID provided to
+ * Returns the default time zone ID for the country. Can return {@code null} in cases when no
+ * data is available or the time zone ID provided to
+ * {@link #createValidated(String, String, boolean, boolean, List, String)} was not recognized.
+ */
+ @libcore.api.CorePlatformApi
+ public String getDefaultTimeZoneId() {
+ return defaultTimeZoneId;
+ }
+
+ /**
+ * Returns the default time zone for the country. Can return {@code null} in cases when no data
+ * is available or the time zone ID provided to
* {@link #createValidated(String, String, boolean, boolean, List, String)} was not recognized.
*/
@libcore.api.CorePlatformApi
@@ -287,18 +300,10 @@
}
/**
- * Returns the default time zone ID for the country. Can return null in cases when no data is
- * available or the time zone ID provided to
- * {@link #createValidated(String, String, boolean, boolean, List, String)} was not recognized.
- */
- @libcore.api.CorePlatformApi
- public String getDefaultTimeZoneId() {
- return defaultTimeZoneId;
- }
-
- /**
- * Qualifier for a country's default time zone. {@code true} indicates whether the default
- * would be a good choice <em>generally</em> when there's no other information available.
+ * Qualifier for a country's default time zone. {@code true} indicates that the country's
+ * default time zone would be a good choice <em>generally</em> when there's no UTC offset
+ * information available. This will only be {@code true} in countries with multiple zones where
+ * a large majority of the population is covered by only one of them.
*/
@libcore.api.CorePlatformApi
public boolean isDefaultTimeZoneBoosted() {
@@ -316,59 +321,15 @@
}
/**
- * Returns an immutable, ordered list of time zone mappings for the country in an undefined but
- * "priority" order, filtered so that only "effective" time zone IDs are returned. An
- * "effective" time zone is one that differs from another time zone used in the country after
- * {@code whenMillis}. The list can be empty if there were no zones configured or the configured
- * zone IDs were not recognized.
- */
- @libcore.api.CorePlatformApi
- public List<TimeZoneMapping> getEffectiveTimeZoneMappingsAt(long whenMillis) {
- ArrayList<TimeZoneMapping> filteredList = new ArrayList<>(timeZoneMappings.size());
- for (TimeZoneMapping timeZoneMapping : timeZoneMappings) {
- if (timeZoneMapping.isEffectiveAt(whenMillis)) {
- filteredList.add(timeZoneMapping);
- }
- }
- return Collections.unmodifiableList(filteredList);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- CountryTimeZones that = (CountryTimeZones) o;
- return defaultTimeZoneBoosted == that.defaultTimeZoneBoosted
- && everUsesUtc == that.everUsesUtc
- && countryIso.equals(that.countryIso)
- && Objects.equals(defaultTimeZoneId, that.defaultTimeZoneId)
- && timeZoneMappings.equals(that.timeZoneMappings);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(
- countryIso, defaultTimeZoneId, defaultTimeZoneBoosted, timeZoneMappings,
- everUsesUtc);
- }
-
- @Override
- public String toString() {
- return "CountryTimeZones{"
- + "countryIso='" + countryIso + '\''
- + ", defaultTimeZoneId='" + defaultTimeZoneId + '\''
- + ", defaultTimeZoneBoosted=" + defaultTimeZoneBoosted
- + ", timeZoneMappings=" + timeZoneMappings
- + ", everUsesUtc=" + everUsesUtc
- + '}';
- }
-
- /**
- * Returns true if the country has at least one zone that is the same as UTC at the given time.
+ * Returns {@code true} if the country has at least one time zone that uses UTC at the given
+ * time. This is an efficient check when trying to validate received UTC offset information.
+ * For example, there are situations when a detected zero UTC offset cannot be distinguished
+ * from "no information available" or a corrupted signal. This method is useful because checking
+ * offset information for large countries is relatively expensive but it is generally only the
+ * countries close to the prime meridian that use UTC at <em>any</em> time of the year.
+ *
+ * @param whenMillis the time the offset information is for in milliseconds since the beginning
+ * of the Unix epoch
*/
@libcore.api.CorePlatformApi
public boolean hasUtcZone(long whenMillis) {
@@ -426,6 +387,58 @@
}
/**
+ * Returns an immutable, ordered list of time zone mappings for the country in an undefined but
+ * "priority" order, filtered so that only "effective" time zone IDs are returned. An
+ * "effective" time zone is one that differs from another time zone used in the country after
+ * {@code whenMillis}. The list can be empty if there were no zones configured or the configured
+ * zone IDs were not recognized.
+ */
+ @libcore.api.CorePlatformApi
+ public List<TimeZoneMapping> getEffectiveTimeZoneMappingsAt(long whenMillis) {
+ ArrayList<TimeZoneMapping> filteredList = new ArrayList<>(timeZoneMappings.size());
+ for (TimeZoneMapping timeZoneMapping : timeZoneMappings) {
+ if (timeZoneMapping.isEffectiveAt(whenMillis)) {
+ filteredList.add(timeZoneMapping);
+ }
+ }
+ return Collections.unmodifiableList(filteredList);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ CountryTimeZones that = (CountryTimeZones) o;
+ return defaultTimeZoneBoosted == that.defaultTimeZoneBoosted
+ && everUsesUtc == that.everUsesUtc
+ && countryIso.equals(that.countryIso)
+ && Objects.equals(defaultTimeZoneId, that.defaultTimeZoneId)
+ && timeZoneMappings.equals(that.timeZoneMappings);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ countryIso, defaultTimeZoneId, defaultTimeZoneBoosted, timeZoneMappings,
+ everUsesUtc);
+ }
+
+ @Override
+ public String toString() {
+ return "CountryTimeZones{"
+ + "countryIso='" + countryIso + '\''
+ + ", defaultTimeZoneId='" + defaultTimeZoneId + '\''
+ + ", defaultTimeZoneBoosted=" + defaultTimeZoneBoosted
+ + ", timeZoneMappings=" + timeZoneMappings
+ + ", everUsesUtc=" + everUsesUtc
+ + '}';
+ }
+
+ /**
* Returns a time zone for the country, if there is one, that matches the supplied properties.
* If there are multiple matches and the {@code bias} is one of them then it is returned,
* otherwise an arbitrary match is returned based on the {@link
diff --git a/luni/src/main/java/libcore/timezone/TelephonyNetwork.java b/luni/src/main/java/libcore/timezone/TelephonyNetwork.java
index e0f26ad..3bd1be8 100644
--- a/luni/src/main/java/libcore/timezone/TelephonyNetwork.java
+++ b/luni/src/main/java/libcore/timezone/TelephonyNetwork.java
@@ -87,16 +87,25 @@
return mccMnc;
}
+ /**
+ * Returns the Mobile Country Code of the network.
+ */
@libcore.api.CorePlatformApi
public String getMcc() {
return mccMnc.mcc;
}
+ /**
+ * Returns the Mobile Network Code of the network.
+ */
@libcore.api.CorePlatformApi
public String getMnc() {
return mccMnc.mnc;
}
+ /**
+ * Returns the country in which the network operates as an ISO 3166 alpha-2 (lower case).
+ */
@libcore.api.CorePlatformApi
public String getCountryIsoCode() {
return countryIsoCode;
diff --git a/luni/src/main/java/libcore/timezone/TelephonyNetworkFinder.java b/luni/src/main/java/libcore/timezone/TelephonyNetworkFinder.java
index f244159..825c06e 100644
--- a/luni/src/main/java/libcore/timezone/TelephonyNetworkFinder.java
+++ b/luni/src/main/java/libcore/timezone/TelephonyNetworkFinder.java
@@ -30,7 +30,8 @@
import java.util.Set;
/**
- * A class that can find telephony networks loaded via {@link TelephonyLookup}.
+ * A class that can find telephony network information loaded via {@link TelephonyLookup}.
+ *
* @hide
*/
@libcore.api.CorePlatformApi
@@ -70,6 +71,11 @@
this.networksMap = networksMap;
}
+ /**
+ * Returns information held about a specific MCC + MNC combination. It is expected for this
+ * method to return {@code null}. Only known, unusual networks will typically have information
+ * returned, e.g. if they operate in countries other than the one suggested by their MCC.
+ */
@libcore.api.CorePlatformApi
public TelephonyNetwork findNetworkByMccMnc(String mcc, String mnc) {
return networksMap.get(new MccMnc(mcc, mnc));
diff --git a/luni/src/main/java/libcore/timezone/TimeZoneFinder.java b/luni/src/main/java/libcore/timezone/TimeZoneFinder.java
index 3f18e36..274440c 100644
--- a/luni/src/main/java/libcore/timezone/TimeZoneFinder.java
+++ b/luni/src/main/java/libcore/timezone/TimeZoneFinder.java
@@ -199,7 +199,8 @@
@libcore.api.CorePlatformApi
public CountryTimeZones lookupCountryTimeZones(String countryIso) {
synchronized (this) {
- if (lastCountryTimeZones != null && lastCountryTimeZones.isForCountryCode(countryIso)) {
+ if (lastCountryTimeZones != null
+ && lastCountryTimeZones.matchesCountryCode(countryIso)) {
return lastCountryTimeZones;
}
}
@@ -525,5 +526,4 @@
return validatedCountryTimeZones;
}
}
-
}
diff --git a/luni/src/main/java/libcore/timezone/TzDataSetVersion.java b/luni/src/main/java/libcore/timezone/TzDataSetVersion.java
index 8b97069b..1a1d156 100644
--- a/luni/src/main/java/libcore/timezone/TzDataSetVersion.java
+++ b/luni/src/main/java/libcore/timezone/TzDataSetVersion.java
@@ -25,7 +25,23 @@
import java.util.regex.Pattern;
/**
- * Constants and logic associated with the time zone data version file.
+ * Version information associated with the set of time zone data on a device.
+ *
+ * <p>Time Zone Data Sets have a major ({@link #getFormatMajorVersion()}) and minor
+ * ({@link #currentFormatMinorVersion()}) version number:
+ * <ul>
+ * <li>Major version numbers are mutually incompatible. e.g. v2 is not compatible with a v1 or a
+ * v3 device.</li>
+ * <li>Minor version numbers are backwards compatible. e.g. a v2.2 data set will work
+ * on a v2.1 device but not a v2.3 device. The minor version is reset to 1 when the major version
+ * is incremented.</li>
+ * </ul>
+ *
+ * <p>Data sets contain time zone rules and other data associated wtih a tzdb release
+ * ({@link #getRulesVersion()}) and an additional Android-specific revision number
+ * ({@link #getRevision()}).
+ *
+ * <p>See platform/system/timezone/README.android for more information.
* @hide
*/
@libcore.api.CorePlatformApi
@@ -162,22 +178,26 @@
return readFromFile(new File(tzVersionFileName));
}
+ /** Returns the major version number. See {@link TzDataSetVersion}. */
@libcore.api.CorePlatformApi
public int getFormatMajorVersion() {
return formatMajorVersion;
}
+ /** Returns the minor version number. See {@link TzDataSetVersion}. */
@libcore.api.CorePlatformApi
public int getFormatMinorVersion() {
return formatMinorVersion;
}
+ /** Returns the tzdb version string. See {@link TzDataSetVersion}. */
@libcore.api.CorePlatformApi
public String getRulesVersion() {
return rulesVersion;
}
// Remove from CorePlatformApi when all users in platform code are removed. http://b/123398797
+ /** Returns the Android revision. See {@link TzDataSetVersion}. */
@libcore.api.CorePlatformApi
public int getRevision() {
return revision;
@@ -210,9 +230,7 @@
if (o == null || getClass() != o.getClass()) {
return false;
}
-
TzDataSetVersion that = (TzDataSetVersion) o;
-
if (formatMajorVersion != that.formatMajorVersion) {
return false;
}
diff --git a/luni/src/main/java/libcore/timezone/ZoneInfoDb.java b/luni/src/main/java/libcore/timezone/ZoneInfoDb.java
index a94d293..bd41911 100644
--- a/luni/src/main/java/libcore/timezone/ZoneInfoDb.java
+++ b/luni/src/main/java/libcore/timezone/ZoneInfoDb.java
@@ -103,6 +103,9 @@
}
};
+ /**
+ * Obtains the singleton instance.
+ */
@libcore.api.CorePlatformApi
public static ZoneInfoDb getInstance() {
return DATA;
@@ -349,6 +352,9 @@
return rawUtcOffsetsCache;
}
+ /**
+ * Returns the tzdb version in use.
+ */
@libcore.api.CorePlatformApi
public String getVersion() {
checkNotClosed();
diff --git a/luni/src/main/native/IcuUtilities.cpp b/luni/src/main/native/IcuUtilities.cpp
index 0db59f9..6811ce5 100644
--- a/luni/src/main/native/IcuUtilities.cpp
+++ b/luni/src/main/native/IcuUtilities.cpp
@@ -16,18 +16,11 @@
#define LOG_TAG "IcuUtilities"
-#include <android/log.h>
#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedLocalRef.h>
-#include <nativehelper/ScopedUtfChars.h>
#include "IcuUtilities.h"
#include "JniConstants.h"
-#include "JniException.h"
-#include "unicode/strenum.h"
-#include "unicode/ustring.h"
-#include "unicode/uloc.h"
bool maybeThrowIcuException(JNIEnv* env, const char* function, UErrorCode error) {
if (U_SUCCESS(error)) {
diff --git a/luni/src/main/native/JniException.cpp b/luni/src/main/native/JniException.cpp
index 164281d..01346ef 100644
--- a/luni/src/main/native/JniException.cpp
+++ b/luni/src/main/native/JniException.cpp
@@ -19,15 +19,6 @@
#include "JniException.h"
#include <nativehelper/JNIHelp.h>
-void jniThrowExceptionWithErrno(JNIEnv* env, const char* exceptionClassName, int error) {
- char buf[BUFSIZ];
- jniThrowException(env, exceptionClassName, jniStrError(error, buf, sizeof(buf)));
-}
-
void jniThrowOutOfMemoryError(JNIEnv* env, const char* message) {
jniThrowException(env, "java/lang/OutOfMemoryError", message);
}
-
-void jniThrowSocketException(JNIEnv* env, int error) {
- jniThrowExceptionWithErrno(env, "java/net/SocketException", error);
-}
diff --git a/luni/src/main/native/JniException.h b/luni/src/main/native/JniException.h
index 2d4a097..cff68b8 100644
--- a/luni/src/main/native/JniException.h
+++ b/luni/src/main/native/JniException.h
@@ -19,9 +19,6 @@
#include "jni.h"
-void jniThrowExceptionWithErrno(JNIEnv* env, const char* exceptionClassName, int error);
-
void jniThrowOutOfMemoryError(JNIEnv* env, const char* message);
-void jniThrowSocketException(JNIEnv* env, int error);
#endif // JNI_EXCEPTION_H_included
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index 9879761..aa3d5004 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -17,57 +17,25 @@
#define LOG_NDEBUG 1
#define LOG_TAG "ICU"
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <string>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <time.h>
-#include <unistd.h>
-
#include <memory>
#include <vector>
#include <androidicuinit/IcuRegistration.h>
#include <log/log.h>
#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedLocalRef.h>
#include <nativehelper/ScopedStringChars.h>
#include <nativehelper/ScopedUtfChars.h>
#include <nativehelper/jni_macros.h>
#include <nativehelper/toStringArray.h>
#include "IcuUtilities.h"
-#include "JniConstants.h"
#include "JniException.h"
-#include "ScopedIcuLocale.h"
#include "ScopedIcuULoc.h"
-#include "ScopedJavaUnicodeString.h"
-#include "unicode/brkiter.h"
-#include "unicode/char16ptr.h"
-#include "unicode/calendar.h"
-#include "unicode/datefmt.h"
-#include "unicode/dcfmtsym.h"
-#include "unicode/decimfmt.h"
-#include "unicode/dtfmtsym.h"
-#include "unicode/gregocal.h"
-#include "unicode/locid.h"
-#include "unicode/numfmt.h"
-#include "unicode/strenum.h"
-#include "unicode/ubrk.h"
-#include "unicode/ucal.h"
-#include "unicode/ucasemap.h"
-#include "unicode/ucol.h"
-#include "unicode/ucurr.h"
-#include "unicode/udat.h"
#include "unicode/udatpg.h"
#include "unicode/uloc.h"
#include "unicode/ures.h"
#include "unicode/ustring.h"
#include "ureslocs.h"
-#include "valueOf.h"
class ScopedResourceBundle {
public:
@@ -155,38 +123,6 @@
return (charCount == 0) ? env->NewStringUTF("XXX") : jniCreateString(env, chars, charCount);
}
-static jstring getCurrencyName(JNIEnv* env, jstring javaLanguageTag, jstring javaCurrencyCode, UCurrNameStyle nameStyle) {
- ScopedUtfChars languageTag(env, javaLanguageTag);
- if (languageTag.c_str() == NULL) {
- return NULL;
- }
- ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode);
- if (!currencyCode.valid()) {
- return NULL;
- }
- icu::UnicodeString icuCurrencyCode(currencyCode.unicodeString());
- UErrorCode status = U_ZERO_ERROR;
- UBool isChoiceFormat = false;
- int32_t charCount;
- const UChar* chars = ucurr_getName(icuCurrencyCode.getTerminatedBuffer(), languageTag.c_str(),
- nameStyle, &isChoiceFormat, &charCount, &status);
- if (status == U_USING_DEFAULT_WARNING) {
- if (nameStyle == UCURR_SYMBOL_NAME) {
- // ICU doesn't distinguish between falling back to the root locale and meeting a genuinely
- // unknown currency. The Currency class does.
- if (!ucurr_isAvailable(icuCurrencyCode.getTerminatedBuffer(), U_DATE_MIN, U_DATE_MAX, &status)) {
- return NULL;
- }
- }
- if (nameStyle == UCURR_LONG_NAME) {
- // ICU's default is English. We want the ISO 4217 currency code instead.
- chars = icuCurrencyCode.getBuffer();
- charCount = icuCurrencyCode.length();
- }
- }
- return (charCount == 0) ? NULL : jniCreateString(env, chars, charCount);
-}
-
static jstring ICU_getISO3Country(JNIEnv* env, jclass, jstring javaLanguageTag) {
ScopedIcuULoc icuLocale(env, javaLanguageTag);
if (!icuLocale.valid()) {
@@ -215,378 +151,6 @@
return toStringArray(env, uloc_countAvailable, uloc_getAvailable);
}
-static bool setIntegerField(JNIEnv* env, jobject obj, const char* fieldName, int value) {
- ScopedLocalRef<jobject> integerValue(env, integerValueOf(env, value));
- if (integerValue.get() == NULL) return false;
- jfieldID fid = env->GetFieldID(JniConstants::GetLocaleDataClass(env), fieldName, "Ljava/lang/Integer;");
- env->SetObjectField(obj, fid, integerValue.get());
- return true;
-}
-
-static void setStringField(JNIEnv* env, jobject obj, const char* fieldName, jstring value) {
- jfieldID fid = env->GetFieldID(JniConstants::GetLocaleDataClass(env), fieldName, "Ljava/lang/String;");
- env->SetObjectField(obj, fid, value);
- env->DeleteLocalRef(value);
-}
-
-static void setStringArrayField(JNIEnv* env, jobject obj, const char* fieldName, jobjectArray value) {
- jfieldID fid = env->GetFieldID(JniConstants::GetLocaleDataClass(env), fieldName, "[Ljava/lang/String;");
- env->SetObjectField(obj, fid, value);
-}
-
-static void setStringArrayField(JNIEnv* env, jobject obj, const char* fieldName, const icu::UnicodeString* valueArray, int32_t size) {
- ScopedLocalRef<jobjectArray> result(env, env->NewObjectArray(size, JniConstants::GetStringClass(env), NULL));
- for (int32_t i = 0; i < size ; i++) {
- ScopedLocalRef<jstring> s(env, jniCreateString(env, valueArray[i].getBuffer(),valueArray[i].length()));
- if (env->ExceptionCheck()) {
- return;
- }
- env->SetObjectArrayElement(result.get(), i, s.get());
- if (env->ExceptionCheck()) {
- return;
- }
- }
- setStringArrayField(env, obj, fieldName, result.get());
-}
-
-static void setStringField(JNIEnv* env, jobject obj, const char* fieldName, UResourceBundle* bundle, int index) {
- UErrorCode status = U_ZERO_ERROR;
- int charCount;
- const UChar* chars;
- UResourceBundle* currentBundle = ures_getByIndex(bundle, index, NULL, &status);
- switch (ures_getType(currentBundle)) {
- case URES_STRING:
- chars = ures_getString(currentBundle, &charCount, &status);
- break;
- case URES_ARRAY:
- // In case there is an array, Android currently only cares about the
- // first string of that array, the rest of the array is used by ICU
- // for additional data ignored by Android.
- chars = ures_getStringByIndex(currentBundle, 0, &charCount, &status);
- break;
- default:
- status = U_INVALID_FORMAT_ERROR;
- }
- ures_close(currentBundle);
- if (U_SUCCESS(status)) {
- setStringField(env, obj, fieldName, jniCreateString(env, chars, charCount));
- } else {
- ALOGE("Error setting String field %s from ICU resource (index %d): %s", fieldName, index, u_errorName(status));
- }
-}
-
-static void setCharField(JNIEnv* env, jobject obj, const char* fieldName, const icu::UnicodeString& value) {
- if (value.length() == 0) {
- return;
- }
- jfieldID fid = env->GetFieldID(JniConstants::GetLocaleDataClass(env), fieldName, "C");
- env->SetCharField(obj, fid, value.charAt(0));
-}
-
-static void setStringField(JNIEnv* env, jobject obj, const char* fieldName, const icu::UnicodeString& value) {
- const UChar* chars = value.getBuffer();
- setStringField(env, obj, fieldName, jniCreateString(env, chars, value.length()));
-}
-
-static void setNumberPatterns(JNIEnv* env, jobject obj, icu::Locale& locale) {
- UErrorCode status = U_ZERO_ERROR;
-
- icu::UnicodeString pattern;
- std::unique_ptr<icu::DecimalFormat> fmt(static_cast<icu::DecimalFormat*>(icu::NumberFormat::createInstance(locale, UNUM_CURRENCY, status)));
- pattern = fmt->toPattern(pattern.remove());
- setStringField(env, obj, "currencyPattern", pattern);
-
- fmt.reset(static_cast<icu::DecimalFormat*>(icu::NumberFormat::createInstance(locale, UNUM_DECIMAL, status)));
- pattern = fmt->toPattern(pattern.remove());
- setStringField(env, obj, "numberPattern", pattern);
-
- fmt.reset(static_cast<icu::DecimalFormat*>(icu::NumberFormat::createInstance(locale, UNUM_PERCENT, status)));
- pattern = fmt->toPattern(pattern.remove());
- setStringField(env, obj, "percentPattern", pattern);
-}
-
-static void setDecimalFormatSymbolsData(JNIEnv* env, jobject obj, icu::Locale& locale) {
- UErrorCode status = U_ZERO_ERROR;
- icu::DecimalFormatSymbols dfs(locale, status);
-
- setCharField(env, obj, "decimalSeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kDecimalSeparatorSymbol));
- setCharField(env, obj, "groupingSeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kGroupingSeparatorSymbol));
- setCharField(env, obj, "patternSeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kPatternSeparatorSymbol));
- setStringField(env, obj, "percent", dfs.getSymbol(icu::DecimalFormatSymbols::kPercentSymbol));
- setStringField(env, obj, "perMill", dfs.getSymbol(icu::DecimalFormatSymbols::kPerMillSymbol));
- setCharField(env, obj, "monetarySeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kMonetarySeparatorSymbol));
- setStringField(env, obj, "minusSign", dfs.getSymbol(icu::DecimalFormatSymbols:: kMinusSignSymbol));
- setStringField(env, obj, "exponentSeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kExponentialSymbol));
- setStringField(env, obj, "infinity", dfs.getSymbol(icu::DecimalFormatSymbols::kInfinitySymbol));
- setStringField(env, obj, "NaN", dfs.getSymbol(icu::DecimalFormatSymbols::kNaNSymbol));
- setCharField(env, obj, "zeroDigit", dfs.getSymbol(icu::DecimalFormatSymbols::kZeroDigitSymbol));
-}
-
-
-// Iterates up through the locale hierarchy. So "en_US" would return "en_US", "en", "".
-class LocaleNameIterator {
- public:
- LocaleNameIterator(const char* locale_name, UErrorCode& status) : status_(status), has_next_(true) {
- strcpy(locale_name_, locale_name);
- locale_name_length_ = strlen(locale_name_);
- }
-
- const char* Get() {
- return locale_name_;
- }
-
- bool HasNext() {
- return has_next_;
- }
-
- void Up() {
- if (locale_name_length_ == 0) {
- has_next_ = false;
- } else {
- locale_name_length_ = uloc_getParent(locale_name_, locale_name_, sizeof(locale_name_), &status_);
- }
- }
-
- private:
- UErrorCode& status_;
- bool has_next_;
- char locale_name_[ULOC_FULLNAME_CAPACITY];
- int32_t locale_name_length_;
-
- DISALLOW_COPY_AND_ASSIGN(LocaleNameIterator);
-};
-
-static bool getAmPmMarkersNarrow(JNIEnv* env, jobject localeData, const char* locale_name) {
- UErrorCode status = U_ZERO_ERROR;
- ScopedResourceBundle root(ures_open(NULL, locale_name, &status));
- if (U_FAILURE(status)) {
- return false;
- }
- ScopedResourceBundle calendar(ures_getByKey(root.get(), "calendar", NULL, &status));
- if (U_FAILURE(status)) {
- return false;
- }
- ScopedResourceBundle gregorian(ures_getByKey(calendar.get(), "gregorian", NULL, &status));
- if (U_FAILURE(status)) {
- return false;
- }
- ScopedResourceBundle amPmMarkersNarrow(ures_getByKey(gregorian.get(), "AmPmMarkersNarrow", NULL, &status));
- if (U_FAILURE(status)) {
- return false;
- }
- setStringField(env, localeData, "narrowAm", amPmMarkersNarrow.get(), 0);
- setStringField(env, localeData, "narrowPm", amPmMarkersNarrow.get(), 1);
- return true;
-}
-
-static bool getDateTimePatterns(JNIEnv* env, jobject localeData, const char* locale_name) {
- UErrorCode status = U_ZERO_ERROR;
- ScopedResourceBundle root(ures_open(NULL, locale_name, &status));
- if (U_FAILURE(status)) {
- return false;
- }
- ScopedResourceBundle calendar(ures_getByKey(root.get(), "calendar", NULL, &status));
- if (U_FAILURE(status)) {
- return false;
- }
- ScopedResourceBundle gregorian(ures_getByKey(calendar.get(), "gregorian", NULL, &status));
- if (U_FAILURE(status)) {
- return false;
- }
- ScopedResourceBundle dateTimePatterns(ures_getByKey(gregorian.get(), "DateTimePatterns", NULL, &status));
- if (U_FAILURE(status)) {
- return false;
- }
- setStringField(env, localeData, "fullTimeFormat", dateTimePatterns.get(), 0);
- setStringField(env, localeData, "longTimeFormat", dateTimePatterns.get(), 1);
- setStringField(env, localeData, "mediumTimeFormat", dateTimePatterns.get(), 2);
- setStringField(env, localeData, "shortTimeFormat", dateTimePatterns.get(), 3);
- setStringField(env, localeData, "fullDateFormat", dateTimePatterns.get(), 4);
- setStringField(env, localeData, "longDateFormat", dateTimePatterns.get(), 5);
- setStringField(env, localeData, "mediumDateFormat", dateTimePatterns.get(), 6);
- setStringField(env, localeData, "shortDateFormat", dateTimePatterns.get(), 7);
- return true;
-}
-
-static bool getYesterdayTodayAndTomorrow(JNIEnv* env, jobject localeData, const icu::Locale& locale, const char* locale_name) {
- UErrorCode status = U_ZERO_ERROR;
- ScopedResourceBundle root(ures_open(NULL, locale_name, &status));
- ScopedResourceBundle fields(ures_getByKey(root.get(), "fields", NULL, &status));
- ScopedResourceBundle day(ures_getByKey(fields.get(), "day", NULL, &status));
- ScopedResourceBundle relative(ures_getByKey(day.get(), "relative", NULL, &status));
- if (U_FAILURE(status)) {
- return false;
- }
-
- icu::UnicodeString yesterday(icu::ures_getUnicodeStringByKey(relative.get(), "-1", &status));
- icu::UnicodeString today(icu::ures_getUnicodeStringByKey(relative.get(), "0", &status));
- icu::UnicodeString tomorrow(icu::ures_getUnicodeStringByKey(relative.get(), "1", &status));
- if (U_FAILURE(status)) {
- ALOGE("Error getting yesterday/today/tomorrow for %s: %s", locale_name, u_errorName(status));
- return false;
- }
-
- // We title-case the strings so they have consistent capitalization (http://b/14493853).
- std::unique_ptr<icu::BreakIterator> brk(icu::BreakIterator::createSentenceInstance(locale, status));
- if (U_FAILURE(status)) {
- ALOGE("Error getting yesterday/today/tomorrow break iterator for %s: %s", locale_name, u_errorName(status));
- return false;
- }
- yesterday.toTitle(brk.get(), locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
- today.toTitle(brk.get(), locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
- tomorrow.toTitle(brk.get(), locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
-
- setStringField(env, localeData, "yesterday", yesterday);
- setStringField(env, localeData, "today", today);
- setStringField(env, localeData, "tomorrow", tomorrow);
- return true;
-}
-
-static jboolean ICU_initLocaleDataNative(JNIEnv* env, jclass, jstring javaLanguageTag, jobject localeData) {
- ScopedUtfChars languageTag(env, javaLanguageTag);
- if (languageTag.c_str() == NULL) {
- return JNI_FALSE;
- }
- if (languageTag.size() >= ULOC_FULLNAME_CAPACITY) {
- return JNI_FALSE; // ICU has a fixed-length limit.
- }
-
- ScopedIcuLocale icuLocale(env, javaLanguageTag);
- if (!icuLocale.valid()) {
- return JNI_FALSE;
- }
-
- // Get the DateTimePatterns.
- UErrorCode status = U_ZERO_ERROR;
- bool foundDateTimePatterns = false;
- for (LocaleNameIterator it(icuLocale.locale().getBaseName(), status); it.HasNext(); it.Up()) {
- if (getDateTimePatterns(env, localeData, it.Get())) {
- foundDateTimePatterns = true;
- break;
- }
- }
- if (!foundDateTimePatterns) {
- ALOGE("Couldn't find ICU DateTimePatterns for %s", languageTag.c_str());
- return JNI_FALSE;
- }
-
- // Get the "Yesterday", "Today", and "Tomorrow" strings.
- bool foundYesterdayTodayAndTomorrow = false;
- for (LocaleNameIterator it(icuLocale.locale().getBaseName(), status); it.HasNext(); it.Up()) {
- if (getYesterdayTodayAndTomorrow(env, localeData, icuLocale.locale(), it.Get())) {
- foundYesterdayTodayAndTomorrow = true;
- break;
- }
- }
- if (!foundYesterdayTodayAndTomorrow) {
- ALOGE("Couldn't find ICU yesterday/today/tomorrow for %s", languageTag.c_str());
- return JNI_FALSE;
- }
-
- // Get the narrow "AM" and "PM" strings.
- bool foundAmPmMarkersNarrow = false;
- for (LocaleNameIterator it(icuLocale.locale().getBaseName(), status); it.HasNext(); it.Up()) {
- if (getAmPmMarkersNarrow(env, localeData, it.Get())) {
- foundAmPmMarkersNarrow = true;
- break;
- }
- }
- if (!foundAmPmMarkersNarrow) {
- ALOGE("Couldn't find ICU AmPmMarkersNarrow for %s", languageTag.c_str());
- return JNI_FALSE;
- }
-
- status = U_ZERO_ERROR;
- std::unique_ptr<icu::Calendar> cal(icu::Calendar::createInstance(icuLocale.locale(), status));
- if (U_FAILURE(status)) {
- return JNI_FALSE;
- }
- if (!setIntegerField(env, localeData, "firstDayOfWeek", cal->getFirstDayOfWeek())) {
- return JNI_FALSE;
- }
- if (!setIntegerField(env, localeData, "minimalDaysInFirstWeek", cal->getMinimalDaysInFirstWeek())) {
- return JNI_FALSE;
- }
-
- // Get DateFormatSymbols.
- status = U_ZERO_ERROR;
- icu::DateFormatSymbols dateFormatSym(icuLocale.locale(), status);
- if (U_FAILURE(status)) {
- return JNI_FALSE;
- }
-
- // Get AM/PM and BC/AD.
- int32_t count = 0;
- const icu::UnicodeString* amPmStrs = dateFormatSym.getAmPmStrings(count);
- setStringArrayField(env, localeData, "amPm", amPmStrs, count);
- const icu::UnicodeString* erasStrs = dateFormatSym.getEras(count);
- setStringArrayField(env, localeData, "eras", erasStrs, count);
-
- const icu::UnicodeString* longMonthNames =
- dateFormatSym.getMonths(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::WIDE);
- setStringArrayField(env, localeData, "longMonthNames", longMonthNames, count);
- const icu::UnicodeString* shortMonthNames =
- dateFormatSym.getMonths(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::ABBREVIATED);
- setStringArrayField(env, localeData, "shortMonthNames", shortMonthNames, count);
- const icu::UnicodeString* tinyMonthNames =
- dateFormatSym.getMonths(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::NARROW);
- setStringArrayField(env, localeData, "tinyMonthNames", tinyMonthNames, count);
- const icu::UnicodeString* longWeekdayNames =
- dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::WIDE);
- setStringArrayField(env, localeData, "longWeekdayNames", longWeekdayNames, count);
- const icu::UnicodeString* shortWeekdayNames =
- dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::ABBREVIATED);
- setStringArrayField(env, localeData, "shortWeekdayNames", shortWeekdayNames, count);
- const icu::UnicodeString* tinyWeekdayNames =
- dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::NARROW);
- setStringArrayField(env, localeData, "tinyWeekdayNames", tinyWeekdayNames, count);
-
- const icu::UnicodeString* longStandAloneMonthNames =
- dateFormatSym.getMonths(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::WIDE);
- setStringArrayField(env, localeData, "longStandAloneMonthNames", longStandAloneMonthNames, count);
- const icu::UnicodeString* shortStandAloneMonthNames =
- dateFormatSym.getMonths(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::ABBREVIATED);
- setStringArrayField(env, localeData, "shortStandAloneMonthNames", shortStandAloneMonthNames, count);
- const icu::UnicodeString* tinyStandAloneMonthNames =
- dateFormatSym.getMonths(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::NARROW);
- setStringArrayField(env, localeData, "tinyStandAloneMonthNames", tinyStandAloneMonthNames, count);
- const icu::UnicodeString* longStandAloneWeekdayNames =
- dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::WIDE);
- setStringArrayField(env, localeData, "longStandAloneWeekdayNames", longStandAloneWeekdayNames, count);
- const icu::UnicodeString* shortStandAloneWeekdayNames =
- dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::ABBREVIATED);
- setStringArrayField(env, localeData, "shortStandAloneWeekdayNames", shortStandAloneWeekdayNames, count);
- const icu::UnicodeString* tinyStandAloneWeekdayNames =
- dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::NARROW);
- setStringArrayField(env, localeData, "tinyStandAloneWeekdayNames", tinyStandAloneWeekdayNames, count);
-
- status = U_ZERO_ERROR;
-
- // For numberPatterns and symbols.
- setNumberPatterns(env, localeData, icuLocale.locale());
- setDecimalFormatSymbolsData(env, localeData, icuLocale.locale());
-
- jstring countryCode = env->NewStringUTF(icuLocale.locale().getCountry());
- jstring internationalCurrencySymbol = ICU_getCurrencyCode(env, NULL, countryCode);
- env->DeleteLocalRef(countryCode);
- countryCode = NULL;
-
- jstring currencySymbol = NULL;
- if (internationalCurrencySymbol != NULL) {
- currencySymbol = getCurrencyName(env, javaLanguageTag, internationalCurrencySymbol, UCURR_SYMBOL_NAME);
- } else {
- internationalCurrencySymbol = env->NewStringUTF("XXX");
- }
- if (currencySymbol == NULL) {
- // This is the UTF-8 encoding of U+00A4 (CURRENCY SIGN).
- currencySymbol = env->NewStringUTF("\xc2\xa4");
- }
- setStringField(env, localeData, "currencySymbol", currencySymbol);
- setStringField(env, localeData, "internationalCurrencySymbol", internationalCurrencySymbol);
-
- return JNI_TRUE;
-}
-
static jstring ICU_getBestDateTimePatternNative(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLanguageTag) {
ScopedIcuULoc icuLocale(env, javaLanguageTag);
if (!icuLocale.valid()) {
@@ -661,7 +225,6 @@
NATIVE_METHOD(ICU, getISOCountriesNative, "()[Ljava/lang/String;"),
NATIVE_METHOD(ICU, getISOLanguagesNative, "()[Ljava/lang/String;"),
NATIVE_METHOD(ICU, getScript, "(Ljava/lang/String;)Ljava/lang/String;"),
- NATIVE_METHOD(ICU, initLocaleDataNative, "(Ljava/lang/String;Llibcore/icu/LocaleData;)Z"),
NATIVE_METHOD(ICU, setDefaultLocale, "(Ljava/lang/String;)V"),
};
diff --git a/luni/src/main/native/libcore_io_Linux.cpp b/luni/src/main/native/libcore_io_Linux.cpp
index 9e44e63..a99b862 100644
--- a/luni/src/main/native/libcore_io_Linux.cpp
+++ b/luni/src/main/native/libcore_io_Linux.cpp
@@ -29,6 +29,7 @@
#include <pwd.h>
#include <signal.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/capability.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
@@ -2470,7 +2471,7 @@
static jstring Linux_strerror(JNIEnv* env, jobject, jint errnum) {
char buffer[BUFSIZ];
- const char* message = jniStrError(errnum, buffer, sizeof(buffer));
+ const char* message = strerror_r(errnum, buffer, sizeof(buffer));
return env->NewStringUTF(message);
}
diff --git a/luni/src/test/java/libcore/java/io/FileDescriptorTest.java b/luni/src/test/java/libcore/java/io/FileDescriptorTest.java
index 3e82690..390cfd6 100644
--- a/luni/src/test/java/libcore/java/io/FileDescriptorTest.java
+++ b/luni/src/test/java/libcore/java/io/FileDescriptorTest.java
@@ -16,7 +16,10 @@
package libcore.java.io;
+import android.system.Os;
+
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -24,6 +27,8 @@
import java.net.ServerSocket;
import junit.framework.TestCase;
+import static org.junit.Assert.assertNotEquals;
+
public class FileDescriptorTest extends TestCase {
public void testReadOnlyFileDescriptorSync() throws Exception {
File f= File.createTempFile("FileDescriptorTest", "tmp");
@@ -40,4 +45,31 @@
assertTrue(s.getImpl().getFD$().isSocket$());
s.close();
}
+
+ public void testStaticFileDescriptors() {
+ assertTrue(FileDescriptor.in.valid());
+ assertTrue(FileDescriptor.out.valid());
+ assertTrue(FileDescriptor.err.valid());
+ }
+
+ public void testFileDescriptorCloneForFork() throws Exception {
+ FileDescriptor [] sources = { FileDescriptor.in, FileDescriptor.out, FileDescriptor.err };
+ for (FileDescriptor source : sources) {
+ // Create a new file descriptor and set it's native descriptor to each of the well
+ // known descriptors in FileDescriptor.
+ FileDescriptor target = new FileDescriptor();
+ target.setInt$(source.getInt$());
+ assertEquals(target.getInt$(), source.getInt$());
+
+ // Clone file descriptor, this creates a native file descriptor.
+ target.cloneForFork();
+ assertTrue(source.valid());
+ assertTrue(target.valid());
+ assertNotEquals(target.getInt$(), source.getInt$());
+
+ // Clean-up native resource we allocated in cloneForFork. Os.close() may throw
+ // an ErrnoException.
+ Os.close(target);
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/lang/OldClassTest.java b/luni/src/test/java/libcore/java/lang/OldClassTest.java
index f5bc787..e0955bc 100644
--- a/luni/src/test/java/libcore/java/lang/OldClassTest.java
+++ b/luni/src/test/java/libcore/java/lang/OldClassTest.java
@@ -306,7 +306,7 @@
}
}
- // AndroidOnly: Class.forName method throws ClassNotFoundException on Android.
+ // Android-note: Class.forName method throws ClassNotFoundException on Android.
public void test_forNameLjava_lang_StringLbooleanLClassLoader_AndroidOnly() throws Exception {
// Android doesn't support loading class files from a jar.
@@ -460,7 +460,7 @@
assertEquals(AbstractList.class, type.getRawType());
}
- // AndroidOnly: Uses dalvik.system.PathClassLoader.
+ // Android-note: Uses dalvik.system.PathClassLoader.
// Different behavior between cts host and run-core-test")
public void test_getPackage() {
diff --git a/luni/src/test/java/libcore/java/lang/SystemTest.java b/luni/src/test/java/libcore/java/lang/SystemTest.java
index 56b6558..939a9f3 100644
--- a/luni/src/test/java/libcore/java/lang/SystemTest.java
+++ b/luni/src/test/java/libcore/java/lang/SystemTest.java
@@ -160,7 +160,7 @@
}
public void testSystemProperties_immutable() {
- // Android-specific: The RI does not have a concept of immutable properties.
+ // Android-note: The RI does not have a concept of immutable properties.
// user.dir is an immutable property
String userDir = System.getProperty("user.dir");
@@ -223,10 +223,10 @@
System.setProperties(newProperties);
- // Android-specific: The RI makes the setProperties() argument the system properties object,
+ // Android-note: The RI makes the setProperties() argument the system properties object.
// Android makes a new Properties object and copies the properties.
assertNotSame(newProperties, System.getProperties());
- // Android-specific: The RI does not have a concept of immutable properties.
+ // Android-note: The RI does not have a concept of immutable properties.
assertEquals(userDir, System.getProperty("user.dir"));
assertEquals("v2", System.getProperty("p1"));
@@ -242,7 +242,7 @@
properties.clear();
- // Android-specific: The RI clears everything, Android resets to immutable defaults.
+ // Android-note: The RI clears everything, Android resets to immutable defaults.
assertEquals(userDir, System.getProperty("user.dir"));
assertNull(System.getProperty("p1"));
}
diff --git a/luni/src/test/java/libcore/java/text/OldDecimalFormatTestICU.java b/luni/src/test/java/libcore/java/text/OldDecimalFormatTestICU.java
index eb3f4ca..75344af 100644
--- a/luni/src/test/java/libcore/java/text/OldDecimalFormatTestICU.java
+++ b/luni/src/test/java/libcore/java/text/OldDecimalFormatTestICU.java
@@ -35,7 +35,7 @@
format = (DecimalFormat) NumberFormat.getNumberInstance();
}
- // AndroidOnly: special feature of icu4c
+ // Android-note: special feature of icu4c.
public void test_sigDigitPatterns() throws Exception {
DecimalFormat format = (DecimalFormat) NumberFormat
.getInstance(Locale.US);
@@ -62,7 +62,7 @@
}
}
- // AndroidOnly: special feature of icu4c
+ // Android-note: special feature of icu4c.
public void test_paddingPattern() throws Exception {
format.applyPattern("*x##,##,#,##0.0#");
assertEquals("xxxxxxxxx123.0", format.format(123));
@@ -95,7 +95,7 @@
}
}
- // AndroidOnly: special feature of icu4c
+ // Android-note: special feature of icu4c.
public void test_positiveExponentSign() throws Exception {
format.applyPattern("0.###E+0");
assertEquals("1E+2", format.format(100));
@@ -124,7 +124,7 @@
}
}
- // AndroidOnly: special feature of icu4c
+ // Android-note: special feature of icu4c.
public void test_secondaryGroupingSize() throws Exception {
format.applyPattern("#,##,###,####");
assertEquals("123,456,7890", format.format(1234567890));
diff --git a/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java b/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java
index 607397d..42caf13 100644
--- a/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java
+++ b/luni/src/test/java/libcore/libcore/icu/LocaleDataTest.java
@@ -16,16 +16,21 @@
package libcore.libcore.icu;
+import static org.junit.Assert.assertArrayEquals;
+
import java.util.Locale;
import libcore.icu.LocaleData;
public class LocaleDataTest extends junit.framework.TestCase {
+ static {
+ System.loadLibrary("javacoretests");
+ }
+
public void testAll() throws Exception {
// Test that we can get the locale data for all known locales.
for (Locale l : Locale.getAvailableLocales()) {
LocaleData d = LocaleData.get(l);
- // System.err.format("%20s %s %s %s\n", l, d.yesterday, d.today, d.tomorrow);
- // System.err.format("%20s %10s %10s\n", l, d.timeFormat_hm, d.timeFormat_Hm);
+ System.err.format("%20s %10s %10s\n", l, d.timeFormat_hm, d.timeFormat_Hm);
}
}
@@ -52,17 +57,6 @@
assertEquals("Sun", l.shortStandAloneWeekdayNames[1]);
assertEquals("S", l.tinyStandAloneWeekdayNames[1]);
- assertEquals("Yesterday", l.yesterday);
- assertEquals("Today", l.today);
- assertEquals("Tomorrow", l.tomorrow);
- }
-
- public void test_de_DE() throws Exception {
- LocaleData l = LocaleData.get(new Locale("de", "DE"));
-
- assertEquals("Gestern", l.yesterday);
- assertEquals("Heute", l.today);
- assertEquals("Morgen", l.tomorrow);
}
public void test_cs_CZ() throws Exception {
@@ -77,15 +71,6 @@
assertEquals("1", l.tinyStandAloneMonthNames[0]);
}
- public void test_ko_KR() throws Exception {
- LocaleData l = LocaleData.get(new Locale("ko", "KR"));
-
- // Ensure the fix for http://b/14493853 doesn't mangle Hangul.
- assertEquals("어제", l.yesterday);
- assertEquals("오늘", l.today);
- assertEquals("내일", l.tomorrow);
- }
-
public void test_ru_RU() throws Exception {
LocaleData l = LocaleData.get(new Locale("ru", "RU"));
@@ -146,4 +131,157 @@
public void testInvalidLocale() {
LocaleData.get(new Locale("invalidLocale"));
}
+
+ // BCP 47 language tags.
+ private static final String[] TEST_LANGUAGE_TAGS = new String[] {
+ "en-US",
+ "en-GB",
+ "ar-EG",
+ "zh-CN",
+ "zh-TW",
+ "nl-NL",
+ "fr-FR",
+ "de-DE",
+ "it-IT",
+ "ja-JP",
+ "ko-KR",
+ "pl-PL",
+ "pt-BR",
+ "ru-RU",
+ "es-ES",
+ "th-TH",
+ "tr-TR",
+ "es-419",
+ };
+
+ public void testInitLocaleData_icu4cConsistency() throws Exception {
+ // Don't test all available locales due to incorrect assumptions in the JNI test code
+ // calling ICU4C. The JNI test code came from libcore, but now moved into this test to load
+ // the locale data from ICU4C. The inappropriate assumptions are the below
+ // 1. Use uloc_getParent as fallback locale in ICU resource bundle format.
+ // uloc_getParent only truncates the locale ID string tp get parent, but doesn't use the
+ // parent-child relationships in the locale data.
+ // 2. Truncate single Unicode character, e.g. U+11136 CHAKMA DIGIT ZERO, into single high
+ // surrogate, e.g. 0xD804.
+ // 3. Does not consider alias in Root Locale
+ // For AM/PM markers, AmPmMarkersNarrow is specified in the Root Locale as the alias of
+ // "/LOCALE/calendar/gregorian/AmPmMarkersAbbr".
+
+ for (String languageTag : TEST_LANGUAGE_TAGS) {
+ Locale locale = Locale.forLanguageTag(languageTag);
+ LocaleData localeData = LocaleData.initLocaleData(locale);
+ Icu4cLocaleData testData = new Icu4cLocaleData();
+ assertTrue("Failed to load ICU4C data", initIcu4cLocaleData(locale.toLanguageTag(),
+ testData, Icu4cLocaleData.class));
+ assertLocaleDataEquals(locale, testData, localeData);
+ }
+ }
+
+ /**
+ * This function does not compare all fields in {@code Icu4cLocaleData} and {@code LocaleData}
+ * because some fields, e.g. patternSeparator, in {@Code LocaleData} has always implemented
+ * by ICU4J or always by ICU4C.
+ */
+ private static void assertLocaleDataEquals(Locale locale, Icu4cLocaleData testData,
+ LocaleData localeData) {
+ String baseMsg = "LocaleData provides different value in locale " + locale + " in the field:";
+ assertEquals(baseMsg + "minimalDaysInFirstWeek", testData.firstDayOfWeek, localeData.firstDayOfWeek);
+ assertEquals(baseMsg + "minimalDaysInFirstWeek", testData.minimalDaysInFirstWeek, localeData.minimalDaysInFirstWeek);
+ assertArrayEquals(baseMsg + "amPm", testData.amPm, localeData.amPm);
+ assertArrayEquals(baseMsg + "eras", testData.eras, localeData.eras);
+ assertArrayEquals(baseMsg + "longMonthNames", testData.longMonthNames, localeData.longMonthNames);
+ assertArrayEquals(baseMsg + "shortMonthNames", testData.shortMonthNames, localeData.shortMonthNames);
+ assertArrayEquals(baseMsg + "tinyMonthNames", testData.tinyMonthNames, localeData.tinyMonthNames);
+ assertArrayEquals(baseMsg + "longStandAloneMonthNames", testData.longStandAloneMonthNames, localeData.longStandAloneMonthNames);
+ assertArrayEquals(baseMsg + "shortStandAloneMonthNames", testData.shortStandAloneMonthNames, localeData.shortStandAloneMonthNames);
+ assertArrayEquals(baseMsg + "tinyStandAloneMonthNames", testData.tinyStandAloneMonthNames, localeData.tinyStandAloneMonthNames);
+ assertArrayEquals(baseMsg + "longWeekdayNames", testData.longWeekdayNames, localeData.longWeekdayNames);
+ assertArrayEquals(baseMsg + "shortWeekdayNames", testData.shortWeekdayNames, localeData.shortWeekdayNames);
+ assertArrayEquals(baseMsg + "tinyWeekdayNames", testData.tinyWeekdayNames, localeData.tinyWeekdayNames);
+ assertArrayEquals(baseMsg + "longStandAloneWeekdayNames", testData.longStandAloneWeekdayNames, localeData.longStandAloneWeekdayNames);
+ assertArrayEquals(baseMsg + "shortStandAloneWeekdayNames", testData.shortStandAloneWeekdayNames, localeData.shortStandAloneWeekdayNames);
+ assertArrayEquals(baseMsg + "tinyStandAloneWeekdayNames", testData.tinyStandAloneWeekdayNames, localeData.tinyStandAloneWeekdayNames);
+
+ assertEquals(baseMsg + "fullTimeFormat", testData.fullTimeFormat, localeData.fullTimeFormat);
+ assertEquals(baseMsg + "longTimeFormat", testData.longTimeFormat, localeData.longTimeFormat);
+ assertEquals(baseMsg + "mediumTimeFormat", testData.mediumTimeFormat, localeData.mediumTimeFormat);
+ assertEquals(baseMsg + "shortTimeFormat", testData.shortTimeFormat, localeData.shortTimeFormat);
+ assertEquals(baseMsg + "fullDateFormat", testData.fullDateFormat, localeData.fullDateFormat);
+ assertEquals(baseMsg + "longDateFormat", testData.longDateFormat, localeData.longDateFormat);
+ assertEquals(baseMsg + "mediumDateFormat", testData.mediumDateFormat, localeData.mediumDateFormat);
+ assertEquals(baseMsg + "shortDateFormat", testData.shortDateFormat, localeData.shortDateFormat);
+ assertEquals(baseMsg + "narrowAm", testData.narrowAm, localeData.narrowAm);
+ assertEquals(baseMsg + "narrowPm", testData.narrowPm, localeData.narrowPm);
+
+ assertEquals(baseMsg + "zeroDigit", testData.zeroDigit, localeData.zeroDigit);
+ assertEquals(baseMsg + "decimalSeparator", testData.decimalSeparator, localeData.decimalSeparator);
+ assertEquals(baseMsg + "groupingSeparator", testData.groupingSeparator, localeData.groupingSeparator);
+ assertEquals(baseMsg + "percent", testData.percent, localeData.percent);
+ assertEquals(baseMsg + "perMill", testData.perMill, localeData.perMill);
+ assertEquals(baseMsg + "monetarySeparator", testData.monetarySeparator, localeData.monetarySeparator);
+ assertEquals(baseMsg + "minusSign", testData.minusSign, localeData.minusSign);
+ assertEquals(baseMsg + "exponentSeparator", testData.exponentSeparator, localeData.exponentSeparator);
+ assertEquals(baseMsg + "infinity", testData.infinity, localeData.infinity);
+ assertEquals(baseMsg + "NaN", testData.NaN, localeData.NaN);
+ assertEquals(baseMsg + "numberPattern", testData.numberPattern, localeData.numberPattern);
+ assertEquals(baseMsg + "currencyPattern", testData.currencyPattern, localeData.currencyPattern);
+ assertEquals(baseMsg + "percentPattern", testData.percentPattern, localeData.percentPattern);
+ }
+
+ private static native boolean initIcu4cLocaleData(String languageTag,
+ Icu4cLocaleData icu4cLocaleData, Class<Icu4cLocaleData> Icu4cLocaleData);
+
+ private static class Icu4cLocaleData {
+ public Integer firstDayOfWeek;
+ public Integer minimalDaysInFirstWeek;
+
+ public String[] amPm; // "AM", "PM".
+ public String[] eras; // "BC", "AD".
+ public String[] longMonthNames; // "January", ...
+ public String[] shortMonthNames; // "Jan", ...
+ public String[] tinyMonthNames; // "J", ...
+ public String[] longStandAloneMonthNames; // "January", ...
+ public String[] shortStandAloneMonthNames; // "Jan", ...
+ public String[] tinyStandAloneMonthNames; // "J", ...
+ public String[] longWeekdayNames; // "Sunday", ...
+ public String[] shortWeekdayNames; // "Sun", ...
+ public String[] tinyWeekdayNames; // "S", ...
+ public String[] longStandAloneWeekdayNames; // "Sunday", ...
+ public String[] shortStandAloneWeekdayNames; // "Sun", ...
+ public String[] tinyStandAloneWeekdayNames; // "S", ...
+
+ public String fullTimeFormat;
+ public String longTimeFormat;
+ public String mediumTimeFormat;
+ public String shortTimeFormat;
+
+ public String fullDateFormat;
+ public String longDateFormat;
+ public String mediumDateFormat;
+ public String shortDateFormat;
+
+ // Used by TimePicker. Not currently used by UTS#35.
+ public String narrowAm; // "a".
+ public String narrowPm; // "p".
+
+ // Used by DecimalFormatSymbols.
+ public char zeroDigit;
+ public char decimalSeparator;
+ public char groupingSeparator;
+ public char patternSeparator;
+ public String percent;
+ public String perMill;
+ public char monetarySeparator;
+ public String minusSign;
+ public String exponentSeparator;
+ public String infinity;
+ public String NaN;
+
+ // Used by DecimalFormat and NumberFormat.
+ public String numberPattern;
+ public String currencyPattern;
+ public String percentPattern;
+
+ private Icu4cLocaleData() {}
+ }
}
diff --git a/luni/src/test/java/libcore/libcore/timezone/CountryTimeZonesTest.java b/luni/src/test/java/libcore/libcore/timezone/CountryTimeZonesTest.java
index cf32896..3fbd0fe 100644
--- a/luni/src/test/java/libcore/libcore/timezone/CountryTimeZonesTest.java
+++ b/luni/src/test/java/libcore/libcore/timezone/CountryTimeZonesTest.java
@@ -74,7 +74,7 @@
CountryTimeZones countryTimeZones = CountryTimeZones.createValidated(
"gb", "Europe/London", false /* defaultTimeZoneBoost */,
true /* everUsesUtc */, timeZoneMappings("Europe/London"), "test");
- assertTrue(countryTimeZones.isForCountryCode("gb"));
+ assertTrue(countryTimeZones.matchesCountryCode("gb"));
assertEquals("Europe/London", countryTimeZones.getDefaultTimeZoneId());
assertZoneEquals(zone("Europe/London"), countryTimeZones.getDefaultTimeZone());
assertEquals(timeZoneMappings("Europe/London"), countryTimeZones.getTimeZoneMappings());
@@ -114,13 +114,13 @@
}
@Test
- public void isForCountryCode() throws Exception {
+ public void matchesCountryCode() throws Exception {
CountryTimeZones countryTimeZones = CountryTimeZones.createValidated(
"gb", "Europe/London", false /* defaultTimeZoneBoost */, true /* everUsesUtc */,
timeZoneMappings("Europe/London"), "test");
- assertTrue(countryTimeZones.isForCountryCode("GB"));
- assertTrue(countryTimeZones.isForCountryCode("Gb"));
- assertTrue(countryTimeZones.isForCountryCode("gB"));
+ assertTrue(countryTimeZones.matchesCountryCode("GB"));
+ assertTrue(countryTimeZones.matchesCountryCode("Gb"));
+ assertTrue(countryTimeZones.matchesCountryCode("gB"));
}
@Test
diff --git a/luni/src/test/native/ScopedIcuLocale.h b/luni/src/test/native/ScopedIcuLocale.h
new file mode 100644
index 0000000..851de76
--- /dev/null
+++ b/luni/src/test/native/ScopedIcuLocale.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef SCOPED_ICU_LOCALE_H_included
+#define SCOPED_ICU_LOCALE_H_included
+
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include "unicode/locid.h"
+
+class ScopedIcuLocale {
+ public:
+ ScopedIcuLocale(JNIEnv* env, jstring javaLocaleName) : mEnv(env) {
+ mLocale.setToBogus();
+
+ if (javaLocaleName == NULL) {
+ jniThrowNullPointerException(mEnv, "javaLocaleName == null");
+ return;
+ }
+
+ const ScopedUtfChars localeName(env, javaLocaleName);
+ if (localeName.c_str() == NULL) {
+ return;
+ }
+
+ mLocale = icu::Locale::createFromName(localeName.c_str());
+ }
+
+ ~ScopedIcuLocale() {
+ }
+
+ bool valid() const {
+ return !mLocale.isBogus();
+ }
+
+ icu::Locale& locale() {
+ return mLocale;
+ }
+
+ private:
+ JNIEnv* const mEnv;
+ icu::Locale mLocale;
+
+ // Disallow copy and assignment.
+ ScopedIcuLocale(const ScopedIcuLocale&);
+ void operator=(const ScopedIcuLocale&);
+};
+
+#endif // SCOPED_ICU_LOCALE_H_included
diff --git a/luni/src/test/native/libcore_libcore_icu_LocaleDataTest.cpp b/luni/src/test/native/libcore_libcore_icu_LocaleDataTest.cpp
new file mode 100644
index 0000000..477142b
--- /dev/null
+++ b/luni/src/test/native/libcore_libcore_icu_LocaleDataTest.cpp
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2008 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_NDEBUG 1
+#define LOG_TAG "LocaleDataTest"
+
+#include <string.h>
+#include <memory>
+
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedStringChars.h>
+#include <nativehelper/ScopedUtfChars.h>
+
+#include "ScopedIcuLocale.h"
+#include "unicode/brkiter.h"
+#include "unicode/calendar.h"
+#include "unicode/dcfmtsym.h"
+#include "unicode/decimfmt.h"
+#include "unicode/dtfmtsym.h"
+#include "unicode/locid.h"
+#include "unicode/numfmt.h"
+#include "unicode/strenum.h"
+#include "unicode/ucasemap.h"
+#include "unicode/udat.h"
+#include "unicode/uloc.h"
+#include "unicode/ures.h"
+#include "unicode/ustring.h"
+
+
+static jclass icu4cLocaleDataClass = nullptr;
+
+class ScopedResourceBundle {
+ public:
+ explicit ScopedResourceBundle(UResourceBundle* bundle) : bundle_(bundle) {
+ }
+
+ ~ScopedResourceBundle() {
+ if (bundle_ != NULL) {
+ ures_close(bundle_);
+ }
+ }
+
+ UResourceBundle* get() {
+ return bundle_;
+ }
+
+ bool hasKey(const char* key) {
+ UErrorCode status = U_ZERO_ERROR;
+ ures_getStringByKey(bundle_, key, NULL, &status);
+ return U_SUCCESS(status);
+ }
+
+ private:
+ UResourceBundle* bundle_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedResourceBundle);
+};
+
+template <typename T>
+static jobject valueOf(JNIEnv* env, jclass c, const char* signature, const T& value) {
+ static jmethodID valueOfMethod = env->GetStaticMethodID(c, "valueOf", signature);
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+ jobject result = env->CallStaticObjectMethod(c, valueOfMethod, value);
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+ return result;
+}
+
+static jobject integerValueOf(JNIEnv* env, jint value) {
+ return valueOf(env, env->FindClass("java/lang/Integer"), "(I)Ljava/lang/Integer;", value);
+}
+
+
+static bool setIntegerField(JNIEnv* env, jobject obj, const char* fieldName, int value) {
+ ScopedLocalRef<jobject> integerValue(env, integerValueOf(env, value));
+ if (integerValue.get() == NULL) return false;
+ jfieldID fid = env->GetFieldID(icu4cLocaleDataClass, fieldName, "Ljava/lang/Integer;");
+ env->SetObjectField(obj, fid, integerValue.get());
+ return true;
+}
+
+static void setStringField(JNIEnv* env, jobject obj, const char* fieldName, jstring value) {
+ jfieldID fid = env->GetFieldID(icu4cLocaleDataClass, fieldName, "Ljava/lang/String;");
+ env->SetObjectField(obj, fid, value);
+ env->DeleteLocalRef(value);
+}
+
+static void setStringArrayField(JNIEnv* env, jobject obj, const char* fieldName, jobjectArray value) {
+ jfieldID fid = env->GetFieldID(icu4cLocaleDataClass, fieldName, "[Ljava/lang/String;");
+ env->SetObjectField(obj, fid, value);
+}
+
+static void setStringArrayField(JNIEnv* env, jobject obj, const char* fieldName, const icu::UnicodeString* valueArray, int32_t size) {
+ ScopedLocalRef<jobjectArray> result(env, env->NewObjectArray(size, env->FindClass("java/lang/String"), NULL));
+ for (int32_t i = 0; i < size ; i++) {
+ ScopedLocalRef<jstring> s(env, jniCreateString(env, valueArray[i].getBuffer(),valueArray[i].length()));
+ if (env->ExceptionCheck()) {
+ return;
+ }
+ env->SetObjectArrayElement(result.get(), i, s.get());
+ if (env->ExceptionCheck()) {
+ return;
+ }
+ }
+ setStringArrayField(env, obj, fieldName, result.get());
+}
+
+static void setStringField(JNIEnv* env, jobject obj, const char* fieldName, UResourceBundle* bundle, int index) {
+ UErrorCode status = U_ZERO_ERROR;
+ int charCount;
+ const UChar* chars;
+ UResourceBundle* currentBundle = ures_getByIndex(bundle, index, NULL, &status);
+ switch (ures_getType(currentBundle)) {
+ case URES_STRING:
+ chars = ures_getString(currentBundle, &charCount, &status);
+ break;
+ case URES_ARRAY:
+ // In case there is an array, Android currently only cares about the
+ // first string of that array, the rest of the array is used by ICU
+ // for additional data ignored by Android.
+ chars = ures_getStringByIndex(currentBundle, 0, &charCount, &status);
+ break;
+ default:
+ status = U_INVALID_FORMAT_ERROR;
+ }
+ ures_close(currentBundle);
+
+ if (U_SUCCESS(status)) {
+ setStringField(env, obj, fieldName, jniCreateString(env, chars, charCount));
+ } else {
+ ALOGE("Error setting String field %s from ICU resource (index %d): %s", fieldName, index, u_errorName(status));
+ }
+}
+
+static void setCharField(JNIEnv* env, jobject obj, const char* fieldName, const icu::UnicodeString& value) {
+ if (value.length() == 0) {
+ return;
+ }
+ jfieldID fid = env->GetFieldID(icu4cLocaleDataClass, fieldName, "C");
+ env->SetCharField(obj, fid, value.charAt(0));
+}
+
+static void setStringField(JNIEnv* env, jobject obj, const char* fieldName, const icu::UnicodeString& value) {
+ const UChar* chars = value.getBuffer();
+ setStringField(env, obj, fieldName, jniCreateString(env, chars, value.length()));
+}
+
+static void setNumberPatterns(JNIEnv* env, jobject obj, icu::Locale& locale) {
+ UErrorCode status = U_ZERO_ERROR;
+
+ icu::UnicodeString pattern;
+ std::unique_ptr<icu::DecimalFormat> fmt(static_cast<icu::DecimalFormat*>(icu::NumberFormat::createInstance(locale, UNUM_CURRENCY, status)));
+ pattern = fmt->toPattern(pattern.remove());
+ setStringField(env, obj, "currencyPattern", pattern);
+
+ fmt.reset(static_cast<icu::DecimalFormat*>(icu::NumberFormat::createInstance(locale, UNUM_DECIMAL, status)));
+ pattern = fmt->toPattern(pattern.remove());
+ setStringField(env, obj, "numberPattern", pattern);
+
+ fmt.reset(static_cast<icu::DecimalFormat*>(icu::NumberFormat::createInstance(locale, UNUM_PERCENT, status)));
+ pattern = fmt->toPattern(pattern.remove());
+ setStringField(env, obj, "percentPattern", pattern);
+}
+
+static void setDecimalFormatSymbolsData(JNIEnv* env, jobject obj, icu::Locale& locale) {
+ UErrorCode status = U_ZERO_ERROR;
+ icu::DecimalFormatSymbols dfs(locale, status);
+
+ setCharField(env, obj, "decimalSeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kDecimalSeparatorSymbol));
+ setCharField(env, obj, "groupingSeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kGroupingSeparatorSymbol));
+ setCharField(env, obj, "patternSeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kPatternSeparatorSymbol));
+ setStringField(env, obj, "percent", dfs.getSymbol(icu::DecimalFormatSymbols::kPercentSymbol));
+ setStringField(env, obj, "perMill", dfs.getSymbol(icu::DecimalFormatSymbols::kPerMillSymbol));
+ setCharField(env, obj, "monetarySeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kMonetarySeparatorSymbol));
+ setStringField(env, obj, "minusSign", dfs.getSymbol(icu::DecimalFormatSymbols:: kMinusSignSymbol));
+ setStringField(env, obj, "exponentSeparator", dfs.getSymbol(icu::DecimalFormatSymbols::kExponentialSymbol));
+ setStringField(env, obj, "infinity", dfs.getSymbol(icu::DecimalFormatSymbols::kInfinitySymbol));
+ setStringField(env, obj, "NaN", dfs.getSymbol(icu::DecimalFormatSymbols::kNaNSymbol));
+ setCharField(env, obj, "zeroDigit", dfs.getSymbol(icu::DecimalFormatSymbols::kZeroDigitSymbol));
+}
+
+
+// Iterates up through the locale hierarchy. So "en_US" would return "en_US", "en", "".
+class LocaleNameIterator {
+ public:
+ LocaleNameIterator(const char* locale_name, UErrorCode& status) : status_(status), has_next_(true) {
+ strcpy(locale_name_, locale_name);
+ locale_name_length_ = strlen(locale_name_);
+ }
+
+ const char* Get() {
+ return locale_name_;
+ }
+
+ bool HasNext() {
+ return has_next_;
+ }
+
+ void Up() {
+ if (locale_name_length_ == 0) {
+ has_next_ = false;
+ } else {
+ locale_name_length_ = uloc_getParent(locale_name_, locale_name_, sizeof(locale_name_), &status_);
+ }
+ }
+
+ private:
+ UErrorCode& status_;
+ bool has_next_;
+ char locale_name_[ULOC_FULLNAME_CAPACITY];
+ int32_t locale_name_length_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocaleNameIterator);
+};
+
+static bool getAmPmMarkersNarrow(JNIEnv* env, jobject localeData, const char* locale_name) {
+ UErrorCode status = U_ZERO_ERROR;
+ ScopedResourceBundle root(ures_open(NULL, locale_name, &status));
+ if (U_FAILURE(status)) {
+ return false;
+ }
+ ScopedResourceBundle calendar(ures_getByKey(root.get(), "calendar", NULL, &status));
+ if (U_FAILURE(status)) {
+ return false;
+ }
+ ScopedResourceBundle gregorian(ures_getByKey(calendar.get(), "gregorian", NULL, &status));
+ if (U_FAILURE(status)) {
+ return false;
+ }
+ ScopedResourceBundle amPmMarkersNarrow(ures_getByKey(gregorian.get(), "AmPmMarkersNarrow", NULL, &status));
+ if (U_FAILURE(status)) {
+ return false;
+ }
+ setStringField(env, localeData, "narrowAm", amPmMarkersNarrow.get(), 0);
+ setStringField(env, localeData, "narrowPm", amPmMarkersNarrow.get(), 1);
+ return true;
+}
+
+static bool getDateTimePatterns(JNIEnv* env, jobject localeData, const char* locale_name) {
+ UErrorCode status = U_ZERO_ERROR;
+ ScopedResourceBundle root(ures_open(NULL, locale_name, &status));
+ if (U_FAILURE(status)) {
+ return false;
+ }
+ ScopedResourceBundle calendar(ures_getByKey(root.get(), "calendar", NULL, &status));
+ if (U_FAILURE(status)) {
+ return false;
+ }
+ ScopedResourceBundle gregorian(ures_getByKey(calendar.get(), "gregorian", NULL, &status));
+ if (U_FAILURE(status)) {
+ return false;
+ }
+ ScopedResourceBundle dateTimePatterns(ures_getByKey(gregorian.get(), "DateTimePatterns", NULL, &status));
+ if (U_FAILURE(status)) {
+ return false;
+ }
+ setStringField(env, localeData, "fullTimeFormat", dateTimePatterns.get(), 0);
+ setStringField(env, localeData, "longTimeFormat", dateTimePatterns.get(), 1);
+ setStringField(env, localeData, "mediumTimeFormat", dateTimePatterns.get(), 2);
+ setStringField(env, localeData, "shortTimeFormat", dateTimePatterns.get(), 3);
+ setStringField(env, localeData, "fullDateFormat", dateTimePatterns.get(), 4);
+ setStringField(env, localeData, "longDateFormat", dateTimePatterns.get(), 5);
+ setStringField(env, localeData, "mediumDateFormat", dateTimePatterns.get(), 6);
+ setStringField(env, localeData, "shortDateFormat", dateTimePatterns.get(), 7);
+ return true;
+}
+
+extern "C" jboolean Java_libcore_libcore_icu_LocaleDataTest_initIcu4cLocaleData(JNIEnv* env,
+ jclass, jstring javaLanguageTag, jobject icu4cLocaleData, jobject dataClass) {
+ if (icu4cLocaleDataClass == nullptr) {
+ // It's okay to hold the class in the test.
+ icu4cLocaleDataClass = reinterpret_cast<jclass>(env->NewGlobalRef(dataClass));
+ }
+
+ // alias pointer
+ jobject localeData = icu4cLocaleData;
+
+ ScopedUtfChars languageTag(env, javaLanguageTag);
+ if (languageTag.c_str() == NULL) {
+ return JNI_FALSE;
+ }
+ if (languageTag.size() >= ULOC_FULLNAME_CAPACITY) {
+ return JNI_FALSE; // ICU has a fixed-length limit.
+ }
+
+ ScopedIcuLocale icuLocale(env, javaLanguageTag);
+ if (!icuLocale.valid()) {
+ return JNI_FALSE;
+ }
+
+ // Get the DateTimePatterns.
+ UErrorCode status = U_ZERO_ERROR;
+ bool foundDateTimePatterns = false;
+ for (LocaleNameIterator it(icuLocale.locale().getBaseName(), status); it.HasNext(); it.Up()) {
+ if (getDateTimePatterns(env, localeData, it.Get())) {
+ foundDateTimePatterns = true;
+ break;
+ }
+ }
+ if (!foundDateTimePatterns) {
+ ALOGE("Couldn't find ICU DateTimePatterns for %s", languageTag.c_str());
+ return JNI_FALSE;
+ }
+
+ // Get the narrow "AM" and "PM" strings.
+ bool foundAmPmMarkersNarrow = false;
+ for (LocaleNameIterator it(icuLocale.locale().getBaseName(), status); it.HasNext(); it.Up()) {
+ if (getAmPmMarkersNarrow(env, localeData, it.Get())) {
+ foundAmPmMarkersNarrow = true;
+ break;
+ }
+ }
+ if (!foundAmPmMarkersNarrow) {
+ ALOGE("Couldn't find ICU AmPmMarkersNarrow for %s", languageTag.c_str());
+ return JNI_FALSE;
+ }
+
+ status = U_ZERO_ERROR;
+ std::unique_ptr<icu::Calendar> cal(icu::Calendar::createInstance(icuLocale.locale(), status));
+ if (U_FAILURE(status)) {
+ return JNI_FALSE;
+ }
+ if (!setIntegerField(env, localeData, "firstDayOfWeek", cal->getFirstDayOfWeek())) {
+ return JNI_FALSE;
+ }
+ if (!setIntegerField(env, localeData, "minimalDaysInFirstWeek", cal->getMinimalDaysInFirstWeek())) {
+ return JNI_FALSE;
+ }
+
+ // Get DateFormatSymbols.
+ status = U_ZERO_ERROR;
+ icu::DateFormatSymbols dateFormatSym(icuLocale.locale(), status);
+ if (U_FAILURE(status)) {
+ return JNI_FALSE;
+ }
+
+ // Get AM/PM and BC/AD.
+ int32_t count = 0;
+ const icu::UnicodeString* amPmStrs = dateFormatSym.getAmPmStrings(count);
+ setStringArrayField(env, localeData, "amPm", amPmStrs, count);
+ const icu::UnicodeString* erasStrs = dateFormatSym.getEras(count);
+ setStringArrayField(env, localeData, "eras", erasStrs, count);
+
+ const icu::UnicodeString* longMonthNames =
+ dateFormatSym.getMonths(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::WIDE);
+ setStringArrayField(env, localeData, "longMonthNames", longMonthNames, count);
+ const icu::UnicodeString* shortMonthNames =
+ dateFormatSym.getMonths(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::ABBREVIATED);
+ setStringArrayField(env, localeData, "shortMonthNames", shortMonthNames, count);
+ const icu::UnicodeString* tinyMonthNames =
+ dateFormatSym.getMonths(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::NARROW);
+ setStringArrayField(env, localeData, "tinyMonthNames", tinyMonthNames, count);
+ const icu::UnicodeString* longWeekdayNames =
+ dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::WIDE);
+ setStringArrayField(env, localeData, "longWeekdayNames", longWeekdayNames, count);
+ const icu::UnicodeString* shortWeekdayNames =
+ dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::ABBREVIATED);
+ setStringArrayField(env, localeData, "shortWeekdayNames", shortWeekdayNames, count);
+ const icu::UnicodeString* tinyWeekdayNames =
+ dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::FORMAT, icu::DateFormatSymbols::NARROW);
+ setStringArrayField(env, localeData, "tinyWeekdayNames", tinyWeekdayNames, count);
+
+ const icu::UnicodeString* longStandAloneMonthNames =
+ dateFormatSym.getMonths(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::WIDE);
+ setStringArrayField(env, localeData, "longStandAloneMonthNames", longStandAloneMonthNames, count);
+ const icu::UnicodeString* shortStandAloneMonthNames =
+ dateFormatSym.getMonths(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::ABBREVIATED);
+ setStringArrayField(env, localeData, "shortStandAloneMonthNames", shortStandAloneMonthNames, count);
+ const icu::UnicodeString* tinyStandAloneMonthNames =
+ dateFormatSym.getMonths(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::NARROW);
+ setStringArrayField(env, localeData, "tinyStandAloneMonthNames", tinyStandAloneMonthNames, count);
+ const icu::UnicodeString* longStandAloneWeekdayNames =
+ dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::WIDE);
+ setStringArrayField(env, localeData, "longStandAloneWeekdayNames", longStandAloneWeekdayNames, count);
+ const icu::UnicodeString* shortStandAloneWeekdayNames =
+ dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::ABBREVIATED);
+ setStringArrayField(env, localeData, "shortStandAloneWeekdayNames", shortStandAloneWeekdayNames, count);
+ const icu::UnicodeString* tinyStandAloneWeekdayNames =
+ dateFormatSym.getWeekdays(count, icu::DateFormatSymbols::STANDALONE, icu::DateFormatSymbols::NARROW);
+ setStringArrayField(env, localeData, "tinyStandAloneWeekdayNames", tinyStandAloneWeekdayNames, count);
+
+ status = U_ZERO_ERROR;
+
+ // For numberPatterns and symbols.
+ setNumberPatterns(env, localeData, icuLocale.locale());
+ setDecimalFormatSymbolsData(env, localeData, icuLocale.locale());
+
+ return JNI_TRUE;
+}
diff --git a/mmodules/core_platform_api/api/platform/current-api.txt b/mmodules/core_platform_api/api/platform/current-api.txt
index 74d536f..c26dce3 100644
--- a/mmodules/core_platform_api/api/platform/current-api.txt
+++ b/mmodules/core_platform_api/api/platform/current-api.txt
@@ -988,8 +988,6 @@
field public String[] tinyStandAloneMonthNames;
field public String[] tinyStandAloneWeekdayNames;
field public String[] tinyWeekdayNames;
- field public String today;
- field public String yesterday;
field public char zeroDigit;
}
@@ -1109,9 +1107,9 @@
method public java.util.List<libcore.timezone.CountryTimeZones.TimeZoneMapping> getTimeZoneMappings();
method public boolean hasUtcZone(long);
method public boolean isDefaultTimeZoneBoosted();
- method public boolean isForCountryCode(String);
method public libcore.timezone.CountryTimeZones.OffsetResult lookupByOffsetWithBias(long, android.icu.util.TimeZone, int, boolean);
method public libcore.timezone.CountryTimeZones.OffsetResult lookupByOffsetWithBias(long, android.icu.util.TimeZone, int);
+ method public boolean matchesCountryCode(String);
}
public static final class CountryTimeZones.OffsetResult {
diff --git a/ojluni/src/main/java/java/io/File.java b/ojluni/src/main/java/java/io/File.java
index 98956ca..0037534 100644
--- a/ojluni/src/main/java/java/io/File.java
+++ b/ojluni/src/main/java/java/io/File.java
@@ -518,7 +518,7 @@
/* -- Path operations -- */
- // Android-changed: Android-specific path information
+ // Android-changed: Android-specific path information.
/**
* Tests whether this abstract pathname is absolute. The definition of
* absolute pathname is system dependent. On Android, absolute paths start with
@@ -531,7 +531,7 @@
return fs.isAbsolute(this);
}
- // Android-changed: Android-specific path information
+ // Android-changed: Android-specific path information.
/**
* Returns the absolute path of this file. An absolute path is a path that starts at a root
* of the file system. On Android, there is only one root: {@code /}.
@@ -737,8 +737,7 @@
/* -- Attribute accessors -- */
- // Android-changed. Removed javadoc comment about special privileges
- // that doesn't make sense on android
+ // Android-changed: Removed inapplicable javadoc comment about special privileges.
/**
* Tests whether the application can read the file denoted by this
* abstract pathname.
@@ -763,8 +762,7 @@
return fs.checkAccess(this, FileSystem.ACCESS_READ);
}
- // Android-changed. Removed javadoc comment about special privileges
- // that doesn't make sense on android
+ // Android-changed: Removed inapplicable javadoc comment about special privileges.
/**
* Tests whether the application can modify the file denoted by this
* abstract pathname.
@@ -1450,8 +1448,7 @@
return fs.setLastModifiedTime(this, time);
}
- // Android-changed. Removed javadoc comment about special privileges
- // that doesn't make sense on Android.
+ // Android-changed: Removed inapplicable javadoc comment about special privileges.
/**
* Marks the file or directory named by this abstract pathname so that
* only read operations are allowed. After invoking this method the file
@@ -1480,8 +1477,7 @@
return fs.setReadOnly(this);
}
- // Android-changed. Removed javadoc comment about special privileges
- // that doesn't make sense on Android.
+ // Android-changed: Removed inapplicable javadoc comment about special privileges.
/**
* Sets the owner's or everybody's write permission for this abstract
* pathname.
@@ -1523,8 +1519,7 @@
return fs.setPermission(this, FileSystem.ACCESS_WRITE, writable, ownerOnly);
}
- // Android-changed. Removed javadoc comment about special privileges
- // that doesn't make sense on Android.
+ // Android-changed: Removed inapplicable javadoc comment about special privileges.
/**
* A convenience method to set the owner's write permission for this abstract
* pathname.
@@ -1554,8 +1549,7 @@
return setWritable(writable, true);
}
- // Android-changed. Removed javadoc comment about special privileges
- // that doesn't make sense on Android.
+ // Android-changed: Removed inapplicable javadoc comment about special privileges.
/**
* Sets the owner's or everybody's read permission for this abstract
* pathname.
@@ -1600,8 +1594,7 @@
return fs.setPermission(this, FileSystem.ACCESS_READ, readable, ownerOnly);
}
- // Android-changed. Removed javadoc comment about special privileges
- // that doesn't make sense on Android.
+ // Android-changed: Removed inapplicable javadoc comment about special privileges.
/**
* A convenience method to set the owner's read permission for this abstract
* pathname.
@@ -1634,8 +1627,7 @@
return setReadable(readable, true);
}
- // Android-changed. Removed javadoc comment about special privileges
- // that doesn't make sense on Android.
+ // Android-changed: Removed inapplicable javadoc comment about special privileges.
/**
* Sets the owner's or everybody's execute permission for this abstract
* pathname.
@@ -1680,8 +1672,7 @@
return fs.setPermission(this, FileSystem.ACCESS_EXECUTE, executable, ownerOnly);
}
- // Android-changed. Removed javadoc comment about special privileges
- // that doesn't make sense on Android.
+ // Android-changed: Removed inapplicable javadoc comment about special privileges.
/**
* A convenience method to set the owner's execute permission for this
* abstract pathname.
@@ -1714,8 +1705,7 @@
return setExecutable(executable, true);
}
- // Android-changed. Removed javadoc comment about special privileges
- // that doesn't make sense on Android.
+ // Android-changed: Removed inapplicable javadoc comment about special privileges.
/**
* Tests whether the application can execute the file denoted by this
* abstract pathname.
@@ -1873,8 +1863,7 @@
private static class TempDirectory {
private TempDirectory() { }
- // Android-changed: Don't cache java.io.tmpdir value
- // temporary directory location.
+ // Android-changed: Don't cache java.io.tmpdir value temporary directory location.
/*
private static final File tmpdir = new File(AccessController
.doPrivileged(new GetPropertyAction("java.io.tmpdir")));
@@ -1888,8 +1877,8 @@
static File generateFile(String prefix, String suffix, File dir)
throws IOException
{
- // Android-changed: Use Math.randomIntInternal. This (pseudo) random number
- // is initialized post-fork
+ // Android-changed: Use Math.randomIntInternal.
+ // This (pseudo) random number is initialized post-fork.
long n = Math.randomLongInternal();
if (n == Long.MIN_VALUE) {
@@ -1898,7 +1887,7 @@
n = Math.abs(n);
}
- // Android-changed: Reject invalid file prefixes
+ // Android-changed: Reject invalid file prefixes.
// Use only the file name from the supplied prefix
// prefix = (new File(prefix)).getName();
diff --git a/ojluni/src/main/java/java/io/FileDescriptor.java b/ojluni/src/main/java/java/io/FileDescriptor.java
index ed3ebfe..8584020 100644
--- a/ojluni/src/main/java/java/io/FileDescriptor.java
+++ b/ojluni/src/main/java/java/io/FileDescriptor.java
@@ -47,11 +47,11 @@
* @since JDK1.0
*/
public final class FileDescriptor {
- // Android-changed: Removed parent reference counting. Creator is responsible for closing
- // the file descriptor.
+ // Android-changed: Removed parent reference counting.
+ // The creator is responsible for closing the file descriptor.
- // Android-changed: Renamed fd to descriptor to avoid issues with JNI/reflection
- // fetching the descriptor value.
+ // Android-changed: Renamed fd to descriptor.
+ // Renaming is to avoid issues with JNI/reflection fetching the descriptor value.
private int descriptor;
// Android-added: Track fd owner to guard against accidental closure. http://b/110100358
@@ -82,8 +82,7 @@
*
* @see java.lang.System#in
*/
- // Android-changed: Duplicates of FDs needed for RuntimeInit#redirectLogStreams
- public static final FileDescriptor in = dupFd(0);
+ public static final FileDescriptor in = new FileDescriptor(0);
/**
* A handle to the standard output stream. Usually, this file
@@ -91,8 +90,7 @@
* known as <code>System.out</code>.
* @see java.lang.System#out
*/
- // Android-changed: Duplicates of FDs needed for RuntimeInit#redirectLogStreams
- public static final FileDescriptor out = dupFd(1);
+ public static final FileDescriptor out = new FileDescriptor(1);
/**
* A handle to the standard error stream. Usually, this file
@@ -101,8 +99,7 @@
*
* @see java.lang.System#err
*/
- // Android-changed: Duplicates of FDs needed for RuntimeInit#redirectLogStreams
- public static final FileDescriptor err = dupFd(2);
+ public static final FileDescriptor err = new FileDescriptor(2);
/**
* Tests if this file descriptor object is valid.
@@ -145,11 +142,11 @@
*/
public native void sync() throws SyncFailedException;
- // Android-removed: initIDs not used to allow compile-time intialization
+ // Android-removed: initIDs not used to allow compile-time initialization.
/* This routine initializes JNI field offsets for the class */
//private static native void initIDs();
- // Android-added: Needed for framework to access descriptor value
+ // Android-added: Needed for framework to access descriptor value.
/**
* Returns the int descriptor. It's highly unlikely you should be calling this. Please discuss
* your needs with a libcore maintainer before using this method.
@@ -159,7 +156,7 @@
return descriptor;
}
- // Android-added: Needed for framework to access descriptor value
+ // Android-added: Needed for framework to access descriptor value.
/**
* Sets the int descriptor. It's highly unlikely you should be calling this. Please discuss
* your needs with a libcore maintainer before using this method.
@@ -169,6 +166,26 @@
this.descriptor = fd;
}
+ // BEGIN Android-added: Method to clone standard file descriptors.
+ // Required as a consequence of RuntimeInit#redirectLogStreams. Cloning is used in
+ // ZygoteHooks.onEndPreload().
+ /**
+ * Clones the current native file descriptor and uses this for this FileDescriptor instance.
+ *
+ * This method does not close the current native file descriptor.
+ *
+ * @hide internal use only
+ */
+ public void cloneForFork() {
+ try {
+ int newDescriptor = Os.fcntlInt(this, F_DUPFD_CLOEXEC, 0);
+ this.descriptor = newDescriptor;
+ } catch (ErrnoException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ // END Android-added: Method to clone standard file descriptors.
+
// BEGIN Android-added: Methods to enable ownership enforcement of Unix file descriptors.
/**
* Returns the owner ID of this FileDescriptor. It's highly unlikely you should be calling this.
@@ -206,7 +223,7 @@
}
// END Android-added: Methods to enable ownership enforcement of Unix file descriptors.
- // Android-added: Needed for framework to test if it's a socket
+ // Android-added: Needed for framework to test if it's a socket.
/**
* @hide internal use only
*/
@@ -214,15 +231,6 @@
return isSocket(descriptor);
}
- // Android-added: Needed for RuntimeInit#redirectLogStreams.
- private static FileDescriptor dupFd(int fd) {
- try {
- return new FileDescriptor(Os.fcntlInt(new FileDescriptor(fd), F_DUPFD_CLOEXEC, 0));
- } catch (ErrnoException e) {
- throw new RuntimeException(e);
- }
- }
-
private static native boolean isSocket(int descriptor);
// Set up JavaIOFileDescriptorAccess in SharedSecrets
static {
@@ -246,5 +254,5 @@
}
);
}
-// Android-removed: Removed method required for parents reference counting
+// Android-removed: Removed method required for parents reference counting.
}
diff --git a/ojluni/src/main/java/java/io/ObjectOutputStream.java b/ojluni/src/main/java/java/io/ObjectOutputStream.java
index ccec944..1f7f901 100644
--- a/ojluni/src/main/java/java/io/ObjectOutputStream.java
+++ b/ojluni/src/main/java/java/io/ObjectOutputStream.java
@@ -1223,7 +1223,7 @@
writeClass((Class) obj, unshared);
} else if (obj instanceof ObjectStreamClass) {
writeClassDesc((ObjectStreamClass) obj, unshared);
- // END Android-changed: Make Class and ObjectStreamClass replaceable.
+ // END Android-changed: Make Class and ObjectStreamClass replaceable.
} else if (obj instanceof String) {
writeString((String) obj, unshared);
} else if (cl.isArray()) {
@@ -1865,7 +1865,7 @@
return blkmode;
}
- // BEGIN Android-added: Warning about writing to closed ObjectOutputStream
+ // BEGIN Android-added: Warning about writing to closed ObjectOutputStream.
/**
* Warns if the stream has been closed.
*
@@ -1884,7 +1884,7 @@
warnOnceWhenWriting = false;
}
}
- // END Android-added: Warning about writing to closed ObjectOutputStream
+ // END Android-added: Warning about writing to closed ObjectOutputStream.
/* ----------------- generic output stream methods ----------------- */
/*
@@ -1916,7 +1916,7 @@
public void close() throws IOException {
flush();
out.close();
- // Android-added: Warning about writing to closed ObjectOutputStream
+ // Android-added: Warning about writing to closed ObjectOutputStream.
warnOnceWhenWriting = true;
}
@@ -1932,7 +1932,7 @@
if (!(copy || blkmode)) { // write directly
drain();
out.write(b, off, len);
- // Android-added: Warning about writing to closed ObjectOutputStream
+ // Android-added: Warning about writing to closed ObjectOutputStream.
warnIfClosed();
return;
}
@@ -1955,7 +1955,7 @@
len -= wlen;
}
}
- // Android-added: Warning about writing to closed ObjectOutputStream
+ // Android-added: Warning about writing to closed ObjectOutputStream.
warnIfClosed();
}
@@ -1972,7 +1972,7 @@
}
out.write(buf, 0, pos);
pos = 0;
- // Android-added: Warning about writing to closed ObjectOutputStream
+ // Android-added: Warning about writing to closed ObjectOutputStream.
warnIfClosed();
}
@@ -1991,7 +1991,7 @@
Bits.putInt(hbuf, 1, len);
out.write(hbuf, 0, 5);
}
- // Android-added: Warning about writing to closed ObjectOutputStream
+ // Android-added: Warning about writing to closed ObjectOutputStream.
warnIfClosed();
}
diff --git a/ojluni/src/main/java/java/io/ObjectStreamClass.java b/ojluni/src/main/java/java/io/ObjectStreamClass.java
index a88ad63..9a1a48f 100644
--- a/ojluni/src/main/java/java/io/ObjectStreamClass.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamClass.java
@@ -1425,12 +1425,12 @@
{
return null;
}
- // BEGIN Android-changed: Serialization constructor obtained differently
+ // BEGIN Android-changed: Serialization constructor obtained differently.
// cons = reflFactory.newConstructorForSerialization(cl, cons);
if (cons.getDeclaringClass() != cl) {
cons = cons.serializationCopy(cons.getDeclaringClass(), cl);
}
- // END Android-changed: Serialization constructor obtained differently
+ // END Android-changed: Serialization constructor obtained differently.
cons.setAccessible(true);
return cons;
} catch (NoSuchMethodException ex) {
@@ -1797,7 +1797,7 @@
}
}
- // BEGIN Android-changed: Fix/log clinit serialization workaround b/29064453
+ // BEGIN Android-changed: Fix/log clinit serialization workaround. b/29064453
// Prior to SDK 24 hasStaticInitializer() would return true if the superclass had a
// static initializer, that was contrary to the specification. In SDK 24 the default
// behavior was corrected but the old behavior was preserved for apps that targeted 23
@@ -1817,7 +1817,7 @@
// instructions to the developer on how to fix the problems.
warnIncompatibleSUIDChange = true;
}
- // END Android-changed: Fix/log clinit serialization workaround b/29064453
+ // END Android-changed: Fix/log clinit serialization workaround. b/29064453
dout.writeUTF("<clinit>");
dout.writeInt(Modifier.STATIC);
dout.writeUTF("()V");
@@ -1882,14 +1882,14 @@
for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
hash = (hash << 8) | (hashBytes[i] & 0xFF);
}
- // BEGIN Android-added: Fix/log clinit serialization workaround b/29064453
+ // BEGIN Android-added: Fix/log clinit serialization workaround. b/29064453
// ObjectStreamClass instances are cached per Class and caches its default
// serialVersionUID so it will only log one message per class per app process
// irrespective of the number of times the class is serialized.
if (warnIncompatibleSUIDChange) {
suidCompatibilityListener.warnDefaultSUIDTargetVersionDependent(cl, hash);
}
- // END Android-added: Fix/log clinit serialization workaround b/29064453
+ // END Android-added: Fix/log clinit serialization workaround. b/29064453
return hash;
} catch (IOException ex) {
throw new InternalError(ex);
@@ -1898,7 +1898,7 @@
}
}
- // BEGIN Android-changed: Fix/log clinit serialization workaround b/29064453
+ // BEGIN Android-changed: Fix/log clinit serialization workaround. b/29064453
/**
* Created for testing as there is no nice way to detect when a message is logged.
*
@@ -1943,7 +1943,7 @@
*/
private native static boolean hasStaticInitializer(
Class<?> cl, boolean inheritStaticInitializer);
- // END Android-changed: Fix/log clinit serialization workaround b/29064453
+ // END Android-changed: Fix/log clinit serialization workaround. b/29064453
/**
* Class for computing and caching field/constructor/method signatures
diff --git a/ojluni/src/main/java/java/lang/Class.java b/ojluni/src/main/java/java/lang/Class.java
index f792248..478c339 100644
--- a/ojluni/src/main/java/java/lang/Class.java
+++ b/ojluni/src/main/java/java/lang/Class.java
@@ -1135,7 +1135,7 @@
* that class is a local or anonymous class; otherwise {@code null}.
* @since 1.5
*/
- // Android-changed: Removed SecurityException
+ // Android-changed: Removed SecurityException.
public Method getEnclosingMethod() {
if (classNameImpliesTopLevel()) {
return null;
@@ -1157,7 +1157,7 @@
* that class is a local or anonymous class; otherwise {@code null}.
* @since 1.5
*/
- // Android-changed: Removed SecurityException
+ // Android-changed: Removed SecurityException.
public Constructor<?> getEnclosingConstructor() {
if (classNameImpliesTopLevel()) {
return null;
@@ -1184,7 +1184,7 @@
* @return the declaring class for this class
* @since JDK1.1
*/
- // Android-changed: Removed SecurityException
+ // Android-changed: Removed SecurityException.
@FastNative
public native Class<?> getDeclaringClass();
@@ -1195,7 +1195,7 @@
* @return the immediately enclosing class of the underlying class
* @since 1.5
*/
- // Android-changed: Removed SecurityException
+ // Android-changed: Removed SecurityException.
@FastNative
public native Class<?> getEnclosingClass();
@@ -1593,7 +1593,7 @@
* @jls 8.2 Class Members
* @jls 8.3 Field Declarations
*/
- // Android-changed: Removed SecurityException
+ // Android-changed: Removed SecurityException.
public Field getField(String name)
throws NoSuchFieldException {
if (name == null) {
@@ -1764,7 +1764,7 @@
*
* @since JDK1.1
*/
- // Android-changed: Removed SecurityException
+ // Android-changed: Removed SecurityException.
@FastNative
public native Class<?>[] getDeclaredClasses();
@@ -1810,7 +1810,7 @@
* @jls 8.2 Class Members
* @jls 8.3 Field Declarations
*/
- // Android-changed: Removed SecurityException
+ // Android-changed: Removed SecurityException.
@FastNative
public native Field[] getDeclaredFields();
@@ -1986,7 +1986,7 @@
* @jls 8.2 Class Members
* @jls 8.3 Field Declarations
*/
- // Android-changed: Removed SecurityException
+ // Android-changed: Removed SecurityException.
@FastNative
public native Field getDeclaredField(String name) throws NoSuchFieldException;
diff --git a/ojluni/src/main/java/java/lang/System.java b/ojluni/src/main/java/java/lang/System.java
index 9cec068..a67bb0b 100644
--- a/ojluni/src/main/java/java/lang/System.java
+++ b/ojluni/src/main/java/java/lang/System.java
@@ -983,12 +983,13 @@
p.put("java.vm.version", runtime.vmVersion());
+ String userName;
try {
- StructPasswd passwd = Libcore.os.getpwuid(Libcore.os.getuid());
- p.put("user.name", passwd.pw_name);
+ userName = Libcore.os.getpwuid(Libcore.os.getuid()).pw_name;
} catch (ErrnoException exception) {
- throw new AssertionError(exception);
+ userName = "unknown";
}
+ p.put("user.name", userName);
StructUtsname info = Libcore.os.uname();
p.put("os.arch", info.machine);
diff --git a/ojluni/src/main/java/java/lang/Thread.java b/ojluni/src/main/java/java/lang/Thread.java
index d06db86..0ff38a6 100644
--- a/ojluni/src/main/java/java/lang/Thread.java
+++ b/ojluni/src/main/java/java/lang/Thread.java
@@ -485,10 +485,10 @@
this.name = name;
Thread parent = currentThread();
- // Android-removed: SecurityManager stubbed out on Android
+ // Android-removed: SecurityManager stubbed out on Android.
// SecurityManager security = System.getSecurityManager();
if (g == null) {
- // Android-changed: SecurityManager stubbed out on Android
+ // Android-changed: SecurityManager stubbed out on Android.
/*
/* Determine if it's an applet or not *
@@ -506,7 +506,7 @@
// }
}
- // Android-removed: SecurityManager stubbed out on Android
+ // Android-removed: SecurityManager stubbed out on Android.
/*
/* checkAccess regardless of whether or not threadgroup is
explicitly passed in. *
@@ -1579,7 +1579,7 @@
* @see SecurityManager#checkAccess(Thread)
*/
public final void checkAccess() {
- // Android-removed: SecurityManager stubbed out on Android
+ // Android-removed: SecurityManager stubbed out on Android.
// SecurityManager security = System.getSecurityManager();
// if (security != null) {
// security.checkAccess(this);
@@ -1631,7 +1631,7 @@
*/
@CallerSensitive
public ClassLoader getContextClassLoader() {
- // Android-removed: SecurityManager stubbed out on Android
+ // Android-removed: SecurityManager stubbed out on Android.
/*
if (contextClassLoader == null)
return null;
@@ -1667,7 +1667,7 @@
* @since 1.2
*/
public void setContextClassLoader(ClassLoader cl) {
- // Android-removed: SecurityManager stubbed out on Android
+ // Android-removed: SecurityManager stubbed out on Android.
// SecurityManager sm = System.getSecurityManager();
// if (sm != null) {
// sm.checkPermission(new RuntimePermission("setContextClassLoader"));
@@ -1774,7 +1774,7 @@
* @since 1.5
*/
public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
- // Android-removed: SecurityManager stubbed out on Android
+ // Android-removed: SecurityManager stubbed out on Android.
/*
// check for getStackTrace permission
SecurityManager security = System.getSecurityManager();
@@ -2098,7 +2098,7 @@
* @since 1.5
*/
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
- // Android-removed: SecurityManager stubbed out on Android
+ // Android-removed: SecurityManager stubbed out on Android.
/*
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
diff --git a/ojluni/src/main/java/java/lang/Throwable.java b/ojluni/src/main/java/java/lang/Throwable.java
index 5a3f8a8..7596681 100644
--- a/ojluni/src/main/java/java/lang/Throwable.java
+++ b/ojluni/src/main/java/java/lang/Throwable.java
@@ -155,7 +155,7 @@
new StackTraceElement[] {STACK_TRACE_ELEMENT_SENTINEL};
}
- // Android-removed: Use libcore.util.EmptyArray for the empty stack trace
+ // Android-removed: Use libcore.util.EmptyArray for the empty stack trace.
// Adding the constant UNASSIGNED_STACK breaks serialization of some subclasses
// /**
// * A shared value for an empty stack.
@@ -211,11 +211,11 @@
* @serial
* @since 1.4
*/
- // Android-changed: Use libcore.util.EmptyArray for the empty stack trace
+ // Android-changed: Use libcore.util.EmptyArray for the empty stack trace.
// private StackTraceElement[] stackTrace = UNASSIGNED_STACK;
private StackTraceElement[] stackTrace = libcore.util.EmptyArray.STACK_TRACE_ELEMENT;
- // Android-removed: Use empty collection in place of SUPPRESSED_SENTINEL
+ // Android-removed: Use empty collection in place of SUPPRESSED_SENTINEL.
// Adding this constant breaks serialization of some subclasses
/*
// Setting this static field introduces an acceptable
@@ -234,7 +234,7 @@
* @serial
* @since 1.7
*/
- // Android-changed: Use empty collection in place of SUPPRESSED_SENTINEL
+ // Android-changed: Use empty collection in place of SUPPRESSED_SENTINEL.
// private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;
private List<Throwable> suppressedExceptions = Collections.emptyList();
@@ -689,7 +689,7 @@
String caption,
String prefix,
Set<Throwable> dejaVu) {
- // Android-removed: Use of assert keyword which breaks serialization of some subclasses
+ // Android-removed: Use of assert keyword which breaks serialization of some subclasses.
// (Using assert adds a static field that determines whether assertions are enabled.)
// assert Thread.holdsLock(s.lock());
if (dejaVu.contains(this)) {
@@ -794,17 +794,17 @@
public synchronized Throwable fillInStackTrace() {
if (stackTrace != null ||
backtrace != null /* Out of protocol state */ ) {
- // Android-changed: Use Android-specific nativeFillInStackTrace
+ // Android-changed: Use Android-specific nativeFillInStackTrace.
// fillInStackTrace(0);
backtrace = nativeFillInStackTrace();
- // Android-changed: Use libcore.util.EmptyArray for the empty stack trace
+ // Android-changed: Use libcore.util.EmptyArray for the empty stack trace.
// stackTrace = UNASSIGNED_STACK;
stackTrace = libcore.util.EmptyArray.STACK_TRACE_ELEMENT;
}
return this;
}
- // Android-changed: Use Android-specific nativeFillInStackTrace
+ // Android-changed: Use Android-specific nativeFillInStackTrace.
// private native Throwable fillInStackTrace(int dummy);
@FastNative
private static native Object nativeFillInStackTrace();
@@ -840,11 +840,11 @@
private synchronized StackTraceElement[] getOurStackTrace() {
// Initialize stack trace field with information from
// backtrace if this is the first call to this method
- // Android-changed: Use libcore.util.EmptyArray for the empty stack trace
+ // Android-changed: Use libcore.util.EmptyArray for the empty stack trace.
// if (stackTrace == UNASSIGNED_STACK ||
if (stackTrace == libcore.util.EmptyArray.STACK_TRACE_ELEMENT ||
(stackTrace == null && backtrace != null) /* Out of protocol state */) {
- // BEGIN Android-changed: Use Android-specific nativeGetStackTrace
+ // BEGIN Android-changed: Use Android-specific nativeGetStackTrace.
// int depth = getStackTraceDepth();
// stackTrace = new StackTraceElement[depth];
// for (int i=0; i < depth; i++)
@@ -854,9 +854,9 @@
if (stackTrace == null) {
return libcore.util.EmptyArray.STACK_TRACE_ELEMENT;
}
- // END Android-changed: Use Android-specific nativeGetStackTrace
+ // END Android-changed: Use Android-specific nativeGetStackTrace.
} else if (stackTrace == null) {
- // Android-changed: Use libcore.util.EmptyArray for the empty stack trace
+ // Android-changed: Use libcore.util.EmptyArray for the empty stack trace.
// return UNASSIGNED_STACK;
return libcore.util.EmptyArray.STACK_TRACE_ELEMENT;
}
@@ -907,7 +907,7 @@
}
}
- // Android-removed: Unused native method getStackTraceDepth()
+ // Android-removed: Unused native method getStackTraceDepth().
// /**
// * Returns the number of elements in the stack trace (or 0 if the stack
// * trace is unavailable).
@@ -925,7 +925,7 @@
* @throws IndexOutOfBoundsException if {@code index < 0 ||
* index >= getStackTraceDepth() }
*/
- // Android-changed: Use Android-specific nativeGetStackTrace
+ // Android-changed: Use Android-specific nativeGetStackTrace.
// native StackTraceElement getStackTraceElement(int index);
@FastNative
private static native StackTraceElement[] nativeGetStackTrace(Object stackState);
@@ -953,7 +953,7 @@
List<Throwable> suppressed = null;
if (suppressedExceptions.isEmpty()) {
// Use the sentinel for a zero-length list
- // Android-changed: Use empty collection in place of SUPPRESSED_SENTINEL
+ // Android-changed: Use empty collection in place of SUPPRESSED_SENTINEL.
// suppressed = SUPPRESSED_SENTINEL;
suppressed = Collections.emptyList();
} else { // Copy Throwables to new list
@@ -982,7 +982,7 @@
*/
if (stackTrace != null) {
if (stackTrace.length == 0) {
- // Android-removed: clone() call not needed because of libcore.util.EmptyArray usage
+ // Android-removed: clone() call unneeded because of libcore.util.EmptyArray usage.
// stackTrace = UNASSIGNED_STACK.clone();
} else if (stackTrace.length == 1 &&
// Check for the marker of an immutable stack trace
@@ -999,7 +999,7 @@
// from an exception serialized without that field in
// older JDK releases; treat such exceptions as having
// empty stack traces.
- // Android-changed: Directly create empty array instead of cloning UNASSIGNED_STACK
+ // Android-changed: Directly create empty array instead of cloning UNASSIGNED_STACK.
// stackTrace = UNASSIGNED_STACK.clone();
stackTrace = new StackTraceElement[0];
}
@@ -1090,7 +1090,7 @@
if (suppressedExceptions == null) // Suppressed exceptions not recorded
return;
- // Android-changed: Use empty collection in place of SUPPRESSED_SENTINEL
+ // Android-changed: Use empty collection in place of SUPPRESSED_SENTINEL.
// if (suppressedExceptions == SUPPRESSED_SENTINEL)
if (suppressedExceptions.isEmpty())
suppressedExceptions = new ArrayList<>(1);
@@ -1098,7 +1098,7 @@
suppressedExceptions.add(exception);
}
- // Android-changed: Lazily initialize EMPTY_THROWABLE_ARRAY
+ // Android-changed: Lazily initialize EMPTY_THROWABLE_ARRAY.
// private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
private static Throwable[] EMPTY_THROWABLE_ARRAY;
@@ -1118,12 +1118,12 @@
* @since 1.7
*/
public final synchronized Throwable[] getSuppressed() {
- // Android-added: Lazily initialize EMPTY_THROWABLE_ARRAY
+ // Android-added: Lazily initialize EMPTY_THROWABLE_ARRAY.
if (EMPTY_THROWABLE_ARRAY == null) {
EMPTY_THROWABLE_ARRAY = new Throwable[0];
}
- // Android-changed: Use empty collection in place of SUPPRESSED_SENTINEL
+ // Android-changed: Use empty collection in place of SUPPRESSED_SENTINEL.
// if (suppressedExceptions == SUPPRESSED_SENTINEL ||
// suppressedExceptions == null)
if (suppressedExceptions == null || suppressedExceptions.isEmpty())
diff --git a/ojluni/src/main/java/java/lang/invoke/CallSite.java b/ojluni/src/main/java/java/lang/invoke/CallSite.java
index 85b4bb9..069b2fd 100644
--- a/ojluni/src/main/java/java/lang/invoke/CallSite.java
+++ b/ojluni/src/main/java/java/lang/invoke/CallSite.java
@@ -25,7 +25,7 @@
package java.lang.invoke;
-// Android-changed: Not using Empty
+// Android-changed: Not using Empty.
//import sun.invoke.empty.Empty;
import static java.lang.invoke.MethodHandleStatics.*;
import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
@@ -104,9 +104,10 @@
*/
/*package-private*/
CallSite(MethodType type) {
- // Android-changed: No cache for these so create uninitializedCallSite target here using
- // method handle transformations to create a method handle that has the expected method
- // type but throws an IllegalStateException.
+ // Android-changed: No cache for these.
+ // Instead create uninitializedCallSite target here using method handle transformations
+ // to create a method handle that has the expected method type but throws an
+ // IllegalStateException.
// target = makeUninitializedCallSite(type);
this.target = MethodHandles.throwException(type.returnType(), IllegalStateException.class);
this.target = MethodHandles.insertArguments(
@@ -115,8 +116,7 @@
this.target = MethodHandles.dropArguments(this.target, 0, type.ptypes());
}
- // Android-changed: Using initializer method for GET_TARGET
- // rather than complex static initializer.
+ // Android-changed: Using initializer method for GET_TARGET instead of static initializer.
initializeGetTarget();
}
@@ -130,8 +130,7 @@
target.type(); // null check
this.target = target;
- // Android-changed: Using initializer method for GET_TARGET
- // rather than complex static initializer.
+ // Android-changed: Using initializer method for GET_TARGET instead of static initializer.
initializeGetTarget();
}
@@ -153,8 +152,7 @@
checkTargetChange(this.target, boundTarget);
this.target = boundTarget;
- // Android-changed: Using initializer method for GET_TARGET
- // rather than complex static initializer.
+ // Android-changed: Using initializer method for GET_TARGET instead of static initializer.
initializeGetTarget();
}
@@ -244,9 +242,9 @@
private static MethodHandle GET_TARGET = null;
private void initializeGetTarget() {
- // Android-changed: moved from static initializer for
- // GET_TARGET to avoid issues with running early. Called from
- // constructors. CallSite creation is not performance critical.
+ // Android-changed: moved from static initializer for GET_TARGET.
+ // This avoids issues with running early. Called from constructors.
+ // CallSite creation is not performance critical.
synchronized (CallSite.class) {
if (GET_TARGET == null) {
try {
diff --git a/ojluni/src/main/java/java/lang/reflect/Array.java b/ojluni/src/main/java/java/lang/reflect/Array.java
index 95a8091..db7e9a2 100644
--- a/ojluni/src/main/java/java/lang/reflect/Array.java
+++ b/ojluni/src/main/java/java/lang/reflect/Array.java
@@ -111,7 +111,7 @@
*/
public static Object newInstance(Class<?> componentType, int... dimensions)
throws IllegalArgumentException, NegativeArraySizeException {
- // Android-changed: New implementation of newInstance(Class, int...)
+ // Android-changed: New implementation of newInstance(Class, int...).
if (dimensions.length <= 0 || dimensions.length > 255) {
throw new IllegalArgumentException("Bad number of dimensions: " + dimensions.length);
}
@@ -132,7 +132,7 @@
* @exception IllegalArgumentException if the object argument is not
* an array
*/
- // Android-changed: Non-native implementation of getLength(Object)
+ // Android-changed: Non-native implementation of getLength(Object).
// Android-changed: Removal of explicit throws IllegalArgumentException from method signature.
public static int getLength(Object array)
/* throws IllegalArgumentException */ {
@@ -174,7 +174,7 @@
* argument is negative, or if it is greater than or equal to the
* length of the specified array
*/
- // Android-changed: Non-native implementation of get(Object, int)
+ // Android-changed: Non-native implementation of get(Object, int).
public static Object get(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof Object[]) {
@@ -226,7 +226,7 @@
* length of the specified array
* @see Array#get
*/
- // Android-changed: Non-native implementation of getBoolean(Object, int)
+ // Android-changed: Non-native implementation of getBoolean(Object, int).
public static boolean getBoolean(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof boolean[]) {
@@ -251,7 +251,7 @@
* length of the specified array
* @see Array#get
*/
- // Android-changed: Non-native implementation of getByte(Object, int)
+ // Android-changed: Non-native implementation of getByte(Object, int).
public static byte getByte(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof byte[]) {
@@ -276,7 +276,7 @@
* length of the specified array
* @see Array#get
*/
- // Android-changed: Non-native implementation of getChar(Object, int)
+ // Android-changed: Non-native implementation of getChar(Object, int).
public static char getChar(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof char[]) {
@@ -301,7 +301,7 @@
* length of the specified array
* @see Array#get
*/
- // Android-changed: Non-native implementation of getShort(Object, int)
+ // Android-changed: Non-native implementation of getShort(Object, int).
public static short getShort(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof short[]) {
@@ -328,7 +328,7 @@
* length of the specified array
* @see Array#get
*/
- // Android-changed: Non-native implementation of getInt(Object, int)
+ // Android-changed: Non-native implementation of getInt(Object, int).
public static int getInt(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof int[]) {
@@ -359,7 +359,7 @@
* length of the specified array
* @see Array#get
*/
- // Android-changed: Non-native implementation of getLong(Object, int)
+ // Android-changed: Non-native implementation of getLong(Object, int).
public static long getLong(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof long[]) {
@@ -392,7 +392,7 @@
* length of the specified array
* @see Array#get
*/
- // Android-changed: Non-native implementation of getFloat(Object, int)
+ // Android-changed: Non-native implementation of getFloat(Object, int).
public static float getFloat(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof float[]) {
@@ -427,7 +427,7 @@
* length of the specified array
* @see Array#get
*/
- // Android-changed: Non-native implementation of getDouble(Object, int)
+ // Android-changed: Non-native implementation of getDouble(Object, int).
public static double getDouble(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof double[]) {
@@ -465,7 +465,7 @@
* argument is negative, or if it is greater than or equal to
* the length of the specified array
*/
- // Android-changed: Non-native implementation of set(Object, int, Object)
+ // Android-changed: Non-native implementation of set(Object, int, Object).
public static void set(Object array, int index, Object value)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (!array.getClass().isArray()) {
@@ -518,8 +518,8 @@
* the length of the specified array
* @see Array#set
*/
- // Android-changed: Non-native implementation of setBoolean(Object, int, boolean)
- // Android-changed: Removal of explicit runtime exceptions throws clause
+ // Android-changed: Non-native implementation of setBoolean(Object, int, boolean).
+ // Android-changed: Removal of explicit runtime exceptions throws clause.
public static void setBoolean(Object array, int index, boolean z)
/* throws IllegalArgumentException, ArrayIndexOutOfBoundsException */ {
if (array instanceof boolean[]) {
@@ -546,7 +546,7 @@
* the length of the specified array
* @see Array#set
*/
- // Android-changed: Non-native implementation of setByte(Object, int, byte)
+ // Android-changed: Non-native implementation of setByte(Object, int, byte).
public static void setByte(Object array, int index, byte b)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof byte[]) {
@@ -583,7 +583,7 @@
* the length of the specified array
* @see Array#set
*/
- // Android-changed: Non-native implementation of setChar(Object, int, char)
+ // Android-changed: Non-native implementation of setChar(Object, int, char).
public static void setChar(Object array, int index, char c)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof char[]) {
@@ -618,7 +618,7 @@
* the length of the specified array
* @see Array#set
*/
- // Android-changed: Non-native implementation of setShort(Object, int, short)
+ // Android-changed: Non-native implementation of setShort(Object, int, short).
public static void setShort(Object array, int index, short s)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof short[]) {
@@ -653,7 +653,7 @@
* the length of the specified array
* @see Array#set
*/
- // Android-changed: Non-native implementation of setInt(Object, int, int)
+ // Android-changed: Non-native implementation of setInt(Object, int, int).
public static void setInt(Object array, int index, int i)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof int[]) {
@@ -686,7 +686,7 @@
* the length of the specified array
* @see Array#set
*/
- // Android-changed: Non-native implementation of setBoolean(Object, int, long)
+ // Android-changed: Non-native implementation of setBoolean(Object, int, long).
public static void setLong(Object array, int index, long l)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof long[]) {
@@ -745,7 +745,7 @@
* the length of the specified array
* @see Array#set
*/
- // Android-changed: Non-native implementation of setDouble(Object, int, double)
+ // Android-changed: Non-native implementation of setDouble(Object, int, double).
public static void setDouble(Object array, int index, double d)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
if (array instanceof double[]) {
@@ -759,7 +759,7 @@
* Private
*/
- // Android-added: Added javadocs for newArray(Class, int)
+ // Android-added: Added javadocs for newArray(Class, int).
/**
* Returns a new array of the specified component type and length.
* Equivalent to {@code new componentType[size]}.
@@ -769,7 +769,7 @@
* @throws NegativeArraySizeException
* if {@code size < 0}
*/
- // Android-changed: Non-native implementation of newArray(Class, int)
+ // Android-changed: Non-native implementation of newArray(Class, int).
private static Object newArray(Class<?> componentType, int length)
throws NegativeArraySizeException {
if (!componentType.isPrimitive()) {
@@ -803,7 +803,7 @@
throws IllegalArgumentException, NegativeArraySizeException;
*/
- // Android-added: createMultiArray(Class, int[]) method. Used instead of multiNewArray
+ // Android-added: createMultiArray(Class, int[]) method. Used instead of multiNewArray.
/*
* Create a multi-dimensional array of objects with the specified type.
*/
diff --git a/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java b/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java
index a3c738a..df3b6ed 100644
--- a/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java
+++ b/ojluni/src/main/java/java/net/AbstractPlainDatagramSocketImpl.java
@@ -55,7 +55,7 @@
protected InetAddress connectedAddress = null;
private int connectedPort = -1;
- // Android-added: CloseGuard
+ // Android-added: CloseGuard.
private final CloseGuard guard = CloseGuard.get();
private static final String os = AccessController.doPrivileged(
@@ -67,7 +67,7 @@
*/
private final static boolean connectDisabled = os.contains("OS X");
- // BEGIN Android-removed: Android doesn't need to load native net library
+ // BEGIN Android-removed: Android doesn't need to load native net library.
/**
* Load net library into runtime.
*
@@ -81,7 +81,7 @@
});
}
*/
- // END Android-removed: Android doesn't need to load native net library
+ // END Android-removed: Android doesn't need to load native net library.
/**
* Creates a datagram socket
@@ -97,7 +97,7 @@
throw ioe;
}
- // Android-added: CloseGuard/fdsan
+ // Android-added: CloseGuard/fdsan.
if (fd != null && fd.valid()) {
guard.open("close");
IoUtils.setFdOwner(fd, this);
@@ -130,7 +130,7 @@
* @param port the remote port number
*/
protected void connect(InetAddress address, int port) throws SocketException {
- // Android-added: BlockGuard
+ // Android-added: BlockGuard.
BlockGuard.getThreadPolicy().onNetwork();
connect0(address, port);
connectedAddress = address;
@@ -248,7 +248,7 @@
* Close the socket.
*/
protected void close() {
- // Android-added: CloseGuard
+ // Android-added: CloseGuard.
guard.close();
if (fd != null) {
@@ -263,7 +263,7 @@
}
protected void finalize() {
- // Android-added: CloseGuard
+ // Android-added: CloseGuard.
if (guard != null) {
guard.warnIfOpen();
}
@@ -375,7 +375,7 @@
case SO_REUSEADDR:
case SO_BROADCAST:
result = socketGetOption(optID);
- // Android-added: Added for app compat reason. See methodgetNIFirstAddress
+ // Android-added: Added for app compat reason. See methodgetNIFirstAddress.
if (optID == IP_MULTICAST_IF) {
return getNIFirstAddress((Integer)result);
}
@@ -422,7 +422,7 @@
return connectDisabled;
}
- // Android-changed: rewritten on the top of IoBridge
+ // Android-changed: rewritten on the top of IoBridge.
int dataAvailable() {
try {
return IoBridge.available(fd);
diff --git a/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java b/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
index 0500811..963b2ac 100644
--- a/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
+++ b/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
@@ -50,7 +50,7 @@
{
/* instance variable for SO_TIMEOUT */
int timeout; // timeout in millisec
- // Android-removed: traffic class is set through socket
+ // Android-removed: traffic class is set through socket.
// private int trafficClass;
private boolean shut_rd = false;
@@ -63,7 +63,7 @@
protected int fdUseCount = 0;
/* lock when increment/decrementing fdUseCount */
- // Android-added: @ReachabilitySensitive
+ // Android-added: @ReachabilitySensitive.
// Marked mostly because it's used where fd is, and fd isn't declared here.
// This adds reachabilityFences where we would if fd were annotated.
@ReachabilitySensitive
@@ -83,7 +83,7 @@
*/
protected boolean stream;
- // BEGIN Android-removed: Android doesn't need to load native net library
+ // BEGIN Android-removed: Android doesn't need to load native net library.
/*
/**
* Load net library into runtime.
@@ -98,9 +98,9 @@
});
}
*/
- // END Android-removed: Android doesn't need to load native net library
+ // END Android-removed: Android doesn't need to load native net library.
- // Android-added: logs a warning if socket is not closed
+ // Android-added: logs a warning if socket is not closed.
@ReachabilitySensitive
private final CloseGuard guard = CloseGuard.get();
@@ -112,18 +112,18 @@
this.stream = stream;
if (!stream) {
ResourceManager.beforeUdpCreate();
- // Android-removed: socketCreate should set fd if it succeeds
+ // Android-removed: socketCreate should set fd if it succeeds.
// fd = new FileDescriptor();
try {
socketCreate(false);
} catch (IOException ioe) {
ResourceManager.afterUdpClose();
- // Android-removed: b/26470377 Represent closed sockets with invalid fd, not null.
+ // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
// fd = null;
throw ioe;
}
} else {
- // Android-removed: socketCreate should set fd if it succeeds
+ // Android-removed: socketCreate should set fd if it succeeds.
// fd = new FileDescriptor();
socketCreate(true);
}
@@ -132,7 +132,7 @@
if (serverSocket != null)
serverSocket.setCreated();
- // Android-added: CloseGuard
+ // Android-added: CloseGuard.
if (fd != null && fd.valid()) {
guard.open("close");
}
@@ -301,7 +301,7 @@
socketSetOption(opt, on, val);
*/
// END Android-removed: Logic dealing with value type moved to socketSetOption.
- // Android-added: Keep track of timeout value not handled by socketSetOption
+ // Android-added: Keep track of timeout value not handled by socketSetOption.
if (opt == SO_TIMEOUT) {
timeout = (Integer) val;
}
@@ -385,7 +385,7 @@
try {
acquireFD();
try {
- // Android-added: BlockGuard
+ // Android-added: BlockGuard.
BlockGuard.getThreadPolicy().onNetwork();
socketConnect(address, port, timeout);
/* socket may have been closed during poll/select */
@@ -446,7 +446,7 @@
protected void accept(SocketImpl s) throws IOException {
acquireFD();
try {
- // Android-added: BlockGuard
+ // Android-added: BlockGuard.
BlockGuard.getThreadPolicy().onNetwork();
socketAccept(s);
} finally {
@@ -558,10 +558,9 @@
if (!stream) {
ResourceManager.afterUdpClose();
}
- // Android-changed:
- // Socket should be untagged before the preclose. After preclose,
- // socket will dup2-ed to marker_fd, therefore, it won't describe the same file.
- // If closingPending is true, then the socket has been preclosed.
+ // Android-changed: Socket should be untagged before the preclose.
+ // After preclose, socket will dup2-ed to marker_fd, therefore, it won't describe
+ // the same file. If closingPending is true, then the socket has been preclosed.
//
// Also, close the CloseGuard when the #close is called.
if (!closePending) {
@@ -582,8 +581,8 @@
} finally {
socketClose();
}
- // Android-changed(http://b/26470377): Some Android code doesn't expect file
- // descriptor to be null. socketClose invalidates the fd by closing the fd.
+ // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
+ // socketClose invalidates the fd by closing the fd.
// fd = null;
return;
} else {
@@ -607,7 +606,7 @@
// Android-changed: Notified the CloseGuard object as the fd has been released.
guard.close();
}
- // Android-removed: b/26470377 Represent closed sockets with invalid fd, not null.
+ // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
// fd = null;
super.reset();
}
@@ -617,7 +616,7 @@
* Shutdown read-half of the socket connection;
*/
protected void shutdownInput() throws IOException {
- // Android-changed: b/26470377 Represent closed sockets with invalid fd, not null.
+ // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
if (fd != null && fd.valid()) {
socketShutdown(SHUT_RD);
if (socketInputStream != null) {
@@ -631,7 +630,7 @@
* Shutdown write-half of the socket connection;
*/
protected void shutdownOutput() throws IOException {
- // Android-changed: b/26470377 Represent closed sockets with invalid fd, not null.
+ // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
if (fd != null && fd.valid()) {
socketShutdown(SHUT_WR);
shut_wr = true;
@@ -643,7 +642,7 @@
}
protected void sendUrgentData (int data) throws IOException {
- // Android-changed: b/26470377 Represent closed sockets with invalid fd, not null.
+ // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
if (fd == null || !fd.valid()) {
throw new IOException("Socket Closed");
}
@@ -654,7 +653,7 @@
* Cleans up if the user forgets to close it.
*/
protected void finalize() throws IOException {
- // Android-added: CloseGuard
+ // Android-added: CloseGuard.
if (guard != null) {
guard.warnIfOpen();
}
@@ -688,8 +687,8 @@
try {
socketClose();
} catch (IOException e) {
- // Android-removed: b/26470377 Some Android code doesn't expect file
- // descriptor to be null. socketClose invalidates the fd by closing the fd.
+ // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
+ // socketClose invalidates the fd by closing the fd.
// } finally {
// fd = null;
}
@@ -734,7 +733,7 @@
* close is in progress.
*/
synchronized (fdLock) {
- // Android-changed: b/26470377 Represent closed sockets with invalid fd, not null.
+ // Android-changed: Closed sockets use an invalid fd, not null. b/26470377
if (closePending || (fd == null) || !fd.valid()) {
return true;
} else {
@@ -781,8 +780,8 @@
abstract void socketShutdown(int howto)
throws IOException;
- // Android-changed: Method signature changed, socket{Get,Set}Option work directly with Object
- // values.
+ // Android-changed: Method signature changes.
+ // socket{Get,Set}Option work directly with Object values.
abstract void socketSetOption(int cmd, Object value) throws SocketException;
abstract Object socketGetOption(int opt) throws SocketException;
diff --git a/ojluni/src/main/java/java/net/CookieManager.java b/ojluni/src/main/java/java/net/CookieManager.java
index dfd3b86..bff9734 100644
--- a/ojluni/src/main/java/java/net/CookieManager.java
+++ b/ojluni/src/main/java/java/net/CookieManager.java
@@ -250,7 +250,7 @@
}
}
}
- // Android-added: b/25897688 A fix to return empty map if cookies list is empty
+ // Android-added: A fix to return empty map if cookies list is empty. b/25897688
if (cookies.isEmpty()) {
return Collections.emptyMap();
}
@@ -315,7 +315,7 @@
}
}
cookie.setPath(path);
- // Android-added: b/25763487 A fix to verify cookie URI before removal
+ // Android-added: A fix to verify cookie URI before removal. b/25763487
} else {
// Validate existing path
if (!pathMatches(uri, cookie)) {
@@ -408,7 +408,7 @@
return false;
}
- // Android-changed: b/25763487 Cookie path matching logic in OpenJDK was wrong
+ // Android-changed: Cookie path matching logic in OpenJDK was wrong. b/25763487
/**
* Return true iff. the path from {@code cookie} matches the path from {@code uri}.
*/
@@ -436,9 +436,9 @@
private List<String> sortByPath(List<HttpCookie> cookies) {
Collections.sort(cookies, new CookiePathComparator());
- // BEGIN Android-changed: Netscape cookie spec and RFC 2965 have different format
- // of Cookie header; RFC 2965 requires a leading $Version="1" string while Netscape does not
- // The workaround here is to add a $Version="1" string in advance
+ // BEGIN Android-changed: Cookie header differs in Netscape cookie spec and RFC 2965.
+ // RFC 2965 requires a leading $Version="1" string while Netscape does not.
+ // The workaround here is to add a $Version="1" string in advance.
final StringBuilder result = new StringBuilder();
int minVersion = 1;
for (HttpCookie cookie : cookies) {
@@ -461,7 +461,7 @@
List<String> cookieHeader = new java.util.ArrayList<String>();
cookieHeader.add(result.toString());
- // END Android-changed: Netscape cookie spec and RFC 2965 have different format
+ // END Android-changed: Cookie header differs in Netscape cookie spec and RFC 2965.
return cookieHeader;
}
@@ -475,7 +475,7 @@
// path rule only applies to the cookies with same name
if (!c1.getName().equals(c2.getName())) return 0;
- // Android-changed: normalize before comparison
+ // Android-changed: normalize before comparison.
final String c1Path = normalizePath(c1.getPath());
final String c2Path = normalizePath(c2.getPath());
diff --git a/ojluni/src/main/java/java/net/HttpCookie.java b/ojluni/src/main/java/java/net/HttpCookie.java
index 3ff33c7..70b9b6b 100644
--- a/ojluni/src/main/java/java/net/HttpCookie.java
+++ b/ojluni/src/main/java/java/net/HttpCookie.java
@@ -57,7 +57,7 @@
* @since 1.6
*/
public final class HttpCookie implements Cloneable {
- // BEGIN Android-added: Reserved name can't be HttpCookie name
+ // BEGIN Android-added: Reserved name can't be HttpCookie name.
private static final Set<String> RESERVED_NAMES = new HashSet<String>();
static {
@@ -73,7 +73,7 @@
RESERVED_NAMES.add("secure"); // Netscape RFC 2109 RFC 2965 RFC 6265
RESERVED_NAMES.add("version"); // RFC 2109 RFC 2965 RFC 6265
}
- // END Android-added: Reserved name can't be HttpCookie name
+ // END Android-added: Reserved name can't be HttpCookie name.
// ---------------- Fields --------------
@@ -691,13 +691,13 @@
String H = host.substring(0, lengthDiff);
String D = host.substring(lengthDiff);
- // BEGIN Android-changed: App compat reason
+ // BEGIN Android-changed: App compat reason.
// 1) Disregard RFC 2965 sec. 3.3.2, the "The request-host is a HDN..."
// 2) match "foo.local" for domain ".local".
// return (H.indexOf('.') == -1 && D.equalsIgnoreCase(domain));
return D.equalsIgnoreCase(domain) && ((domain.startsWith(".") && isFullyQualifiedDomainName(domain, 1))
|| isLocalDomain);
- // END Android-changed: App compat reason
+ // END Android-changed: App compat reason.
}
else if (lengthDiff == -1) {
// if domain is actually .host
@@ -708,12 +708,12 @@
return false;
}
- // BEGIN Android-added: App compat reason
+ // BEGIN Android-added: App compat reason.
private static boolean isFullyQualifiedDomainName(String s, int firstCharacter) {
int dotPosition = s.indexOf('.', firstCharacter + 1);
return dotPosition != -1 && dotPosition < s.length() - 1;
}
- // END Android-added: App compat reason
+ // END Android-added: App compat reason.
/**
* Constructs a cookie header string representation of this cookie,
@@ -799,7 +799,7 @@
// from RFC 2068, token special case characters
//
// private static final String tspecials = "()<>@,;:\\\"/[]?={} \t";
- // Android-changed: App compat reason. Disallow "=\t" as token
+ // Android-changed: App compat reason. Disallow "=\t" as token.
// private static final String tspecials = ",; "; // deliberately includes space
private static final String tspecials = ",;= \t";
@@ -813,7 +813,7 @@
* {@code false} if it is not
*/
private static boolean isToken(String value) {
- // Android-added: Reserved name can't be a token
+ // Android-added: Reserved name can't be a token.
if (RESERVED_NAMES.contains(value.toLowerCase(Locale.US))) {
return false;
}
@@ -998,7 +998,7 @@
// BEGIN Android-changed: Use HttpDate for date parsing.
// it accepts broader set of date formats.
// cookie.setMaxAge(cookie.expiryDate2DeltaSeconds(attrValue));
- // Android-changed: Altered max age calculation to avoid setting
+ // Android-changed: Altered max age calculation to avoid setting.
// it to MAX_AGE_UNSPECIFIED (-1) if "expires" is one second in past.
Date date = HttpDate.parse(attrValue);
long maxAgeInSeconds = 0;
@@ -1030,7 +1030,7 @@
}
}
- // BEGIN Android-removed: Android doesn't use JavaNetHttpCookieAccess
+ // BEGIN Android-removed: Android doesn't use JavaNetHttpCookieAccess.
/*
static {
sun.misc.SharedSecrets.setJavaNetHttpCookieAccess(
@@ -1046,7 +1046,7 @@
);
}
*/
- // END Android-removed: Android doesn't use JavaNetHttpCookieAccess
+ // END Android-removed: Android doesn't use JavaNetHttpCookieAccess.
/*
* Returns the original header this cookie was consructed from, if it was
diff --git a/ojluni/src/main/java/java/net/IDN.java b/ojluni/src/main/java/java/net/IDN.java
index a18c3a8..36559cf 100644
--- a/ojluni/src/main/java/java/net/IDN.java
+++ b/ojluni/src/main/java/java/net/IDN.java
@@ -103,7 +103,7 @@
* @throws IllegalArgumentException if the input string doesn't conform to RFC 3490 specification
*/
public static String toASCII(String input, int flag) {
- // BEGIN Android-changed: Use ICU4J implementation
+ // BEGIN Android-changed: Use ICU4J implementation.
try {
return IDNA.convertIDNToASCII(input, flag).toString();
} catch (android.icu.text.StringPrepParseException e) {
@@ -114,7 +114,7 @@
}
throw new IllegalArgumentException("Invalid input to toASCII: " + input, e);
}
- // END Android-changed: Use ICU4J implementation
+ // END Android-changed: Use ICU4J implementation.
}
@@ -158,7 +158,7 @@
* @return the translated {@code String}
*/
public static String toUnicode(String input, int flag) {
- // BEGIN Android-changed: Use ICU4J implementation
+ // BEGIN Android-changed: Use ICU4J implementation.
try {
// ICU only translates separators to ASCII for toASCII.
// Java expects the translation for toUnicode too.
@@ -168,10 +168,10 @@
// the original string is returned.
return input;
}
- // END Android-changed: Use ICU4J implementation
+ // END Android-changed: Use ICU4J implementation.
}
- // BEGIN Android-added: Use ICU4J implementation
+ // BEGIN Android-added: Use ICU4J implementation.
private static boolean isLabelSeperator(char c) {
return (c == '\u3002' || c == '\uff0e' || c == '\uff61');
}
@@ -184,7 +184,7 @@
}
return input;
}
- // END Android-added: Use ICU4J implementation
+ // END Android-added: Use ICU4J implementation.
/**
* Translates a string from ASCII Compatible Encoding (ACE) to Unicode,
diff --git a/ojluni/src/main/java/java/net/InMemoryCookieStore.java b/ojluni/src/main/java/java/net/InMemoryCookieStore.java
index 5df66c0..85aab8b 100644
--- a/ojluni/src/main/java/java/net/InMemoryCookieStore.java
+++ b/ojluni/src/main/java/java/net/InMemoryCookieStore.java
@@ -36,7 +36,7 @@
import java.util.Iterator;
import java.util.concurrent.locks.ReentrantLock;
-// Android-changed: App compat changes and bug fixes
+// Android-changed: App compat changes and bug fixes.
// b/26456024 Add targetSdkVersion based compatibility for domain matching
// b/33034917 Support clearing cookies by adding it with "max-age=0"
// b/25897688 InMemoryCookieStore ignores scheme (http/https) port and path of the cookie
@@ -52,7 +52,7 @@
*/
public class InMemoryCookieStore implements CookieStore {
// the in-memory representation of cookies
- // BEGIN Android-removed: Remove cookieJar and domainIndex
+ // BEGIN Android-removed: Remove cookieJar and domainIndex.
/*
private List<HttpCookie> cookieJar = null;
@@ -62,13 +62,13 @@
// presence of cookie when retrieve one form index store.
private Map<String, List<HttpCookie>> domainIndex = null;
*/
- // END Android-removed: Remove cookieJar and domainIndex
+ // END Android-removed: Remove cookieJar and domainIndex.
private Map<URI, List<HttpCookie>> uriIndex = null;
// use ReentrantLock instead of syncronized for scalability
private ReentrantLock lock = null;
- // BEGIN Android-changed: Add targetSdkVersion and remove cookieJar and domainIndex
+ // BEGIN Android-changed: Add targetSdkVersion and remove cookieJar and domainIndex.
private final boolean applyMCompatibility;
/**
@@ -83,7 +83,7 @@
lock = new ReentrantLock(false);
applyMCompatibility = (targetSdkVersion <= 23);
}
- // END Android-changed: Add targetSdkVersion and remove cookieJar and domainIndex
+ // END Android-changed: Add targetSdkVersion and remove cookieJar and domainIndex.
/**
* Add one cookie into cookie store.
@@ -96,8 +96,8 @@
lock.lock();
try {
- // Android-changed: http://b/33034917, android supports clearing cookies
- // by adding the cookie with max-age: 0.
+ // Android-changed: Android supports clearing cookies. http://b/33034917
+ // They are cleared by adding the cookie with max-age: 0.
//if (cookie.getMaxAge() != 0) {
addIndex(uriIndex, getEffectiveURI(uri), cookie);
//}
@@ -121,7 +121,7 @@
}
List<HttpCookie> cookies = new ArrayList<HttpCookie>();
- // BEGIN Android-changed: b/25897688 InMemoryCookieStore ignores scheme (http/https)
+ // BEGIN Android-changed: InMemoryCookieStore ignores scheme (http/https). b/25897688
lock.lock();
try {
// check domainIndex first
@@ -131,7 +131,7 @@
} finally {
lock.unlock();
}
- // END Android-changed: b/25897688 InMemoryCookieStore ignores scheme (http/https)
+ // END Android-changed: InMemoryCookieStore ignores scheme (http/https). b/25897688
return cookies;
}
@@ -139,7 +139,7 @@
* Get all cookies in cookie store, except those have expired
*/
public List<HttpCookie> getCookies() {
- // BEGIN Android-changed: Remove cookieJar and domainIndex
+ // BEGIN Android-changed: Remove cookieJar and domainIndex.
List<HttpCookie> rt = new ArrayList<HttpCookie>();
lock.lock();
@@ -159,7 +159,7 @@
rt = Collections.unmodifiableList(rt);
lock.unlock();
}
- // END Android-changed: Remove cookieJar and domainIndex
+ // END Android-changed: Remove cookieJar and domainIndex.
return rt;
}
@@ -213,7 +213,7 @@
throw new NullPointerException("cookie is null");
}
- // BEGIN Android-changed: Fix uri not being removed from uriIndex
+ // BEGIN Android-changed: Fix uri not being removed from uriIndex.
lock.lock();
try {
uri = getEffectiveURI(uri);
@@ -230,7 +230,7 @@
} finally {
lock.unlock();
}
- // END Android-changed: Fix uri not being removed from uriIndex
+ // END Android-changed: Fix uri not being removed from uriIndex.
}
@@ -299,7 +299,7 @@
// need to check H & D component
String D = host.substring(lengthDiff);
- // Android-changed: b/26456024 targetSdkVersion based compatibility for domain matching
+ // Android-changed: b/26456024 targetSdkVersion based compatibility for domain matching.
// Android M and earlier: Cookies with domain "foo.com" would not match "bar.foo.com".
// The RFC dictates that the user agent must treat those domains as if they had a
// leading period and must therefore match "bar.foo.com".
@@ -319,7 +319,7 @@
private void getInternal1(List<HttpCookie> cookies, Map<URI, List<HttpCookie>> cookieIndex,
String host) {
- // BEGIN Android-changed: b/25897688 InMemoryCookieStore ignores scheme (http/https)
+ // BEGIN Android-changed: InMemoryCookieStore ignores scheme (http/https). b/25897688
// Use a separate list to handle cookies that need to be removed so
// that there is no conflict with iterators.
ArrayList<HttpCookie> toRemove = new ArrayList<HttpCookie>();
@@ -348,7 +348,7 @@
}
toRemove.clear();
}
- // END Android-changed: b/25897688 InMemoryCookieStore ignores scheme (http/https)
+ // END Android-changed: InMemoryCookieStore ignores scheme (http/https). b/25897688
}
// @param cookies [OUT] contains the found cookies
@@ -359,7 +359,7 @@
void getInternal2(List<HttpCookie> cookies, Map<T, List<HttpCookie>> cookieIndex,
T comparator)
{
- // BEGIN Android-changed: b/25897688 InMemoryCookieStore ignores scheme (http/https)
+ // BEGIN Android-changed: InMemoryCookieStore ignores scheme (http/https). b/25897688
// Removed cookieJar
for (T index : cookieIndex.keySet()) {
if ((index == comparator) || (index != null && comparator.compareTo(index) == 0)) {
@@ -381,7 +381,7 @@
} // end of indexedCookies != null
} // end of comparator.compareTo(index) == 0
} // end of cookieIndex iteration
- // END Android-changed: b/25897688 InMemoryCookieStore ignores scheme (http/https)
+ // END Android-changed: InMemoryCookieStore ignores scheme (http/https). b/25897688
}
// add 'cookie' indexed by 'index' into 'indexStore'
@@ -389,9 +389,9 @@
T index,
HttpCookie cookie)
{
- // Android-changed: "index" can be null. We only use the URI based
- // index on Android and we want to support null URIs. The underlying
- // store is a HashMap which will support null keys anyway.
+ // Android-changed: "index" can be null.
+ // We only use the URI based index on Android and we want to support null URIs. The
+ // underlying store is a HashMap which will support null keys anyway.
// if (index != null) {
List<HttpCookie> cookies = indexStore.get(index);
if (cookies != null) {
@@ -413,7 +413,7 @@
//
private URI getEffectiveURI(URI uri) {
URI effectiveURI = null;
- // Android-added: Fix NullPointerException
+ // Android-added: Fix NullPointerException.
if (uri == null) {
return null;
}
diff --git a/ojluni/src/main/java/java/net/Inet4Address.java b/ojluni/src/main/java/java/net/Inet4Address.java
index 1fb7b92..2dc875b 100644
--- a/ojluni/src/main/java/java/net/Inet4Address.java
+++ b/ojluni/src/main/java/java/net/Inet4Address.java
@@ -93,7 +93,7 @@
* serialized */
private static final long serialVersionUID = 3286316764910316507L;
- // BEGIN Android-added: Define special-purpose IPv4 address
+ // BEGIN Android-added: Define special-purpose IPv4 address.
/** @hide */
public static final InetAddress ANY = new Inet4Address(null, new byte[] { 0, 0, 0, 0 });
@@ -104,10 +104,10 @@
/** @hide */
public static final InetAddress LOOPBACK =
new Inet4Address("localhost", new byte[] { 127, 0, 0, 1 });
- // END Android-added: Define special-purpose IPv4 address
+ // END Android-added: Define special-purpose IPv4 address.
- // BEGIN Android-removed: Android doesn't need to call native init
+ // BEGIN Android-removed: Android doesn't need to call native init.
/*
* Perform initializations.
*
@@ -115,7 +115,7 @@
init();
}
*/
- // END Android-removed: Android doesn't need to call native init
+ // END Android-removed: Android doesn't need to call native init.
Inet4Address() {
super();
holder().hostName = null;
@@ -391,11 +391,11 @@
return (src[0] & 0xff) + "." + (src[1] & 0xff) + "." + (src[2] & 0xff) + "." + (src[3] & 0xff);
}
- // BEGIN Android-removed: Android doesn't need to call native init
+ // BEGIN Android-removed: Android doesn't need to call native init.
/*
* Perform class load-time initializations.
*
private static native void init();
*/
- // END Android-removed: Android doesn't need to call native init
+ // END Android-removed: Android doesn't need to call native init.
}
diff --git a/ojluni/src/main/java/java/net/Inet6Address.java b/ojluni/src/main/java/java/net/Inet6Address.java
index c0aadb3..83f3451 100644
--- a/ojluni/src/main/java/java/net/Inet6Address.java
+++ b/ojluni/src/main/java/java/net/Inet6Address.java
@@ -178,15 +178,15 @@
class Inet6Address extends InetAddress {
final static int INADDRSZ = 16;
- // BEGIN Android-removed: Remove special handling for link-local addresses
+ // BEGIN Android-removed: Remove special handling for link-local addresses.
/*
* cached scope_id - for link-local address use only.
*
private transient int cached_scope_id; // 0
*/
- // END Android-removed: Remove special handling for link-local addresses
+ // END Android-removed: Remove special handling for link-local addresses.
- // BEGIN Android-added: Define special-purpose IPv6 address
+ // BEGIN Android-added: Define special-purpose IPv6 address.
/** @hide */
public static final InetAddress ANY =
new Inet6Address("::", new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0);
@@ -194,7 +194,7 @@
/** @hide */
public static final InetAddress LOOPBACK = new Inet6Address("ip6-localhost",
new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 0);
- // END Android-added: Define special-purpose IPv6 address
+ // END Android-added: Define special-purpose IPv6 address.
private class Inet6AddressHolder {
@@ -252,7 +252,7 @@
void init(byte addr[], int scope_id) {
setAddr(addr);
- // Android-changed: was >= 0
+ // Android-changed: was >= 0.
if (scope_id > 0) {
this.scope_id = scope_id;
this.scope_id_set = true;
@@ -272,7 +272,7 @@
}
}
- // Android-removed: getnameinfo returns smarter representations than getHostAddress()
+ // Android-removed: getnameinfo returns smarter representations than getHostAddress().
/*
String getHostAddress() {
String s = numericToTextFormat(ipaddress);
@@ -389,11 +389,11 @@
private static final long serialVersionUID = 6880410070516793377L;
- // BEGIN Android-removed: Android doesn't need to call native init
+ // BEGIN Android-removed: Android doesn't need to call native init.
/*
// Perform native initialization
static { init(); }
- // END Android-removed: Android doesn't need to call native init
+ // END Android-removed: Android doesn't need to call native init.
*/
Inet6Address() {
@@ -622,7 +622,7 @@
throws IOException, ClassNotFoundException {
NetworkInterface scope_ifname = null;
- // Android-changed: was getClass().getClassLoader() != null
+ // Android-changed: was getClass().getClassLoader() != null.
if (getClass().getClassLoader() != Class.class.getClassLoader()) {
throw new SecurityException ("invalid address type");
}
@@ -894,7 +894,7 @@
*/
@Override
public String getHostAddress() {
- // Android-changed: getnameinfo returns smarter representations than getHostAddress()
+ // Android-changed: getnameinfo returns smarter representations than getHostAddress().
// return holder6.getHostAddress();
return Libcore.os.getnameinfo(this, NI_NUMERICHOST); // Can't throw.
}
@@ -971,11 +971,11 @@
return sb.toString();
}
- // BEGIN Android-removed: Android doesn't need to call native init
+ // BEGIN Android-removed: Android doesn't need to call native init.
/*
* Perform class load-time initializations.
*
private static native void init();
*/
- // END Android-removed: Android doesn't need to call native init
+ // END Android-removed: Android doesn't need to call native init.
}
diff --git a/ojluni/src/main/java/java/net/URLStreamHandler.java b/ojluni/src/main/java/java/net/URLStreamHandler.java
index dffc6d5..c0876e8 100644
--- a/ojluni/src/main/java/java/net/URLStreamHandler.java
+++ b/ojluni/src/main/java/java/net/URLStreamHandler.java
@@ -134,9 +134,9 @@
boolean isRelPath = false;
boolean queryOnly = false;
- // BEGIN Android-changed: App compat
+ // BEGIN Android-changed: App compat.
boolean querySet = false;
- // END Android-changed: App compat
+ // END Android-changed: App compat.
// FIX: should not assume query if opaque
// Strip off the query part
@@ -148,22 +148,22 @@
if (limit > queryStart)
limit = queryStart;
spec = spec.substring(0, queryStart);
- // BEGIN Android-changed: App compat
+ // BEGIN Android-changed: App compat.
querySet = true;
- // END Android-changed: App compat
+ // END Android-changed: App compat.
}
}
int i = 0;
// Parse the authority part if any
- // BEGIN Android-changed: App compat
+ // BEGIN Android-changed: App compat.
// boolean isUNCName = (start <= limit - 4) &&
// (spec.charAt(start) == '/') &&
// (spec.charAt(start + 1) == '/') &&
// (spec.charAt(start + 2) == '/') &&
// (spec.charAt(start + 3) == '/');
boolean isUNCName = false;
- // END Android-changed: App compat
+ // END Android-changed: App compat.
if (!isUNCName && (start <= limit - 2) && (spec.charAt(start) == '/') &&
(spec.charAt(start + 1) == '/')) {
start += 2;
@@ -239,7 +239,7 @@
if (ind >= 0) {
// port can be null according to RFC2396
if (host.length() > (ind + 1)) {
- // BEGIN Android-changed: App compat
+ // BEGIN Android-changed: App compat.
// port = Integer.parseInt(host.substring(ind + 1));
char firstPortChar = host.charAt(ind+1);
if (firstPortChar >= '0' && firstPortChar <= '9') {
@@ -248,7 +248,7 @@
throw new IllegalArgumentException("invalid port: " +
host.substring(ind + 1));
}
- // END Android-changed: App compat
+ // END Android-changed: App compat.
}
host = host.substring(0, ind);
}
@@ -263,14 +263,14 @@
// If the authority is defined then the path is defined by the
// spec only; See RFC 2396 Section 5.2.4.
- // BEGIN Android-changed: App compat
+ // BEGIN Android-changed: App compat.
// if (authority != null && authority.length() > 0)
// path = "";
path = null;
if (!querySet) {
query = null;
}
- // END Android-changed: App compat
+ // END Android-changed: App compat.
}
if (host == null) {
@@ -297,21 +297,21 @@
path = seperator + spec.substring(start, limit);
}
}
- // BEGIN Android-changed: App compat
+ // BEGIN Android-changed: App compat.
//else if (queryOnly && path != null) {
// int ind = path.lastIndexOf('/');
// if (ind < 0)
// ind = 0;
// path = path.substring(0, ind) + "/";
//}
- // END Android-changed: App compat
+ // END Android-changed: App compat.
if (path == null)
path = "";
- // BEGIN Android-changed
+ // BEGIN Android-changed: always assume isRelPath is true.
//if (isRelPath) {
if (true) {
- // END Android-changed
+ // END Android-changed: always assume isRelPath is true.
// Remove embedded /./
while ((i = path.indexOf("/./")) >= 0) {
path = path.substring(0, i) + path.substring(i + 2);
@@ -319,21 +319,21 @@
// Remove embedded /../ if possible
i = 0;
while ((i = path.indexOf("/../", i)) >= 0) {
- // BEGIN Android-changed: App compat
+ // BEGIN Android-changed: App compat.
/*
* Trailing /../
*/
if (i == 0) {
path = path.substring(i + 3);
i = 0;
- // END Android-changed: App compat
+ // END Android-changed: App compat.
/*
* A "/../" will cancel the previous segment and itself,
* unless that segment is a "/../" itself
* i.e. "/a/b/../c" becomes "/a/c"
* but "/../../a" should stay unchanged
*/
- // Android-changed: App compat
+ // Android-changed: App compat.
// if (i > 0 && (limit = path.lastIndexOf('/', i - 1)) >= 0 &&
} else if (i > 0 && (limit = path.lastIndexOf('/', i - 1)) >= 0 &&
(path.indexOf("/../", limit) != 0)) {
@@ -360,7 +360,7 @@
if (path.endsWith("/."))
path = path.substring(0, path.length() -1);
- // Android-changed: App compat: Remove trailing ?
+ // Android-changed: App compat: Remove trailing '?'.
if (path.endsWith("?"))
path = path.substring(0, path.length() -1);
}
@@ -391,7 +391,7 @@
* @since 1.3
*/
protected boolean equals(URL u1, URL u2) {
- // Android-changed: Avoid network I/O
+ // Android-changed: Avoid network I/O.
return Objects.equals(u1.getRef(), u2.getRef()) &&
Objects.equals(u1.getQuery(), u2.getQuery()) &&
// sameFile compares the protocol, file, port & host components of
@@ -408,7 +408,7 @@
* @since 1.3
*/
protected int hashCode(URL u) {
- // Android-changed: Avoid network I/O
+ // Android-changed: Avoid network I/O.
// Hash on the same set of fields that we compare in equals().
return Objects.hash(
u.getRef(),
@@ -522,7 +522,7 @@
if (u.getRef() != null)
len += 1 + u.getRef().length();
- // BEGIN Android-changed: Add a toExternalForm variant that optionally escapes illegal chars
+ // BEGIN Android-changed: New toExternalForm variant that optionally escapes illegal chars.
// TODO: The variant has been removed. We can potentially revert the change
StringBuilder result = new StringBuilder(len);
result.append(u.getProtocol());
@@ -535,7 +535,7 @@
if (fileAndQuery != null) {
result.append(fileAndQuery);
}
- // END Android-changed: Add a toExternalForm variant that optionally escapes illegal chars
+ // END Android-changed: New toExternalForm variant that optionally escapes illegal chars.
if (u.getRef() != null) {
result.append("#");
result.append(u.getRef());
@@ -543,7 +543,7 @@
return result.toString();
}
- // Android-changed: Removed @see tag (target is package-private):
+ // Android-changed: Removed @see tag (target is package-private).
// @see java.net.URL#set(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String)
/**
* Sets the fields of the {@code URL} argument to the indicated values.
diff --git a/ojluni/src/main/java/java/security/Provider.java b/ojluni/src/main/java/java/security/Provider.java
index 9936859..6deb954 100644
--- a/ojluni/src/main/java/java/security/Provider.java
+++ b/ojluni/src/main/java/java/security/Provider.java
@@ -95,7 +95,7 @@
// Declare serialVersionUID to be compatible with JDK1.1
static final long serialVersionUID = -4298000515446427739L;
- // Android-added: Provider registration
+ // Android-added: Provider registration.
// Marking a provider as "registered" makes it change the security version when
// changes to it are made. As of 2017-05-22 this is only used in ProviderTest.
// TODO: Change ProviderTest to no longer require this mechanism
@@ -703,7 +703,7 @@
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
- // Android-added: Provider registration
+ // Android-added: Provider registration.
registered = false;
Map<Object,Object> copy = new HashMap<>();
for (Map.Entry<Object,Object> entry : super.entrySet()) {
@@ -717,7 +717,7 @@
}
private boolean checkLegacy(Object key) {
- // Android-added: Provider registration
+ // Android-added: Provider registration.
if (registered) {
Security.increaseVersion();
}
@@ -742,7 +742,7 @@
for (Map.Entry<?,?> e : t.entrySet()) {
implPut(e.getKey(), e.getValue());
}
- // Android-added: Provider registration
+ // Android-added: Provider registration.
if (registered) {
Security.increaseVersion();
}
@@ -817,7 +817,7 @@
if (!checkLegacy(key)) {
return null;
}
- // BEGIN Android-changed: use compute() instead of computeIfAbsent() to avoid cast fails
+ // BEGIN Android-changed: use compute(), not computeIfAbsent(), to avoid cast fails.
// The upstream code cannot ever succeed as the cast from BiFunction to Function
// always fails.
// legacyStrings.computeIfAbsent((String) key,
@@ -825,7 +825,7 @@
legacyStrings.compute((String) key,
(BiFunction<? super String, ? super String, ? extends String>)
remappingFunction);
- // END Android-changed: use compute() instead of computeIfAbsent() to avoid cast fails
+ // END Android-changed: use compute(), not computeIfAbsent(), to avoid cast fails.
}
return super.compute(key, remappingFunction);
}
@@ -887,7 +887,7 @@
serviceSet = null;
super.clear();
putId();
- // Android-added: Provider registration
+ // Android-added: Provider registration.
if (registered) {
Security.increaseVersion();
}
@@ -1192,7 +1192,7 @@
String key = type + "." + algorithm + " " + entry.getKey();
super.put(key, entry.getValue());
}
- // Android-added: Provider registration
+ // Android-added: Provider registration.
if (registered) {
Security.increaseVersion();
}
@@ -1214,7 +1214,7 @@
String key = type + "." + algorithm + " " + entry.getKey();
super.remove(key);
}
- // Android-added: Provider registration
+ // Android-added: Provider registration.
if (registered) {
Security.increaseVersion();
}
@@ -1883,7 +1883,7 @@
}
- // BEGIN Android-added: Provider registration
+ // BEGIN Android-added: Provider registration.
/**
* @hide
*/
@@ -1922,5 +1922,5 @@
// stored field, if the services didn't change in the meantime.
getServices();
}
- // END Android-added: Provider registration
+ // END Android-added: Provider registration.
}
diff --git a/ojluni/src/main/java/java/text/DateFormatSymbols.java b/ojluni/src/main/java/java/text/DateFormatSymbols.java
index 97dc528..5f48e1b 100644
--- a/ojluni/src/main/java/java/text/DateFormatSymbols.java
+++ b/ojluni/src/main/java/java/text/DateFormatSymbols.java
@@ -101,7 +101,7 @@
*/
public class DateFormatSymbols implements Serializable, Cloneable {
- // Android-changed: Removed reference to DateFormatSymbolsProvider but suggested getInstance()
+ // Android-changed: Removed reference to DateFormatSymbolsProvider but suggested getInstance().
// be used instead in case Android supports it in future.
/**
* Construct a DateFormatSymbols object by loading format data from
@@ -123,7 +123,7 @@
initializeData(Locale.getDefault(Locale.Category.FORMAT));
}
- // Android-changed: Removed reference to DateFormatSymbolsProvider but suggested getInstance()
+ // Android-changed: Removed reference to DateFormatSymbolsProvider but suggested getInstance().
// be used instead in case Android supports it in future.
/**
* Construct a DateFormatSymbols object by loading format data from
@@ -229,7 +229,7 @@
* Unlocalized date-time pattern characters. For example: 'y', 'd', etc.
* All locales use the same these unlocalized pattern characters.
*/
- // Android-changed: Add 'c' (standalone day of week), 'b' (day period),
+ // Android-changed: Add 'c' (standalone day of week), 'b' (day period),.
// 'B' (flexible day period)
static final String patternChars = "GyMdkHmsSEDFwWahKzZYuXLcbB";
@@ -258,7 +258,7 @@
static final int PATTERN_MONTH_STANDALONE = 22; // L
// Android-added: Constant for standalone day of week.
static final int PATTERN_STANDALONE_DAY_OF_WEEK = 23; // c
- // Android-added: Constant for pattern letter 'b', 'B'
+ // Android-added: Constant for pattern letter 'b', 'B'.
static final int PATTERN_DAY_PERIOD = 24; // b
static final int PATTERN_FLEXIBLE_DAY_PERIOD = 25; // B
@@ -844,7 +844,7 @@
// END Android-changed: Use ICU data and move cache handling to getCachedInstance().
}
- // Android-removed: toOneBasedArray(String[])
+ // Android-removed: toOneBasedArray(String[]).
// BEGIN Android-added: initializeSupplementaryData(LocaleData) for tiny and standalone fields.
private void initializeSupplementaryData(LocaleData localeData) {
@@ -917,10 +917,11 @@
}
return zoneStrings;
}
+ // END Android-changed: extract initialization of zoneStrings to separate method.
private String[][] getZoneStringsImpl(boolean needsCopy) {
+ // Android-changed: use helper method to initialize zoneStrings.
String[][] zoneStrings = internalZoneStrings();
- // END Android-changed: extract initialization of zoneStrings to separate method.
if (!needsCopy) {
return zoneStrings;
diff --git a/ojluni/src/main/java/java/util/Arrays.java b/ojluni/src/main/java/java/util/Arrays.java
index 6da3e5d..8cd8aaf 100644
--- a/ojluni/src/main/java/java/util/Arrays.java
+++ b/ojluni/src/main/java/java/util/Arrays.java
@@ -78,7 +78,7 @@
* tasks that makes parallel speedups unlikely.
* @hide
*/
- // Android-changed: Make MIN_ARRAY_SORT_GRAN public and @hide (used by harmony ArraysTest)
+ // Android-changed: Make MIN_ARRAY_SORT_GRAN public and @hide (used by harmony ArraysTest).
public static final int MIN_ARRAY_SORT_GRAN = 1 << 13;
// Suppresses default constructor, ensuring non-instantiability.
@@ -1232,14 +1232,14 @@
* {@link Comparable} contract
*/
public static void sort(Object[] a) {
- // Android-removed: LegacyMergeSort support
+ // Android-removed: LegacyMergeSort support.
// if (LegacyMergeSort.userRequested)
// legacyMergeSort(a);
// else
ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
}
- // Android-removed: legacyMergeSort() (unused on Android)
+ // Android-removed: legacyMergeSort() (unused on Android).
/**
* Sorts the specified range of the specified array of objects into
@@ -1295,14 +1295,14 @@
*/
public static void sort(Object[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
- // Android-removed: LegacyMergeSort support
+ // Android-removed: LegacyMergeSort support.
// if (LegacyMergeSort.userRequested)
// legacyMergeSort(a, fromIndex, toIndex);
// else
ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0);
}
- // Android-removed: legacyMergeSort() (unused on Android)
+ // Android-removed: legacyMergeSort() (unused on Android).
/**
* Tuning parameter: list size at or below which insertion sort will be
@@ -1417,7 +1417,7 @@
if (c == null) {
sort(a);
} else {
- // Android-removed: LegacyMergeSort support
+ // Android-removed: LegacyMergeSort support.
// if (LegacyMergeSort.userRequested)
// legacyMergeSort(a, c);
// else
@@ -1425,7 +1425,7 @@
}
}
- // Android-removed: legacyMergeSort() (unused on Android)
+ // Android-removed: legacyMergeSort() (unused on Android).
/**
* Sorts the specified range of the specified array of objects according
@@ -1485,7 +1485,7 @@
sort(a, fromIndex, toIndex);
} else {
rangeCheck(a.length, fromIndex, toIndex);
- // Android-removed: LegacyMergeSort support
+ // Android-removed: LegacyMergeSort support.
// if (LegacyMergeSort.userRequested)
// legacyMergeSort(a, fromIndex, toIndex, c);
// else
@@ -1493,8 +1493,8 @@
}
}
- // Android-removed: legacyMergeSort() (unused on Android)
- // Android-removed: mergeSort() (unused on Android)
+ // Android-removed: legacyMergeSort() (unused on Android).
+ // Android-removed: mergeSort() (unused on Android).
// Parallel prefix
@@ -4110,7 +4110,7 @@
for (Object element : a) {
int elementHash = 0;
- // BEGIN Android-changed: getComponentType() is faster than instanceof()
+ // BEGIN Android-changed: getComponentType() is faster than instanceof().
if (element != null) {
Class<?> cl = element.getClass().getComponentType();
if (cl == null)
@@ -4136,7 +4136,7 @@
else
elementHash = element.hashCode();
}
- // END Android-changed: getComponentType() is faster than instanceof()
+ // END Android-changed: getComponentType() is faster than instanceof().
result = 31 * result + elementHash;
}
diff --git a/ojluni/src/main/java/java/util/Calendar.java b/ojluni/src/main/java/java/util/Calendar.java
index 3a0343b..a5be988 100644
--- a/ojluni/src/main/java/java/util/Calendar.java
+++ b/ojluni/src/main/java/java/util/Calendar.java
@@ -1595,7 +1595,7 @@
*/
protected Calendar(TimeZone zone, Locale aLocale)
{
- // BEGIN Android-added: Allow aLocale == null
+ // BEGIN Android-added: Allow aLocale == null.
// http://b/16938922.
//
// TODO: This is for backwards compatibility only. Seems like a better idea to throw
@@ -1603,7 +1603,7 @@
if (aLocale == null) {
aLocale = Locale.getDefault();
}
- // END Android-added: Allow aLocale == null
+ // END Android-added: Allow aLocale == null.
fields = new int[FIELD_COUNT];
isSet = new boolean[FIELD_COUNT];
stamp = new int[FIELD_COUNT];
@@ -1667,7 +1667,7 @@
return createCalendar(zone, aLocale);
}
- // BEGIN Android-added: add getJapaneseImperialInstance()
+ // BEGIN Android-added: add getJapaneseImperialInstance().
/**
* Create a Japanese Imperial Calendar.
* @hide
@@ -1675,14 +1675,14 @@
public static Calendar getJapaneseImperialInstance(TimeZone zone, Locale aLocale) {
return new JapaneseImperialCalendar(zone, aLocale);
}
- // END Android-added: add getJapaneseImperialInstance()
+ // END Android-added: add getJapaneseImperialInstance().
private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
- // BEGIN Android-changed: only support GregorianCalendar here
+ // BEGIN Android-changed: only support GregorianCalendar here.
return new GregorianCalendar(zone, aLocale);
- // END Android-changed: only support GregorianCalendar here
+ // END Android-changed: only support GregorianCalendar here.
}
/**
@@ -2061,13 +2061,13 @@
* @since 1.6
*/
public String getDisplayName(int field, int style, Locale locale) {
- // BEGIN Android-changed: Treat ALL_STYLES as SHORT
+ // BEGIN Android-changed: Treat ALL_STYLES as SHORT.
// Android has traditionally treated ALL_STYLES as SHORT, even though
// it's not documented to be a valid value for style.
if (style == ALL_STYLES) {
style = SHORT;
}
- // END Android-changed: Treat ALL_STYLES as SHORT
+ // END Android-changed: Treat ALL_STYLES as SHORT.
if (!checkDisplayNameParams(field, style, SHORT, NARROW_FORMAT, locale,
ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
return null;
@@ -2161,7 +2161,7 @@
ERA_MASK|MONTH_MASK|DAY_OF_WEEK_MASK|AM_PM_MASK)) {
return null;
}
- // Android-added: Add complete() here to fix leniency, see http://b/35382060
+ // Android-added: Add complete() here to fix leniency. http://b/35382060
complete();
String calendarType = getCalendarType();
@@ -2209,12 +2209,12 @@
baseStyle < minStyle || baseStyle > maxStyle) {
throw new IllegalArgumentException();
}
- // BEGIN Android-added: Check for invalid baseStyle == 3
+ // BEGIN Android-added: Check for invalid baseStyle == 3.
// 3 is not a valid base style (unlike 1, 2 and 4). Throw if used.
if (baseStyle == 3) {
throw new IllegalArgumentException();
}
- // END Android-added: Check for invalid baseStyle == 3
+ // END Android-added: Check for invalid baseStyle == 3.
if (locale == null) {
throw new NullPointerException();
}
@@ -2574,12 +2574,12 @@
return style & ~STANDALONE_MASK;
}
- // BEGIN Android-changed: Make toStandaloneStyle() public to use in java.text.SimpleDateFormat
+ // BEGIN Android-changed: Make toStandaloneStyle() public to use in java.text.SimpleDateFormat.
/**
* @hide
*/
public static int toStandaloneStyle(int style) {
- // END Android-changed: Make toStandaloneStyle() public to use in java.text.SimpleDateFormat
+ // END Android-changed: Make toStandaloneStyle() public to use in java.text.SimpleDateFormat.
return style | STANDALONE_MASK;
}
diff --git a/ojluni/src/main/java/java/util/GregorianCalendar.java b/ojluni/src/main/java/java/util/GregorianCalendar.java
index 1d8c87b..46733e9 100644
--- a/ojluni/src/main/java/java/util/GregorianCalendar.java
+++ b/ojluni/src/main/java/java/util/GregorianCalendar.java
@@ -739,12 +739,12 @@
gdate = (BaseCalendar.Date) gcal.newCalendarDate(getZone());
}
- // BEGIN Android-added
+ // BEGIN Android-added: Constructor.
GregorianCalendar(long milliseconds) {
this();
setTimeInMillis(milliseconds);
}
- // END Android-added
+ // END Android-added: Constructor.
/////////////////
// Public methods
@@ -1080,7 +1080,7 @@
}
fd += delta; // fd is the expected fixed date after the calculation
- // BEGIN Android-changed: time zone related calculation via helper methods
+ // BEGIN Android-changed: time zone related calculation via helper methods.
// Calculate the time in the UTC time zone.
long utcTime = (fd - EPOCH_OFFSET) * ONE_DAY + timeOfDay;
@@ -1093,7 +1093,7 @@
// Update the time and recompute the fields.
setTimeInMillis(millis);
- // END Android-changed: time zone related calculation via helper methods
+ // END Android-changed: time zone related calculation via helper methods.
}
}
@@ -2346,12 +2346,12 @@
}
if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) {
if (tz instanceof ZoneInfo) {
- // BEGIN Android-changed: use libcore.util.ZoneInfo
+ // BEGIN Android-changed: use libcore.util.ZoneInfo.
// The method name to get offsets differs from sun.util.calendar.ZoneInfo
// zoneOffset = ((ZoneInfo)tz).getOffsets(time, zoneOffsets);
ZoneInfo zoneInfo = (ZoneInfo) tz;
zoneOffset = zoneInfo.getOffsetsByUtcTime(time, zoneOffsets);
- // END Android-changed: use libcore.util.ZoneInfo
+ // END Android-changed: use libcore.util.ZoneInfo.
} else {
zoneOffset = tz.getOffset(time);
zoneOffsets[0] = tz.getRawOffset();
@@ -2801,11 +2801,11 @@
// We use the TimeZone object, unless the user has explicitly set the ZONE_OFFSET
// or DST_OFFSET fields; then we use those fields.
TimeZone zone = getZone();
- // BEGIN Android-changed: time zone related calculation via helper methods
+ // BEGIN Android-changed: time zone related calculation via helper methods.
int tzMask = fieldMask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK);
millis = adjustForZoneAndDaylightSavingsTime(tzMask, millis, zone);
- // END Android-changed: time zone related calculation via helper methods
+ // END Android-changed: time zone related calculation via helper methods.
// Set this calendar's time in milliseconds
time = millis;
@@ -2828,7 +2828,7 @@
setFieldsNormalized(mask);
}
- // BEGIN Android-added: helper methods for time zone related calculation
+ // BEGIN Android-added: helper methods for time zone related calculation.
/**
* Calculates the time in milliseconds that this calendar represents using the UTC time,
* timezone information (specifically Daylight Savings Time (DST) rules, if any) and knowledge
@@ -2998,7 +2998,7 @@
}
return dstOffset;
}
- // END Android-added: helper methods for time zone related calculation
+ // END Android-added: helper methods for time zone related calculation.
/**
* Computes the fixed date under either the Gregorian or the
diff --git a/ojluni/src/main/java/java/util/TreeMap.java b/ojluni/src/main/java/java/util/TreeMap.java
index 20d98bc..3359635 100644
--- a/ojluni/src/main/java/java/util/TreeMap.java
+++ b/ojluni/src/main/java/java/util/TreeMap.java
@@ -1343,7 +1343,7 @@
*/
abstract static class NavigableSubMap<K,V> extends AbstractMap<K,V>
implements NavigableMap<K,V>, java.io.Serializable {
- // Android-changed: Explicitly add a serialVersionUID so that we're serialization
+ // Android-changed: Explicitly add a serialVersionUID so that we're serialization.
// compatible with the Java-7 version of this class. Several new methods were added
// in Java-8 but none of them have any bearing on the serialized format of the class
// or require any additional state to be preserved.
@@ -1877,11 +1877,11 @@
}
public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
- // BEGIN Android-changed: Fix for edge cases
+ // BEGIN Android-changed: Fix for edge cases.
// if (!inRange(toKey, inclusive))
if (!inRange(toKey) && !(!toEnd && m.compare(toKey, hi) == 0 &&
!hiInclusive && !inclusive))
- // END Android-changed: Fix for edge cases
+ // END Android-changed: Fix for edge cases.
throw new IllegalArgumentException("toKey out of range");
return new AscendingSubMap<>(m,
fromStart, lo, loInclusive,
@@ -1889,11 +1889,11 @@
}
public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
- // BEGIN Android-changed: Fix for edge cases
+ // BEGIN Android-changed: Fix for edge cases.
// if (!inRange(fromKey, inclusive))
if (!inRange(fromKey) && !(!fromStart && m.compare(fromKey, lo) == 0 &&
!loInclusive && !inclusive))
- // END Android-changed: Fix for edge cases
+ // END Android-changed: Fix for edge cases.
throw new IllegalArgumentException("fromKey out of range");
return new AscendingSubMap<>(m,
false, fromKey, inclusive,
@@ -1970,11 +1970,11 @@
}
public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
- // BEGIN Android-changed: Fix for edge cases
+ // BEGIN Android-changed: Fix for edge cases.
// if (!inRange(toKey, inclusive))
if (!inRange(toKey) && !(!fromStart && m.compare(toKey, lo) == 0 &&
!loInclusive && !inclusive))
- // END Android-changed: Fix for edge cases
+ // END Android-changed: Fix for edge cases.
throw new IllegalArgumentException("toKey out of range");
return new DescendingSubMap<>(m,
false, toKey, inclusive,
@@ -1982,11 +1982,11 @@
}
public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
- // BEGIN Android-changed: Fix for edge cases
+ // BEGIN Android-changed: Fix for edge cases.
// if (!inRange(fromKey, inclusive))
if (!inRange(fromKey) && !(!toEnd && m.compare(fromKey, hi) == 0 &&
!hiInclusive && !inclusive))
- // END Android-changed: Fix for edge cases
+ // END Android-changed: Fix for edge cases.
throw new IllegalArgumentException("fromKey out of range");
return new DescendingSubMap<>(m,
fromStart, lo, loInclusive,
diff --git a/ojluni/src/main/java/java/util/zip/ZipFile.java b/ojluni/src/main/java/java/util/zip/ZipFile.java
index 851aab1..e06fb6d 100644
--- a/ojluni/src/main/java/java/util/zip/ZipFile.java
+++ b/ojluni/src/main/java/java/util/zip/ZipFile.java
@@ -81,7 +81,7 @@
private final boolean locsig; // if zip file starts with LOCSIG (usually true)
private volatile boolean closeRequested = false;
- // Android-added: CloseGuard support
+ // Android-added: CloseGuard support.
private final CloseGuard guard = CloseGuard.get();
// Android-added: Do not use unlink() to implement OPEN_DELETE.
@@ -243,7 +243,7 @@
Integer.toHexString(mode));
}
String name = file.getPath();
- // Android-removed: SecurityManager is always null
+ // Android-removed: SecurityManager is always null.
/*
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
@@ -260,16 +260,16 @@
if (charset == null)
throw new NullPointerException("charset is null");
this.zc = ZipCoder.get(charset);
- // Android-removed: Skip perf counters
+ // Android-removed: Skip perf counters.
// long t0 = System.nanoTime();
jzfile = open(name, mode, file.lastModified(), usemmap);
- // Android-removed: Skip perf counters
+ // Android-removed: Skip perf counters.
// sun.misc.PerfCounter.getZipFileOpenTime().addElapsedTimeFrom(t0);
// sun.misc.PerfCounter.getZipFileCount().increment();
this.name = name;
this.total = getTotal(jzfile);
this.locsig = startsWithLOC(jzfile);
- // Android-added: CloseGuard support
+ // Android-added: CloseGuard support.
guard.open("close");
}
@@ -668,7 +668,7 @@
public void close() throws IOException {
if (closeRequested)
return;
- // Android-added: CloseGuard support
+ // Android-added: CloseGuard support.
if (guard != null) {
guard.close();
}
@@ -739,7 +739,7 @@
* @see java.util.zip.ZipFile#close()
*/
protected void finalize() throws IOException {
- // Android-added: CloseGuard support
+ // Android-added: CloseGuard support.
if (guard != null) {
guard.warnIfOpen();
}
diff --git a/ojluni/src/main/java/sun/misc/SharedSecrets.java b/ojluni/src/main/java/sun/misc/SharedSecrets.java
index 45cd489..226dbf7 100644
--- a/ojluni/src/main/java/sun/misc/SharedSecrets.java
+++ b/ojluni/src/main/java/sun/misc/SharedSecrets.java
@@ -35,7 +35,7 @@
for this purpose, namely the loss of compile-time checking. */
public class SharedSecrets {
- // BEGIN Android-removed: Pruned unused access interfaces
+ // BEGIN Android-removed: Pruned unused access interfaces.
/*
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static JavaUtilJarAccess javaUtilJarAccess;
@@ -46,9 +46,9 @@
private static JavaNetHttpCookieAccess javaNetHttpCookieAccess;
private static JavaNioAccess javaNioAccess;
*/
- // END Android-removed: Pruned unused access interfaces
+ // END Android-removed: Pruned unused access interfaces.
private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
- // BEGIN Android-removed: Pruned unused access interfaces
+ // BEGIN Android-removed: Pruned unused access interfaces.
/*
private static JavaSecurityProtectionDomainAccess javaSecurityProtectionDomainAccess;
private static JavaSecurityAccess javaSecurityAccess;
@@ -129,7 +129,7 @@
return javaIOAccess;
}
*/
- // END Android-removed: Pruned unused access interfaces
+ // END Android-removed: Pruned unused access interfaces.
public static void setJavaIOFileDescriptorAccess(JavaIOFileDescriptorAccess jiofda) {
javaIOFileDescriptorAccess = jiofda;
@@ -150,7 +150,7 @@
return javaIOFileDescriptorAccess;
}
- // BEGIN Android-removed: Pruned unused access interfaces
+ // BEGIN Android-removed: Pruned unused access interfaces.
/*
public static void setJavaOISAccess(JavaOISAccess access) {
javaOISAccess = access;
@@ -221,5 +221,5 @@
javaObjectInputStreamAccess = access;
}
*/
- // END Android-removed: Pruned unused access interfaces
+ // END Android-removed: Pruned unused access interfaces.
}
diff --git a/ojluni/src/main/java/sun/misc/URLClassPath.java b/ojluni/src/main/java/sun/misc/URLClassPath.java
index e9a89bc..0961d7a 100644
--- a/ojluni/src/main/java/sun/misc/URLClassPath.java
+++ b/ojluni/src/main/java/sun/misc/URLClassPath.java
@@ -360,7 +360,7 @@
lookupCacheEnabled = false;
}
- // BEGIN Android-changed: No lookup chache support
+ // BEGIN Android-changed: No lookup cache support.
/*
private static native URL[] getLookupCacheURLs(ClassLoader loader);
private static native int[] getLookupCacheForClassLoader(ClassLoader loader,
@@ -380,7 +380,7 @@
String className) {
return false;
}
- // END Android-changed: No lookup chache support
+ // END Android-changed: No lookup cache support.
synchronized boolean knownToNotExist(String className) {
@@ -816,7 +816,7 @@
private final HashMap<String, Loader> lmap;
private final AccessControlContext acc;
private boolean closed = false;
- // Android-changed: Not needed, called directly
+ // Android-changed: Not needed, called directly.
// private static final sun.misc.JavaUtilZipFileAccess zipAccess =
// sun.misc.SharedSecrets.getJavaUtilZipFileAccess();
diff --git a/ojluni/src/main/java/sun/misc/VM.java b/ojluni/src/main/java/sun/misc/VM.java
index f9060ba..0c5c4e5 100644
--- a/ojluni/src/main/java/sun/misc/VM.java
+++ b/ojluni/src/main/java/sun/misc/VM.java
@@ -93,7 +93,7 @@
return STATE_GREEN;
}
- // Android-removed: Not used
+ // Android-removed: Not used.
/** @deprecated */
// @Deprecated
// public static void registerVMNotification(VMNotification n) { }
@@ -233,7 +233,7 @@
return allowArraySyntax;
}
- // BEGIN Android-removed: Not used on android
+ // BEGIN Android-removed: Not used on android.
/**
* Returns true if the given class loader is in the system domain
* in which all permissions are granted.
@@ -241,7 +241,7 @@
// public static boolean isSystemDomainLoader(ClassLoader loader) {
// return loader == null;
// }
- // END Android-removed: Not used on android
+ // END Android-removed: Not used on android.
/**
* Returns the system property of the specified key saved at
@@ -403,7 +403,7 @@
private final static int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010;
private final static int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;
- // BEGIN Android-removed: latestUserDefinedLoader()/initialize() not supported
+ // BEGIN Android-removed: latestUserDefinedLoader()/initialize() not supported.
// /*
// * Returns the first non-null class loader up the execution stack,
// * or null if only code from the null class loader is on the stack.
@@ -414,5 +414,5 @@
// initialize();
// }
// private native static void initialize();
- // END Android-removed: latestUserDefinedLoader()/initialize() not supported
+ // END Android-removed: latestUserDefinedLoader()/initialize() not supported.
}
diff --git a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
index 49ad55c..c680c9c 100644
--- a/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
+++ b/ojluni/src/main/java/sun/nio/ch/DatagramChannelImpl.java
@@ -237,6 +237,18 @@
if (index == -1)
throw new IOException("Network interface cannot be identified");
Net.setInterface6(fd, index);
+ // BEGIN Android-added: Apply IP_MULTICAST_IF to dual-stack sockets.
+ // On dual-stack sockets, IP_MULTICAST_IF sets inet_sk(sk)->mc_index and
+ // inet_sk(sk)->mc_addr, which are specific to IPv4, and IPV6_MULTICAST_IF sets
+ // inet6_sk(sk)->mcast_oif, which are specific to IPv6. For IPv4 multicast
+ // traffic to work over an interface that is not the default, we need to
+ // configure both. http://b/144222142
+ Inet4Address target = Net.anyInet4Address(interf);
+ if (target != null) {
+ int targetAddress = Net.inet4AsInt(target);
+ Net.setInterface4(fd, targetAddress);
+ }
+ // END Android-added: Apply IP_MULTICAST_IF to dual-stack sockets.
} else {
// need IPv4 address to identify interface
Inet4Address target = Net.anyInet4Address(interf);
diff --git a/ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java b/ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java
index b4fdf70..6af86d5 100644
--- a/ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java
+++ b/ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java
@@ -116,7 +116,7 @@
return false;
}
- // Android-removed: Dead code: Unused method conservativeCheckMemberAccess()
+ // Android-removed: Dead code: Unused method conservativeCheckMemberAccess().
/**
* Checks package access on the given class.
@@ -262,6 +262,6 @@
return Proxy.isProxyClass(cls) && !pkg.isEmpty();
}
- // Android-removed: Dead code: unused method checkProxyMethod()
- // Android-removed: Dead code: unused method isVMAnonymousClass()
+ // Android-removed: Dead code: unused method checkProxyMethod().
+ // Android-removed: Dead code: unused method isVMAnonymousClass().
}
diff --git a/ojluni/src/main/java/sun/security/util/DerInputStream.java b/ojluni/src/main/java/sun/security/util/DerInputStream.java
index 6608676..7f42bb0 100644
--- a/ojluni/src/main/java/sun/security/util/DerInputStream.java
+++ b/ojluni/src/main/java/sun/security/util/DerInputStream.java
@@ -325,7 +325,7 @@
* (used to initialize an auto-growing data structure)
* @return array of the values in the sequence
*/
- // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation
+ // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation.
public DerValue[] getSequence(int startLen,
boolean originalEncodedFormRetained) throws IOException {
tag = (byte)buffer.read();
@@ -348,8 +348,8 @@
return getSequence(
startLen,
false); // no need to retain original encoded form
- // END Android-changed: Original encoded form needed for APKs parsing/validation
}
+ // END Android-changed: Original encoded form needed for APKs parsing/validation.
/**
* Return a set of encoded entities. ASN.1 sets are unordered,
@@ -381,7 +381,7 @@
*/
public DerValue[] getSet(int startLen, boolean implicit)
throws IOException {
- // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation
+ // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation.
return getSet(
startLen,
implicit,
@@ -398,7 +398,7 @@
}
}
return (readVector(startLen, originalEncodedFormRetained));
- // END Android-changed: Original encoded form needed for APKs parsing/validation
+ // END Android-changed: Original encoded form needed for APKs parsing/validation.
}
/*
@@ -407,7 +407,7 @@
* this same helper routine.
*/
protected DerValue[] readVector(int startLen) throws IOException {
- // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation
+ // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation.
return readVector(
startLen,
false); // no need to retain original encoded form
@@ -420,7 +420,7 @@
*/
protected DerValue[] readVector(int startLen,
boolean originalEncodedFormRetained) throws IOException {
- // END Android-changed: Original encoded form needed for APKs parsing/validation
+ // END Android-changed: Original encoded form needed for APKs parsing/validation.
DerInputStream newstr;
byte lenByte = (byte)buffer.read();
@@ -465,7 +465,7 @@
DerValue value;
do {
- // Android-changed: Original encoded form needed for APKs parsing/validation
+ // Android-changed: Original encoded form needed for APKs parsing/validation.
value = new DerValue(newstr.buffer, originalEncodedFormRetained);
vec.addElement(value);
} while (newstr.available() > 0);
diff --git a/ojluni/src/main/java/sun/security/util/DerValue.java b/ojluni/src/main/java/sun/security/util/DerValue.java
index 3045995..7828820 100644
--- a/ojluni/src/main/java/sun/security/util/DerValue.java
+++ b/ojluni/src/main/java/sun/security/util/DerValue.java
@@ -72,13 +72,13 @@
private int length;
- // BEGIN Android-added: Original encoded form needed for APKs parsing/validation
+ // BEGIN Android-added: Original encoded form needed for APKs parsing/validation.
/**
* The original encoded form of the whole value (tag, length, and value)
* or null if the form was not provided or was not retained during parsing.
*/
private byte[] originalEncodedForm;
- // END Android-added: Original encoded form needed for APKs parsing/validation
+ // END Android-added: Original encoded form needed for APKs parsing/validation.
/*
* The type starts at the first byte of the encoding, and
@@ -251,7 +251,7 @@
/*
* package private
*/
- // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation
+ // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation.
DerValue(DerInputBuffer in, boolean originalEncodedFormRetained)
throws IOException {
// XXX must also parse BER-encoded constructed
@@ -297,7 +297,7 @@
int consumed = in.getPos() - startPosInInput;
originalEncodedForm = in.getSlice(startPosInInput, consumed);
}
- // END Android-changed: Original encoded form needed for APKs parsing/validation
+ // END Android-changed: Original encoded form needed for APKs parsing/validation.
}
/**
@@ -838,7 +838,7 @@
}
}
- // BEGIN Android-added: Original encoded form needed for APKs parsing/validation
+ // BEGIN Android-added: Original encoded form needed for APKs parsing/validation.
/**
* Returns the original encoded form or {@code null} if the form was not
* retained or is not available.
@@ -847,7 +847,7 @@
return (originalEncodedForm != null)
? originalEncodedForm.clone() : null;
}
- // END Android-added: Original encoded form needed for APKs parsing/validation
+ // END Android-added: Original encoded form needed for APKs parsing/validation.
/**
* Returns a DER-encoded value, such that if it's passed to the
diff --git a/ojluni/src/main/java/sun/security/x509/X509CertImpl.java b/ojluni/src/main/java/sun/security/x509/X509CertImpl.java
index 57a8f71..f15b998 100644
--- a/ojluni/src/main/java/sun/security/x509/X509CertImpl.java
+++ b/ojluni/src/main/java/sun/security/x509/X509CertImpl.java
@@ -192,7 +192,7 @@
}
}
- // BEGIN Android-removed: unused code
+ // BEGIN Android-removed: unused code.
/*
/**
* unmarshals an X.509 certificate from an input stream. If the
@@ -280,7 +280,7 @@
return der;
}
*/
- // END Android-removed: unused code
+ // END Android-removed: unused code.
/**
* Construct an initialized X509 Certificate. The certificate is stored
@@ -310,7 +310,7 @@
}
}
- // BEGIN Android-added: Ctor to retain original encoded form for APKs parsing
+ // BEGIN Android-added: Ctor to retain original encoded form for APKs parsing.
/**
* Unmarshal a certificate from its encoded form, parsing a DER value.
* This form of constructor is used by agents which need to examine
@@ -328,7 +328,7 @@
throw new CertificateException("Unable to initialize, " + e, e);
}
}
- // END Android-added: Ctor to retain original encoded form for APKs parsing
+ // END Android-added: Ctor to retain original encoded form for APKs parsing.
/**
* Appends the certificate to an output stream.
@@ -1814,7 +1814,7 @@
throw new CertificateParsingException(
"invalid DER-encoded certificate data");
- // Android-changed: Needed for providing encoded form of cert
+ // Android-changed: Needed for providing encoded form of cert.
// signedCert = val.toByteArray();
signedCert =
(originalEncodedForm != null)
@@ -1972,12 +1972,12 @@
private ConcurrentHashMap<String,String> fingerprints =
new ConcurrentHashMap<>(2);
-// BEGIN Android-removed
+// BEGIN Android-removed: unused code.
// public String getFingerprint(String algorithm) {
// return fingerprints.computeIfAbsent(algorithm,
// x -> getFingerprint(x, this));
// }
-// END Android-removed
+// END Android-removed: unused code.
/**
* Gets the requested finger print of the certificate. The result
diff --git a/ojluni/src/main/java/sun/util/locale/LocaleMatcher.java b/ojluni/src/main/java/sun/util/locale/LocaleMatcher.java
index 70fabc7..37eb416 100644
--- a/ojluni/src/main/java/sun/util/locale/LocaleMatcher.java
+++ b/ojluni/src/main/java/sun/util/locale/LocaleMatcher.java
@@ -212,7 +212,7 @@
if (range.equals("*")) {
continue;
}
- // Android-changed: backport OpenJDK 9 fix for JDK-8166994
+ // Android-changed: backport OpenJDK 9 fix for JDK-8166994.
String rangeForRegex = range.replace("*", "\\p{Alnum}*");
while (rangeForRegex.length() > 0) {
for (String tag : tags) {
@@ -242,7 +242,7 @@
}
public static List<LanguageRange> parse(String ranges) {
- // Android-changed: backport OpenJDK 9 fix for JDK-8166994
+ // Android-changed: backport OpenJDK 9 fix for JDK-8166994.
ranges = ranges.replace(" ", "").toLowerCase();
if (ranges.startsWith("accept-language:")) {
ranges = ranges.substring(16); // delete unnecessary prefix
@@ -332,7 +332,7 @@
return list;
}
- // BEGIN Android-added: backport OpenJDK 9 fix for JDK-8166994
+ // BEGIN Android-added: backport OpenJDK 9 fix for JDK-8166994.
/**
* A faster alternative approach to String.replaceFirst(), if the given
* string is a literal String, not a regex.
@@ -347,7 +347,7 @@
+ range.substring(pos + substr.length());
}
}
- // END Android-added: backport OpenJDK 9 fix for JDK-8166994
+ // END Android-added: backport OpenJDK 9 fix for JDK-8166994.
private static String[] getEquivalentsForLanguage(String range) {
String r = range;
@@ -357,7 +357,7 @@
String equiv = LocaleEquivalentMaps.singleEquivMap.get(r);
// Return immediately for performance if the first matching
// subtag is found.
-// BEGIN Android-added: backport OpenJDK 9 fix for JDK-8166994
+// BEGIN Android-added: backport OpenJDK 9 fix for JDK-8166994.
// Upstream bug: https://bugs.openjdk.java.net/browse/JDK-8166994
// Upstream fix: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/60837db5d445
return new String[]{replaceFirstSubStringMatch(range,
@@ -370,7 +370,7 @@
r, equivs[i]);
}
return result;
-// END Android-added: backport OpenJDK 9 fix for JDK-8166994
+// END Android-added: backport OpenJDK 9 fix for JDK-8166994.
}
// Truncate the last subtag simply.
diff --git a/tools/patch-style/libcore-patch-style.awk b/tools/patch-style/libcore-patch-style.awk
new file mode 100644
index 0000000..e138298
--- /dev/null
+++ b/tools/patch-style/libcore-patch-style.awk
@@ -0,0 +1,175 @@
+# Copyright 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.
+
+# Simple libcore patch-style checking based on http://go/libcore-patch-style.
+#
+# See sample-input.java for examples of matches and failures.
+#
+# Usage:
+# awk -f libcore-patch-style.awk <file0> [... fileN]
+#
+# This script ignores any files whose name does not end in the suffix ".java".
+#
+# To scan all source code in the libcore tree:
+# $ cd libcore
+# $ find . -type f | xargs awk -f tools/patch-style/libcore-patch-style.awk
+#
+# To find sources with the most issues:
+# $ cd libcore
+# $ find . -type f | xargs awk -f tools/patch-style/libcore-patch-style.awk \
+# | grep -F ./ | sed -e 's/:.*//' | uniq -c | sort -n -r | head
+
+BEGIN {
+ g_errors = 0 # Number of errors accumulated.
+ g_expected_end = "" # Expected END line.
+ g_max_length = 100 # Maximum line length for markers (0 == no checking).
+ g_stop_oneline_interleaving = 0 # Error one-line comments between BEGIN and END markers.
+}
+
+BEGINFILE {
+ # Skip files whose names do not have a .java suffix.
+ if (FILENAME !~ /\.java$/) {
+ nextfile
+ }
+
+ # Reset the line number for reporting errors back to zero.
+ NR = 0
+
+ # Clear expected end marker as processing a new file.
+ g_expected_end = ""
+}
+
+function error(message) {
+ print(FILENAME ":" NR ":", message "\n")
+ g_errors += 1;
+}
+
+function expectationError(reason, expected, actual) {
+ error(reason "\n Expected: \"" expected "\"\n Actual: \"" actual "\"")
+}
+
+function inputError(reason, actual) {
+ error(reason "\n Input: \"" actual "\"")
+}
+
+function checkLineLength(line) {
+ if (g_max_length > 0 && length(line) > g_max_length) {
+ inputError("Line too long", line)
+ }
+}
+
+function leftTrim(message) {
+ return gensub(/^ */, "", 1, message)
+}
+
+function failIfEndExpected() {
+ if (g_expected_end != "") {
+ expectationError("Missing END marker.", g_expected_end, $0)
+ g_expected_end = ""
+ }
+}
+
+function expectEndFor(begin_line) {
+ g_expected_end = begin_line
+ sub("BEGIN", "END", g_expected_end)
+}
+
+function actualEndFor(actual_line) {
+ if (actual_line != g_expected_end) {
+ expectationError("Bad END marker.", g_expected_end, actual_line)
+ }
+ g_expected_end = ""
+}
+
+function processBeginMarker(line) {
+ failIfEndExpected()
+ expectEndFor(line)
+}
+
+function processEndMarker(line) {
+ actualEndFor(line)
+}
+
+# BEGIN marker ending in a period.
+/^ *\/\/ BEGIN Android-(added|changed|note|removed):.*\./ {
+ checkLineLength($0)
+ processBeginMarker($0)
+ next
+}
+
+# BEGIN marker ending in a period.
+/^ *\/\/ END Android-(added|changed|note|removed):.*\./ {
+ checkLineLength($0)
+ processEndMarker($0)
+ next
+}
+
+# BEGIN marker ending in a bug reference.
+/^ *\/\/ BEGIN Android-(added|changed|note|removed):.*[.](http:\/\/)?b\/[1-9][0-9]*/ {
+ checkLineLength($0)
+ processBeginMarker($0)
+ next
+}
+
+# BEGIN marker ending in anything else, oops!
+/^ *\/\/ BEGIN Android-(added|changed|note|removed)[^:].*/ {
+ inputError("BEGIN marker is missing colon or description.", $0)
+ next
+}
+
+# END marker, should be paired with last BEGIN marker.
+/^ *\/\/ END Android-(added|changed|note|removed):.*/ {
+ checkLineLength($0)
+ processEndMarker($0)
+ next
+}
+
+# One line change marker ending in a period.
+/^ *\/\/ Android-(added|changed|note|removed):.*[.]/ {
+ checkLineLength($0)
+ if (g_stop_oneline_interleaving) {
+ failIfEndExpected()
+ }
+ next
+}
+
+# One line change marker ending in a bug reference.
+/^ *\/\/ Android-(added|changed|note|removed):[.](http:\/\/)?b\/[1-9][0-9]*/ {
+ checkLineLength($0)
+ if (g_stop_oneline_interleaving) {
+ failIfEndExpected()
+ }
+ next
+}
+
+# One line change marker missing comment after colon.
+/^ *\/\/ BEGIN Android-(added|changed|note|removed).*/ {
+ inputError("Bad change marker: missing colon or description.", $0)
+ next
+}
+
+# Something that looks like a potential change marker.
+/^ *(\/\*|\/\/|\*) *(Android|ANDROID)-/ {
+ if (g_stop_oneline_interleaving) {
+ failIfEndExpected()
+ }
+ inputError("Bad change marker.", $0)
+ next
+}
+
+END {
+ failIfEndExpected()
+ printf("Found " g_errors " libcore patch style issues.\n")
+ exit g_errors == 0
+}
diff --git a/tools/patch-style/sample-input.java b/tools/patch-style/sample-input.java
new file mode 100644
index 0000000..8d55cfe
--- /dev/null
+++ b/tools/patch-style/sample-input.java
@@ -0,0 +1,32 @@
+# HAPPY PATHS
+ // BEGIN Android-added: something bot like.
+ // END Android-added: something bot like.
+
+ // BEGIN Android-changed: something bot like. http://b/12345
+ // END Android-changed: something bot like. http://b/12345
+
+ // BEGIN Android-removed: coffee stain. b/12345
+ // END Android-changed: something bot like. http://b/12345
+
+ // Android-added: hello world.
+ // Android-change: hello world. http://b/1100
+ // Android-remove: goodbye world. http://b/999912
+
+# UNHAPPY PATHS
+
+ // BEGIN Android-added something bot like.
+ // END Android-added something bot like.
+
+ // Android-note: blah
+ // Android-note: blah.
+ // Android-changed hello
+ // Android-added: hello
+
+ /* Android-note blah balh */
+ /* Android note: blah balh */
+ /* ANDROID android android android */
+ * ANDROID *
+
+Android-bar
+
+// BEGIN Android-removed: END from last line.
diff --git a/tools/testmapping/README b/tools/testmapping/README
new file mode 100644
index 0000000..0222018
--- /dev/null
+++ b/tools/testmapping/README
@@ -0,0 +1,36 @@
+These scripts help generate the libcore TEST_MAPPING smoke tests, i.e. a set of
+tests to run on every change, chosen to run as many as possible in less than
+some time limit.
+
+The process is as follows.
+1. Do `source build/envsetup.sh` and `lunch <whatever>` as normal.
+2. Run the CtsLibcoreTestCases tests to generate logs to extract timings from.
+ This can be done with `atest CtsLibcoreTestCases` as normal. Make sure to use
+ an appropriate device (virtual or physical).
+3. Do that two more times. We'll use best-of-three timings, since sometimes a
+ test takes an unusual amount of time (perhaps because of GC pause or other
+ jank) and it should not be excluded for that.
+4. Run the save_logs.py script to copy the logs from out/ to libcore/smoketest.
+ (Empty that directory if it exists already). This is interactive and allows
+ you to pick the runs you want. (If you prefer, you can run this after each
+ run, rather than once after all three runs.)
+5. Run the gen_smoke_tests.py script to generate libcore/TEST_MAPPING.
+6. Check stdout from the script looks okay (not too many warnings, sensible
+ numbers, etc.).
+7. Check the generated TEST_MAPPING looks okay.
+8. Do e.g. `time atest --test-mapping libcore` to check it runs okay.
+9. Delete libcore/smoketest/ once you're happy.
+10. Submit the new TEST_MAPPING.
+
+The scripts take no options. There are some constants at the start you can
+adjust. (These could be converted to command-line options if convenient.)
+
+See comments in the scripts for more on how they work.
+
+At time of writing, with the current configuration, this generates a sensible
+number of classes to exclude, so the TEST_MAPPING looks reasonable. If this list
+becomes too long, we'll have to find a way to simplify it, by rolling up to a
+higher granularity. Given the way that atest et al are configured, that will
+probably mean excluding more things.
+
+TODO(peteg): What about PTS?
diff --git a/tools/testmapping/gen_smoke_tests.py b/tools/testmapping/gen_smoke_tests.py
new file mode 100755
index 0000000..159be1b
--- /dev/null
+++ b/tools/testmapping/gen_smoke_tests.py
@@ -0,0 +1,474 @@
+#!/usr/bin/env python2
+#
+# Copyright 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.
+
+"""Tool to generate data for smoke tests."""
+
+from __future__ import print_function
+
+import collections
+import datetime
+import gzip
+import operator
+import os
+import re
+import tempfile
+
+import jinja2
+import util
+
+ANDROID_REPOSITORY_ROOT = util.android_repository_root()
+LIBCORE_DIR = os.path.join(ANDROID_REPOSITORY_ROOT, 'libcore')
+LOGS_DIR = os.path.join(LIBCORE_DIR, 'smoketest')
+REQUIRED_RUNS = 3
+CTS_LOG_LINE_PATTERN = (r'(\d+)-(\d+) +(\d+):(\d+):(\d+)\.(\d+) +\d+ +\d+ +'
+ r'[^ ]+ (CtsTestRunListener|TestRunner) *: *(.+)')
+THIS_YEAR = datetime.datetime.now().year
+START_MATCHER = ('CtsTestRunListener', r'Now executing\s*:\s*(.+)')
+TESTS_RAN_MATCHER = ('TestRunner', r'started\s*:.*')
+END_MATCHER = ('CtsTestRunListener', r'Total memory\s*:.+')
+HARD_END_MATCHER = ('TestRunner', r'run finished\s*:.+')
+JAVA_CLASS_PATTERN = r'(?:([a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*)\.)?[a-zA-Z_][a-zA-Z0-9_]*'
+MAX_RUN_TIME = datetime.timedelta(minutes=10)
+OUT_DIR = tempfile.mkdtemp()
+ROLL_UP_TEST_CLASSES_TO_PACKAGE = False
+CTS_MODULE_NAME = 'CtsLibcoreTestCases'
+
+TEST_MAPPING_TEMPLATE = jinja2.Template("""
+{
+ "presubmit": [
+ {
+ "name": "{{module}}",
+ "options": [{% for test in exclusions %}
+ {
+ "exclude-filter": "{{test}}"
+ }{% if not loop.last %},{% endif %}{% endfor %}
+ ]
+ }
+ ]
+}
+""".strip())
+
+
+def find_all_log_files():
+ """Returns a list of the log files to read."""
+ if not os.path.isdir(LOGS_DIR):
+ raise Exception('Could not find logs directory ' + LOGS_DIR)
+ filenames = os.listdir(LOGS_DIR)
+ if not filenames:
+ raise Exception('Found empty logs directory ' + LOGS_DIR)
+ if len(filenames) != REQUIRED_RUNS:
+ raise Exception('Expected to find exactly %d files in %s, found %d' %
+ (REQUIRED_RUNS, LOGS_DIR, len(filenames)))
+ return map(lambda f: os.path.join(LOGS_DIR, f), filenames)
+
+
+def read_cts_logs(filename):
+ """Read CTS entries from a log file.
+
+ Args:
+ filename: The name of the file to read.
+
+ Yields:
+ Tuples of timestamps (as datetimes), log sources, and log messages.
+ """
+ print('Reading ' + util.printable_path(filename))
+ with gzip.open(filename, mode='rt') as log_file:
+ for line in log_file:
+ cts_match = re.match(CTS_LOG_LINE_PATTERN, line)
+ if cts_match:
+ assert len(cts_match.groups()) == 8
+ timestamp = datetime.datetime(
+ year=THIS_YEAR,
+ month=int(cts_match.group(1)),
+ day=int(cts_match.group(2)),
+ hour=int(cts_match.group(3)),
+ minute=int(cts_match.group(4)),
+ second=int(cts_match.group(5)),
+ microsecond=1000 * int(cts_match.group(6)))
+ source = cts_match.group(7)
+ message = cts_match.group(8)
+ yield (timestamp, source, message)
+
+
+def match(matcher, got_source, message):
+ """Check whether a log line matches requirements.
+
+ Args:
+ matcher: A pair of the required log source and a pattern to match messages.
+ got_source: The actual log source.
+ message: The actual message.
+
+ Returns:
+ A MatchObject from the pattern match against the message, or None.
+ """
+ (want_source, pattern) = matcher
+ if got_source == want_source:
+ return re.match(pattern, message)
+ else:
+ return None
+
+
+def parse_running_times(filename):
+ """Parse the running times from a log file.
+
+ Args:
+ filename: The name of the file to read.
+
+ Yields:
+ Pairs of test names and running times (as timedeltas). Also emits the
+ overall elapsed time from the start of the first test to the end of the last
+ test with the key 'OVERALL'.
+
+ Raises:
+ Exception: The log file entries didn't look like we expected.
+ """
+ executing = None
+ start_timestamp = None
+ ran_tests = False
+ overall_start_timestamp = None
+ overall_end_timestamp = None
+ for (timestamp, source, message) in read_cts_logs(filename):
+ start_match = match(START_MATCHER, source, message)
+ tests_ran_match = match(TESTS_RAN_MATCHER, source, message)
+ end_match = match(END_MATCHER, source, message)
+ hard_end_match = match(HARD_END_MATCHER, source, message)
+ if not executing:
+ if start_match:
+ assert len(start_match.groups()) == 1
+ executing = start_match.group(1)
+ start_timestamp = timestamp
+ if not overall_start_timestamp:
+ overall_start_timestamp = timestamp
+ else:
+ if start_match:
+ raise Exception(
+ 'Found start for %s while waiting for end for %s at %s in %s' %
+ (start_match.group(1), executing, str(timestamp), filename))
+ if tests_ran_match:
+ ran_tests = True
+ if end_match or hard_end_match:
+ running_time = timestamp - start_timestamp
+ # We see two types of execution in the logs. One appears to be some kind
+ # of dry run which doesn't actually run any tests (and completes
+ # significantly faster). We want the one that actually runs tests.
+ if ran_tests:
+ yield (executing, running_time)
+ executing = None
+ start_timestamp = None
+ ran_tests = False
+ overall_end_timestamp = timestamp
+ if executing:
+ raise Exception('Reached EOF while waiting for end for %s in %s' %
+ (executing, filename))
+ yield ('OVERALL', overall_end_timestamp - overall_start_timestamp)
+
+
+def collect_running_times(filenames):
+ """Collect running times from some log file.
+
+ Args:
+ filenames: The names of the files to read.
+
+ Returns:
+ A tuple containing (1) a dictionary mapping test names to sets of running
+ times (as timedeltas), and (2) a list of overall running times (i.e. elapsed
+ times from the start of the first test to the end of the last test).
+ """
+ times_by_test = collections.defaultdict(list)
+ output_path = os.path.join(OUT_DIR, 'test_times.txt')
+ overall_times = []
+ with open(output_path, 'w') as output:
+ for filename in filenames:
+ for (test_name, time) in parse_running_times(filename):
+ output.write('%s: %g ms\n' % (test_name, time.total_seconds() * 1000))
+ if test_name == 'OVERALL':
+ overall_times.append(time)
+ else:
+ times_by_test[test_name].append(time)
+ print('Wrote test times to ' + util.printable_path(output_path))
+ return (times_by_test, overall_times)
+
+
+def process_running_times(times_by_test):
+ """Processes the collected running times.
+
+ Args:
+ times_by_test: A dictionary mapping test names to sets of running times.
+
+ Returns:
+ A dictionary mapping test names to fastest running times.
+ """
+ for (test, times) in times_by_test.iteritems():
+ if len(times) != REQUIRED_RUNS:
+ print('Warning: Only found %d runs for %s' % (len(times), test))
+ return {test: min(times) for (test, times) in times_by_test.iteritems()}
+
+
+def calculate_overhead_ratio(overall_times, fastest_time_by_test):
+ """Calculates a ratio for the actual overall time to the sum of test times.
+
+ The actual overall times are the elapsed times from the start of the first
+ test to the end of the last test. The average of these is used. The ratio is
+ taken with the sume of the fastest time for each test (which is what will be
+ used for scoring).
+
+ Args:
+ overall_times: A list of overall running times.
+ fastest_time_by_test: A dictionary mapping test names to fastest running
+ times.
+
+ Returns:
+ The ratio.
+ """
+ average_overall_time = sum(overall_times,
+ datetime.timedelta(0)) / len(overall_times)
+ total_time_by_test = sum(fastest_time_by_test.values(), datetime.timedelta(0))
+ ratio = (
+ average_overall_time.total_seconds() / total_time_by_test.total_seconds())
+ print(
+ 'Average time for run is %g seconds, sum of fastest test times is %g, ratio is %g'
+ % (average_overall_time.total_seconds(),
+ total_time_by_test.total_seconds(), ratio))
+................................................................................
+ # N.B. Possible future enhancement: Currently, because# we take the fastest of
+ # three runs, a real run will always be slightly slower than we predict. We
+ # could multiply in another overhead factor to account for this, e.g. by
+ # looking at the ratio of the mean of the three to the fastest of the three.
+ # (This factor should be applied globally rather than individually to each
+ # test so as not to penalize tests which happened to have a slow run or two.)
+ # This is not a high priority since for now we can just set MAX_RUN_TIME a bit
+ # low to allow for this.
+ return ratio
+
+
+def get_parent(name):
+ """Returns the parent of a Java class or package name."""
+ class_match = re.match(JAVA_CLASS_PATTERN, name)
+ if not class_match:
+ raise Exception('Could not parse Java class name ' + name)
+ assert len(class_match.groups()) == 1
+ return class_match.group(1)
+
+
+def group_times_by_package(times_by_test):
+ """Groups the test classes by package name, summing the times.
+
+ Args:
+ times_by_test: A dictionary mapping test names to fastest running times.
+
+ Returns:
+ A dictionary mapping package names to total fastest running times.
+ """
+ time_by_package = collections.defaultdict(datetime.timedelta)
+ for (clazz, time) in times_by_test.iteritems():
+ package = get_parent(clazz)
+ if package: # A few tests have no package. They're weird, let's skip them.
+ time_by_package[package] = time_by_package[package] + time
+ output_path = os.path.join(OUT_DIR, 'package_times.txt')
+ with open(output_path, 'w') as output:
+ for (package, time) in time_by_package.iteritems():
+ output.write('%s: %s ms\n' % (package, time.total_seconds() * 1000.0))
+ print('Wrote package times to ' + util.printable_path(output_path))
+ return time_by_package
+
+
+def find_tests_to_run(time_by_test, overhead_ratio):
+ """Finds the tests to actually run.
+
+ The tests chosen will be the fastest set such that their total time, when
+ multiplied by the overhead ratio, is less than the maximum.
+
+ Args:
+ time_by_test: A dictionary mapping test names to total fastest running
+ times. The names can be packages, classes, or a mixture of the two.
+ overhead_ratio: A ratio for the actual overall time to the sum of test
+ times.
+
+ Returns:
+ A list of test names whose running times are below the threshold.
+
+ Raises:
+ Exception: The total running time of all the tests is below the threhold.
+ """
+ test_inclusions = {test: False for test in time_by_test.keys()}
+ included = 0
+ total_time = datetime.timedelta()
+ output_path = os.path.join(OUT_DIR, 'included_tests.txt')
+ adjusted_max_run_time_seconds = MAX_RUN_TIME.total_seconds() / overhead_ratio
+ with open(output_path, 'w') as output:
+ for (test, time) in sorted(
+ time_by_test.iteritems(), key=operator.itemgetter(1)):
+ if (total_time + time).total_seconds() <= adjusted_max_run_time_seconds:
+ test_inclusions[test] = True
+ included += 1
+ total_time += time
+ output.write('%s: %g ms -> %g ms\n' %
+ (test, time.total_seconds() * 1000.0,
+ total_time.total_seconds() * 1000.0))
+ else:
+ print('Can run fastest %d of %d tests in %g * %g = %g seconds' %
+ (included, len(time_by_test), total_time.total_seconds(),
+ overhead_ratio, total_time.total_seconds() * overhead_ratio))
+ print('Wrote tests to include to ' + util.printable_path(output_path))
+ return test_inclusions
+ raise Exception('Apparently we can run all the tests? This smells wrong.')
+
+
+def build_test_tree(tests):
+ """Builds a tree of tests.
+
+ Args:
+ tests: The list of tests to build into a tree. These can be packages,
+ classes, or a mixture of the two.
+
+ Returns:
+ A dictionary mapping every test's ancestors to its children. The roots
+ appear as children of None.
+ """
+ tree = collections.defaultdict(set)
+ for test in tests:
+ while True:
+ parent = get_parent(test)
+ tree[parent].add(test)
+ if parent:
+ test = parent
+ else:
+ break
+ return tree
+
+
+def build_exclusion_list(test_inclusions):
+ """Builds a list of tests to exclude.
+
+ Args:
+ test_inclusions: A dictionary mapping test names to whether or not they
+ should be included in the smoke tests. The names can be packages, classes,
+ or a mixture of the two.
+
+ Returns:
+ A list of the exclusions. These could be individual tests, or packages or
+ some part of the package hierarchy if they are to be entirely excluded.
+ """
+ tree = build_test_tree(test_inclusions.keys())
+ exclusions = []
+
+ # We do a DFS of the tree, rolling up exclusions as far as possible, i.e. if
+ # an entire branch is excluded, we exclude that branch rather than all of its
+ # leaves.
+
+ def visit(test):
+ """Visitor for a DFS of the tree.
+
+ Args:
+ test: The test to visit (either a class or package name).
+
+ Returns:
+ Whether or not the parent should include this node in the tree.
+
+ Raises:
+ Exception: The tree had an unexpected structure.
+ """
+ if test in test_inclusions:
+ # We only expect to have inclusion status for the leaves of the tree.
+ # Check that this is the case.
+ if test in tree:
+ raise Exception('The name %s is used for a leaf and a branch!' % test)
+ # Return to the parent node whether this leaf is included.
+ return test_inclusions[test]
+ else:
+ # We expect to have inclusion status for all leaves of the tree. Check
+ # that this is the case.
+ if test not in tree:
+ raise Exception('Leaf %s has no inclusion status!' % test)
+ # Look at all the children of this node.
+ any_child_included = False
+ child_exclusions = []
+ for child in tree[test]:
+ child_included = visit(child)
+ if child_included:
+ any_child_included = True
+ else:
+ child_exclusions.append(child)
+ # If any children are included, we will count this node as included, so we
+ # have to add any excluded children to the exclusion list.
+ if any_child_included:
+ for child in child_exclusions:
+ exclusions.append(child)
+ # Now return whether this node should be counted as included, which means
+ # whether any children are included.
+ return any_child_included
+
+ # Start the DFS at each root of the tree.
+ for root in tree[None]:
+ root_included = visit(root)
+ # If any of the roots are counted as excluded, add them to the list.
+ if not root_included:
+ exclusions.append(root)
+
+ # Finally, sort and return the list of exclusions.
+ return sorted(exclusions)
+
+
+def self_test():
+ """Self-test for the build_include_exclude_list logic."""
+ test_inclusions = {
+ 'a.x': True,
+ 'a.y': True,
+ 'b.x': True,
+ 'b.y': False,
+ 'c.x': False,
+ 'c.y': False,
+ 'd.x.m': True,
+ 'd.x.n': True,
+ 'd.y.m': True,
+ 'd.y.n': False,
+ 'd.z.m': False,
+ 'd.z.n': False,
+ }
+ expected_exclusions = [
+ 'b.y',
+ 'c',
+ 'd.y.n',
+ 'd.z',
+ ]
+ actual_exclusions = build_exclusion_list(test_inclusions)
+ if actual_exclusions != expected_exclusions:
+ raise Exception('Self test failed! Expected %s but got %s' %
+ (expected_exclusions, actual_exclusions))
+
+
+def main():
+ """The main method."""
+ self_test()
+ filenames = find_all_log_files()
+ (times_by_test, overall_times) = collect_running_times(filenames)
+ fastest_time_by_test = process_running_times(times_by_test)
+ overhead_ratio = calculate_overhead_ratio(overall_times, fastest_time_by_test)
+ if ROLL_UP_TEST_CLASSES_TO_PACKAGE:
+ time_by_package = group_times_by_package(fastest_time_by_test)
+ test_inclusions = find_tests_to_run(time_by_package, overhead_ratio)
+ else:
+ test_inclusions = find_tests_to_run(fastest_time_by_test, overhead_ratio)
+ exclusions = build_exclusion_list(test_inclusions)
+ output_path = os.path.join(LIBCORE_DIR, 'TEST_MAPPING')
+ with open(output_path, 'w') as output:
+ output.write(
+ TEST_MAPPING_TEMPLATE.render(
+ module=CTS_MODULE_NAME, exclusions=exclusions))
+ print('Wrote test mapping to ' + util.printable_path(output_path))
+
+
+main()
diff --git a/tools/testmapping/save_logs.py b/tools/testmapping/save_logs.py
new file mode 100755
index 0000000..8f737b3e
--- /dev/null
+++ b/tools/testmapping/save_logs.py
@@ -0,0 +1,142 @@
+#!/usr/bin/env python2
+#
+# Copyright 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.
+
+"""Tool to save logs files for use by gen_smoke_tests.py."""
+
+from __future__ import print_function
+
+import glob
+import os
+import shutil
+import sys
+
+import util
+
+ANDROID_REPOSITORY_ROOT = util.android_repository_root()
+LOGS_ROOT = os.path.join(ANDROID_REPOSITORY_ROOT, 'out', 'host', 'linux-x86',
+ 'cts', 'android-cts', 'logs')
+CTS_LOGS_PATTERN = os.path.join(LOGS_ROOT, '*', '*',
+ 'device_logcat_test_*.txt.gz')
+LIBCORE_DIR = os.path.join(ANDROID_REPOSITORY_ROOT, 'libcore')
+DESTINATION_DIR = os.path.join(LIBCORE_DIR, 'smoketest')
+
+
+def check_destination():
+ """Ensures the destination directory to copy the files to exists."""
+ if not os.path.isdir(LIBCORE_DIR):
+ raise Exception('Could not find directory ' + LIBCORE_DIR)
+ if not os.path.isdir(DESTINATION_DIR):
+ print('Making destination directory ' +
+ util.printable_path(DESTINATION_DIR))
+ os.mkdir(DESTINATION_DIR, 0o755)
+ else:
+ print('Found destination directory ' + util.printable_path(DESTINATION_DIR))
+
+
+def is_real_log_file(filename):
+ """Returns whether the filename is one we should use or not."""
+ return 'latest' not in filename
+
+
+def find_all_log_files():
+ """Finds all CTS log files in the expected directory.
+
+ Returns:
+ A list of filenames, sorted by mtime, most recent first.
+ Raises:
+ Exception: Not enough log files found.
+ """
+ print('Looking for logs in %s' % util.printable_path(LOGS_ROOT))
+ print('+++ ' + CTS_LOGS_PATTERN)
+ for f in glob.glob(CTS_LOGS_PATTERN):
+ print('*** ' + f)
+ sources = [f for f in glob.glob(CTS_LOGS_PATTERN) if is_real_log_file(f)]
+ if not sources:
+ raise Exception('Found no logs files!')
+ return sorted(sources, key=os.path.getmtime, reverse=True)
+
+
+def relative_source_name(source):
+ """Returns the name of a source file, relative to the logs root."""
+ return os.path.relpath(source, LOGS_ROOT)
+
+
+def flatten_name(name):
+ """Returns a flattened version of a path, using _ to separate."""
+ parts = []
+ while name:
+ (head, tail) = os.path.split(name)
+ parts.insert(0, tail)
+ name = head
+ return '_'.join(parts)
+
+
+def destination_path(name):
+ """Returns the destination path for a given name (which must be flattened)."""
+ assert not os.path.dirname(name)
+ return os.path.join(DESTINATION_DIR, name)
+
+
+def get_indexes_from_user(prompt, options):
+ """Gets a sequence of indexes between 1 and max from the user.
+
+ Args:
+ prompt: A prompt to show to the user.
+ options: The options to show to the user.
+
+ Yields:
+ The indexes.
+ """
+ for (index, option) in enumerate(options):
+ print('%d: %s' % (index + 1, option))
+ while True:
+ print(prompt)
+ instr = sys.stdin.readline().strip()
+ if instr.lower() == 'q':
+ break
+ try:
+ index = int(instr)
+ except ValueError:
+ print('Not a valid index! Please try again')
+ continue
+ if index < 1 or index > len(options):
+ print('Not a valid index! Please try again')
+ continue
+ yield index - 1
+
+
+def do_copy(source):
+ """Copies the given source into the destination directory."""
+ destination = destination_path(flatten_name(relative_source_name(source)))
+ if os.path.exists(destination):
+ print('File already exists: ' + util.printable_path(destination))
+ else:
+ print('Copying %s to %s' %
+ (util.printable_path(source), util.printable_path(destination)))
+ shutil.copyfile(source, destination)
+
+
+def main():
+ check_destination()
+ sources = find_all_log_files()
+ for index in get_indexes_from_user(
+ 'Enter the number of the file to save, or Q to quit',
+ map(relative_source_name, sources)):
+ do_copy(sources[index])
+ print('Bye!')
+
+
+main()
diff --git a/tools/testmapping/util.py b/tools/testmapping/util.py
new file mode 100644
index 0000000..b1cf937
--- /dev/null
+++ b/tools/testmapping/util.py
@@ -0,0 +1,34 @@
+#
+# Copyright 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.
+
+"""Common functions shared between the scripts."""
+
+import os
+
+
+def android_repository_root():
+ """Returns the root of the tree."""
+ if 'ANDROID_BUILD_TOP' not in os.environ:
+ raise Exception('Environment variable ANDROID_BUILD_TOP not set')
+ return os.environ['ANDROID_BUILD_TOP']
+
+
+def printable_path(filename):
+ """Returns the filename relative to the current dir, if it's under it."""
+ relative_path = os.path.relpath(filename)
+ if not relative_path.startswith('../'):
+ return relative_path
+ else:
+ return filename