Merge "Add regression test for loading locale data with unknown/invalid locale"
diff --git a/expectations/Android.bp b/expectations/Android.bp
new file mode 100644
index 0000000..bf4a993
--- /dev/null
+++ b/expectations/Android.bp
@@ -0,0 +1,9 @@
+filegroup {
+ name: "libcore-expectations-knownfailures",
+ srcs: ["knownfailures.txt"],
+}
+
+filegroup {
+ name: "libcore-expectations-virtualdeviceknownfailures",
+ srcs: ["virtualdeviceknownfailures.txt"],
+}
diff --git a/luni/src/main/java/libcore/net/android.mime.types b/luni/src/main/java/libcore/net/android.mime.types
index dd3b21a..dff930a 100644
--- a/luni/src/main/java/libcore/net/android.mime.types
+++ b/luni/src/main/java/libcore/net/android.mime.types
@@ -69,6 +69,7 @@
video/m4v m4v
video/mp2p mpeg
video/mp2ts ts
+video/MP2T m2ts MTS
video/x-webex wrf
# Special cases where Android has a strong opinion about mappings, so we
diff --git a/luni/src/main/java/libcore/util/HexEncoding.java b/luni/src/main/java/libcore/util/HexEncoding.java
index f5eed4f..6d00074 100644
--- a/luni/src/main/java/libcore/util/HexEncoding.java
+++ b/luni/src/main/java/libcore/util/HexEncoding.java
@@ -120,7 +120,9 @@
*
* Throws an {@code IllegalArgumentException} if the input is malformed.
*/
- public static byte[] decode(String encoded, boolean allowSingleChar) throws IllegalArgumentException {
+ @libcore.api.CorePlatformApi
+ public static byte[] decode(String encoded, boolean allowSingleChar)
+ throws IllegalArgumentException {
return decode(encoded.toCharArray(), allowSingleChar);
}
@@ -143,25 +145,28 @@
* Throws an {@code IllegalArgumentException} if the input is malformed.
*/
@libcore.api.CorePlatformApi
- public static byte[] decode(char[] encoded, boolean allowSingleChar) throws IllegalArgumentException {
- int resultLengthBytes = (encoded.length + 1) / 2;
+ public static byte[] decode(char[] encoded, boolean allowSingleChar)
+ throws IllegalArgumentException {
+ int encodedLength = encoded.length;
+ int resultLengthBytes = (encodedLength + 1) / 2;
byte[] result = new byte[resultLengthBytes];
int resultOffset = 0;
int i = 0;
if (allowSingleChar) {
- if ((encoded.length % 2) != 0) {
- // Odd number of digits -- the first digit is the lower 4 bits of the first result byte.
+ if ((encodedLength % 2) != 0) {
+ // Odd number of digits -- the first digit is the lower 4 bits of the first result
+ // byte.
result[resultOffset++] = (byte) toDigit(encoded, i);
i++;
}
} else {
- if ((encoded.length % 2) != 0) {
- throw new IllegalArgumentException("Invalid input length: " + encoded.length);
+ if ((encodedLength % 2) != 0) {
+ throw new IllegalArgumentException("Invalid input length: " + encodedLength);
}
}
- for (int len = encoded.length; i < len; i += 2) {
+ for (; i < encodedLength; i += 2) {
result[resultOffset++] = (byte) ((toDigit(encoded, i) << 4) | toDigit(encoded, i + 1));
}
@@ -181,7 +186,6 @@
return 10 + (pseudoCodePoint - 'A');
}
- throw new IllegalArgumentException("Illegal char: " + str[offset] +
- " at offset " + offset);
+ throw new IllegalArgumentException("Illegal char: " + str[offset] + " at offset " + offset);
}
}
diff --git a/luni/src/test/java/libcore/java/io/ObjectStreamClassTest.java b/luni/src/test/java/libcore/java/io/ObjectStreamClassTest.java
index 612b7d8..8bee284 100644
--- a/luni/src/test/java/libcore/java/io/ObjectStreamClassTest.java
+++ b/luni/src/test/java/libcore/java/io/ObjectStreamClassTest.java
@@ -16,6 +16,7 @@
package libcore.java.io;
import java.io.ObjectStreamClass;
+import java.io.ObjectStreamClass.DefaultSUIDCompatibilityListener;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -31,6 +32,7 @@
import org.junit.runners.MethodSorters;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
@RunWith(JUnitParamsRunner.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@@ -99,8 +101,6 @@
// The default SUID for the InheritStaticInitializer should be affected by the b/29064453
// patch and so should differ between version <= 23 and version > 23.
{ InheritStaticInitializer.class, 4188245044387716731L, 992629205079295334L },
-
-
};
}
@@ -108,27 +108,46 @@
@Test
public void computeDefaultSUID_current(Class<?> clazz, long suid,
@SuppressWarnings("unused") long suid23) {
- checkSerialVersionUID(suid, clazz);
+ checkSerialVersionUID(suid, clazz, false);
}
@Parameters(method = "defaultSUIDs")
@Test
@TargetSdkVersion(23)
- public void computeDefaultSUID_targetSdkVersion_23(Class<?> clazz,
- @SuppressWarnings("unused") long suid, long suid23) {
- checkSerialVersionUID(suid23, clazz);
+ public void computeDefaultSUID_targetSdkVersion_23(Class<?> clazz, long suid, long suid23) {
+ // If the suid and suid23 hashes are different then a warning is expected to be logged.
+ boolean expectedWarning = suid23 != suid;
+ checkSerialVersionUID(suid23, clazz, expectedWarning);
}
- private static void checkSerialVersionUID(long expectedSUID, Class<?> clazz) {
- // Use reflection to access the private static computeDefaultSUID method.
+ private static void checkSerialVersionUID(
+ long expectedSUID, Class<?> clazz, boolean expectedWarning) {
+ // Use reflection to call the private static computeDefaultSUID method directly to avoid the
+ // caching performed by ObjectStreamClass.lookup(Class).
long defaultSUID;
+ DefaultSUIDCompatibilityListener savedListener
+ = ObjectStreamClass.suidCompatibilityListener;
try {
+ ObjectStreamClass.suidCompatibilityListener = (c, hash) -> {
+ // Delegate to the existing listener so that the warning is logged.
+ savedListener.warnDefaultSUIDTargetVersionDependent(clazz, hash);
+ if (expectedWarning) {
+ assertEquals(clazz, c);
+ assertEquals(expectedSUID, hash);
+ } else {
+ fail("Unexpected warning for " + c + " with defaultSUID " + hash);
+ }
+ };
+
Method computeDefaultSUIDMethod =
ObjectStreamClass.class.getDeclaredMethod("computeDefaultSUID", Class.class);
computeDefaultSUIDMethod.setAccessible(true);
+
defaultSUID = (Long) computeDefaultSUIDMethod.invoke(null, clazz);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new IllegalStateException(e);
+ } finally {
+ ObjectStreamClass.suidCompatibilityListener = savedListener;
}
assertEquals(expectedSUID, defaultSUID);
}
diff --git a/luni/src/test/java/libcore/java/net/InetAddressTest.java b/luni/src/test/java/libcore/java/net/InetAddressTest.java
index 2ce79fd..88f03d4 100644
--- a/luni/src/test/java/libcore/java/net/InetAddressTest.java
+++ b/luni/src/test/java/libcore/java/net/InetAddressTest.java
@@ -313,11 +313,12 @@
public void test_getByName_invalid(String invalid) throws Exception {
try {
InetAddress.getByName(invalid);
- String failMessage = "Invalid IP address incorrectly recognized as valid: " + invalid;
+ String msg = "Invalid IP address incorrectly recognized as valid: \"" + invalid + "\"";
if (InetAddressUtils.parseNumericAddressNoThrowStripOptionalBrackets(invalid) == null) {
- failMessage += " (it was probably unexpectedly resolved by this network's DNS)";
+ msg += " (it was probably unexpectedly resolved by this network's DNS)";
}
- fail(failMessage);
+ msg += ".";
+ fail(msg);
} catch (UnknownHostException expected) {
}
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index 8505d4c..c29ba09 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -345,7 +345,7 @@
server.enqueue(new MockResponse().setResponseCode(404).setBody("A"));
server.play();
HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection.getErrorStream(), Integer.MAX_VALUE));
+ assertEquals("A", readAscii(connection.getErrorStream()));
}
// Check that if we don't read to the end of a response, the next request on the
@@ -411,10 +411,10 @@
server.play();
URLConnection connection1 = server.getUrl("/").openConnection();
- assertEquals("ABC", readAscii(connection1.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("ABC", readAscii(connection1.getInputStream()));
assertEquals(0, server.takeRequest().getSequenceNumber());
URLConnection connection2 = server.getUrl("/").openConnection();
- assertEquals("DEF", readAscii(connection2.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("DEF", readAscii(connection2.getInputStream()));
assertEquals(1, server.takeRequest().getSequenceNumber());
}
@@ -596,7 +596,7 @@
connection = (HttpsURLConnection) server.getUrl("/").openConnection();
try {
- readAscii(connection.getInputStream(), Integer.MAX_VALUE);
+ readAscii(connection.getInputStream());
fail("without an SSL socket factory, the connection should fail");
} catch (SSLException expected) {
}
@@ -1211,7 +1211,7 @@
inputStream = new AuditInputStream(connection.getInputStream(), auditStream);
connection.getHeaderFields();
headerRead = true;
- readAscii(inputStream, Integer.MAX_VALUE);
+ readAscii(inputStream);
fail("Didn't expect to successfully read all of the data");
} catch (IOException expected) {
} finally {
@@ -1325,7 +1325,7 @@
* exhausted before {@code count} characters can be read, the remaining
* characters are returned and the stream is closed.
*/
- private String readAscii(InputStream in, int count) throws IOException {
+ private static String readAscii(InputStream in, int count) throws IOException {
StringBuilder result = new StringBuilder();
for (int i = 0; i < count; i++) {
int value = in.read();
@@ -1338,6 +1338,10 @@
return result.toString();
}
+ private static String readAscii(InputStream in) throws IOException {
+ return readAscii(in, Integer.MAX_VALUE);
+ }
+
public void testMarkAndResetWithContentLengthHeader() throws IOException {
testMarkAndReset(TransferKind.FIXED_LENGTH);
}
@@ -1366,7 +1370,7 @@
fail();
} catch (IOException expected) {
}
- assertEquals("FGHIJKLMNOPQRSTUVWXYZ", readAscii(in, Integer.MAX_VALUE));
+ assertEquals("FGHIJKLMNOPQRSTUVWXYZ", readAscii(in));
assertContent("ABCDEFGHIJKLMNOPQRSTUVWXYZ", server.getUrl("/").openConnection());
}
@@ -1403,7 +1407,7 @@
URLConnection connection = server.getUrl("/").openConnection();
try {
- readAscii(connection.getInputStream(), Integer.MAX_VALUE);
+ readAscii(connection.getInputStream());
fail();
} catch (IOException e) {
}
@@ -1419,7 +1423,7 @@
URLConnection connection = server.getUrl("/").openConnection();
try {
- readAscii(connection.getInputStream(), Integer.MAX_VALUE);
+ readAscii(connection.getInputStream());
fail();
} catch (IOException e) {
}
@@ -1437,7 +1441,7 @@
server.play();
URLConnection connection = server.getUrl("/").openConnection();
- assertEquals("ABCABCABC", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("ABCABCABC", readAscii(connection.getInputStream()));
assertNull(connection.getContentEncoding());
assertEquals(-1, connection.getContentLength());
@@ -1456,7 +1460,7 @@
URLConnection connection = server.getUrl("/").openConnection();
connection.addRequestProperty("Accept-Encoding", "gzip");
InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream());
- assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", readAscii(gunzippedIn, Integer.MAX_VALUE));
+ assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", readAscii(gunzippedIn));
assertEquals(bodyBytes.length, connection.getContentLength());
RecordedRequest request = server.takeRequest();
@@ -1480,7 +1484,7 @@
URLConnection connection = server.getUrl("/").openConnection();
connection.addRequestProperty("Accept-Encoding", "custom");
- assertEquals("ABCDE", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("ABCDE", readAscii(connection.getInputStream()));
RecordedRequest request = server.takeRequest();
assertContains(request.getHeaders(), "Accept-Encoding: custom");
@@ -1505,11 +1509,11 @@
URLConnection connection = server.getUrl("/").openConnection();
connection.addRequestProperty("Accept-Encoding", "gzip");
InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream());
- assertEquals("one (gzipped)", readAscii(gunzippedIn, Integer.MAX_VALUE));
+ assertEquals("one (gzipped)", readAscii(gunzippedIn));
assertEquals(0, server.takeRequest().getSequenceNumber());
connection = server.getUrl("/").openConnection();
- assertEquals("two (identity)", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("two (identity)", readAscii(connection.getInputStream()));
assertEquals(1, server.takeRequest().getSequenceNumber());
}
@@ -1530,7 +1534,7 @@
assertContent("", connection1);
HttpURLConnection connection2 = (HttpURLConnection) server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection2.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("A", readAscii(connection2.getInputStream()));
assertEquals(0, server.takeRequest().getSequenceNumber());
assertEquals(1, server.takeRequest().getSequenceNumber());
@@ -1666,7 +1670,7 @@
server.enqueue(new MockResponse().setBody("A"));
server.play();
HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("A", readAscii(connection.getInputStream()));
try {
connection.setFixedLengthStreamingMode(1);
fail();
@@ -1678,7 +1682,7 @@
server.enqueue(new MockResponse().setBody("A"));
server.play();
HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("A", readAscii(connection.getInputStream()));
try {
connection.setChunkedStreamingMode(1);
fail();
@@ -1738,7 +1742,7 @@
OutputStream outputStream = connection.getOutputStream();
outputStream.write(requestBody);
outputStream.close();
- assertEquals("Success!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("Success!", readAscii(connection.getInputStream()));
RecordedRequest request = server.takeRequest();
assertEquals("POST / HTTP/1.1", request.getRequestLine());
@@ -1774,7 +1778,7 @@
OutputStream outputStream = connection.getOutputStream();
outputStream.write(requestBody);
outputStream.close();
- assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("Successful auth!", readAscii(connection.getInputStream()));
// no authorization header for the first request...
RecordedRequest request = server.takeRequest();
@@ -1806,7 +1810,7 @@
SimpleAuthenticator authenticator = new SimpleAuthenticator();
Authenticator.setDefault(authenticator);
HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("Successful auth!", readAscii(connection.getInputStream()));
assertEquals(Authenticator.RequestorType.SERVER, authenticator.requestorType);
assertEquals(server.getPort(), authenticator.requestingPort);
assertEquals(InetAddress.getByName(server.getHostName()), authenticator.requestingSite);
@@ -1844,7 +1848,7 @@
SimpleAuthenticator authenticator = new SimpleAuthenticator();
Authenticator.setDefault(authenticator);
HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("Successful auth!", readAscii(connection.getInputStream()));
assertEquals(Authenticator.RequestorType.SERVER, authenticator.requestorType);
assertEquals(server.getPort(), authenticator.requestingPort);
assertEquals(InetAddress.getByName(server.getHostName()), authenticator.requestingSite);
@@ -1867,7 +1871,7 @@
authenticator.expectedPrompt = "b";
Authenticator.setDefault(authenticator);
HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("Successful auth!", readAscii(connection.getInputStream()));
assertContainsNoneMatching(server.takeRequest().getHeaders(), "Authorization: .*");
assertContains(server.takeRequest().getHeaders(),
@@ -1889,7 +1893,7 @@
authenticator.expectedPrompt = "b";
Authenticator.setDefault(authenticator);
HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("Successful auth!", readAscii(connection.getInputStream()));
assertContainsNoneMatching(server.takeRequest().getHeaders(), "Authorization: .*");
assertContains(server.takeRequest().getHeaders(),
@@ -1919,8 +1923,7 @@
server.play();
URLConnection connection = server.getUrl("/").openConnection();
- assertEquals("This is the new location!",
- readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("This is the new location!", readAscii(connection.getInputStream()));
RecordedRequest first = server.takeRequest();
assertEquals("GET / HTTP/1.1", first.getRequestLine());
@@ -1943,8 +1946,7 @@
HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
- assertEquals("This is the new location!",
- readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("This is the new location!", readAscii(connection.getInputStream()));
RecordedRequest first = server.takeRequest();
assertEquals("GET / HTTP/1.1", first.getRequestLine());
@@ -1964,8 +1966,7 @@
HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
- assertEquals("This page has moved!",
- readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("This page has moved!", readAscii(connection.getInputStream()));
}
public void testNotRedirectedFromHttpToHttps() throws IOException, InterruptedException {
@@ -1976,8 +1977,7 @@
server.play();
HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- assertEquals("This page has moved!",
- readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("This page has moved!", readAscii(connection.getInputStream()));
}
public void testRedirectToAnotherOriginServer() throws Exception {
@@ -1993,13 +1993,11 @@
server.play();
URLConnection connection = server.getUrl("/").openConnection();
- assertEquals("This is the 2nd server!",
- readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("This is the 2nd server!", readAscii(connection.getInputStream()));
assertEquals(server2.getUrl("/"), connection.getURL());
// make sure the first server was careful to recycle the connection
- assertEquals("This is the first server again!",
- readAscii(server.getUrl("/").openStream(), Integer.MAX_VALUE));
+ assertEquals("This is the first server again!", readAscii(server.getUrl("/").openStream()));
RecordedRequest first = server.takeRequest();
assertContains(first.getHeaders(), "Host: " + hostName + ":" + server.getPort());
@@ -2065,7 +2063,7 @@
try {
HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- assertEquals("Target", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("Target", readAscii(connection.getInputStream()));
// Inspect the redirect request to see what request was actually made.
RecordedRequest actualRequest = server2.takeRequest();
@@ -2153,7 +2151,7 @@
OutputStream outputStream = connection.getOutputStream();
outputStream.write(requestBody);
outputStream.close();
- assertEquals("Page 2", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("Page 2", readAscii(connection.getInputStream()));
assertTrue(connection.getDoOutput());
RecordedRequest page1 = server.takeRequest();
@@ -2174,8 +2172,7 @@
HttpURLConnection connection = (HttpURLConnection) server.getUrl("/foo").openConnection();
// Fails on the RI, which gets "Proxy Response"
- assertEquals("This page has moved!",
- readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("This page has moved!", readAscii(connection.getInputStream()));
RecordedRequest page1 = server.takeRequest();
assertEquals("GET /foo HTTP/1.1", page1.getRequestLine());
@@ -2201,9 +2198,9 @@
server.play();
URL url = server.getUrl("/");
- assertEquals("ABC", readAscii(url.openStream(), Integer.MAX_VALUE));
- assertEquals("DEF", readAscii(url.openStream(), Integer.MAX_VALUE));
- assertEquals("GHI", readAscii(url.openStream(), Integer.MAX_VALUE));
+ assertEquals("ABC", readAscii(url.openStream()));
+ assertEquals("DEF", readAscii(url.openStream()));
+ assertEquals("GHI", readAscii(url.openStream()));
assertEquals(Arrays.asList("verify " + hostName), hostnameVerifier.calls);
assertEquals(Arrays.asList("checkServerTrusted ["
@@ -2372,8 +2369,7 @@
server.play();
URLConnection connection = server.getUrl("/").openConnection();
- assertEquals("This is the new location!",
- readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("This is the new location!", readAscii(connection.getInputStream()));
assertEquals(0, server.takeRequest().getSequenceNumber());
assertEquals("When connection: close is used, each request should get its own connection",
@@ -2387,8 +2383,7 @@
server.play();
URLConnection connection = server.getUrl("/").openConnection();
- assertEquals("This body is not allowed!",
- readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("This body is not allowed!", readAscii(connection.getInputStream()));
}
public void testSingleByteReadIsSigned() throws IOException {
@@ -2435,7 +2430,7 @@
OutputStream out = connection.getOutputStream();
out.write(upload);
- assertEquals("abc", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("abc", readAscii(connection.getInputStream()));
out.flush(); // dubious but permitted
try {
@@ -2472,7 +2467,7 @@
// Read timeout of a day, sure to cause the test to timeout and fail.
connection.setReadTimeout(24 * 3600 * 1000);
InputStream input = connection.getInputStream();
- assertEquals("ABC", readAscii(input, Integer.MAX_VALUE));
+ assertEquals("ABC", readAscii(input));
input.close();
try {
connection = server.getUrl("").openConnection();
@@ -2779,7 +2774,7 @@
server.play();
HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
InputStream in = (InputStream) connection.getContent();
- assertEquals("A", readAscii(in, Integer.MAX_VALUE));
+ assertEquals("A", readAscii(in));
}
public void testGetContentOfType() throws Exception {
@@ -2863,7 +2858,7 @@
OutputStream out = connection.getOutputStream();
out.write(new byte[] { 'A', 'B', 'C' });
out.close();
- assertEquals("A", readAscii(connection.getInputStream(), Integer.MAX_VALUE));
+ assertEquals("A", readAscii(connection.getInputStream()));
RecordedRequest request = server.takeRequest();
assertContains(request.getHeaders(), "Content-Length: 3");
}
@@ -2901,7 +2896,7 @@
server.enqueue(new MockResponse().setBody("A"));
server.play();
URL url = new URL("http", server.getHostName(), server.getPort(), "?query");
- assertEquals("A", readAscii(url.openConnection().getInputStream(), Integer.MAX_VALUE));
+ assertEquals("A", readAscii(url.openConnection().getInputStream()));
RecordedRequest request = server.takeRequest();
assertEquals("GET /?query HTTP/1.1", request.getRequestLine());
}
diff --git a/mmodules/core_platform_api/api/platform/current-api.txt b/mmodules/core_platform_api/api/platform/current-api.txt
index ec28ddf..da717bd 100644
--- a/mmodules/core_platform_api/api/platform/current-api.txt
+++ b/mmodules/core_platform_api/api/platform/current-api.txt
@@ -800,10 +800,6 @@
package java.lang {
- public final class Byte extends java.lang.Number implements java.lang.Comparable<java.lang.Byte> {
- method public static String toHexString(byte, boolean);
- }
-
public final class Class<T> implements java.lang.reflect.AnnotatedElement java.lang.reflect.GenericDeclaration java.io.Serializable java.lang.reflect.Type {
method @dalvik.annotation.optimization.FastNative public java.lang.reflect.Field[] getDeclaredFieldsUnchecked(boolean);
method @dalvik.annotation.optimization.FastNative public java.lang.reflect.Method[] getDeclaredMethodsUnchecked(boolean);
@@ -1223,6 +1219,7 @@
public class HexEncoding {
method public static byte[] decode(String) throws java.lang.IllegalArgumentException;
+ method public static byte[] decode(String, boolean) throws java.lang.IllegalArgumentException;
method public static byte[] decode(char[]) throws java.lang.IllegalArgumentException;
method public static byte[] decode(char[], boolean) throws java.lang.IllegalArgumentException;
method public static char[] encode(byte[]);
@@ -1365,6 +1362,18 @@
method public static sun.misc.Cleaner create(Object, Runnable);
}
+ public final class Unsafe {
+ method public int arrayBaseOffset(Class);
+ method @dalvik.annotation.optimization.FastNative public byte getByte(Object, long);
+ method @dalvik.annotation.optimization.FastNative public byte getByte(long);
+ method @dalvik.annotation.optimization.FastNative public long getLong(Object, long);
+ method @dalvik.annotation.optimization.FastNative public long getLong(long);
+ method public static sun.misc.Unsafe getUnsafe();
+ method public long objectFieldOffset(java.lang.reflect.Field);
+ method @dalvik.annotation.optimization.FastNative public void putByte(Object, long, byte);
+ method @dalvik.annotation.optimization.FastNative public void putByte(long, byte);
+ }
+
}
package sun.security.jca {
diff --git a/ojluni/annotations/mmodule/java/lang/Byte.annotated.java b/ojluni/annotations/mmodule/java/lang/Byte.annotated.java
deleted file mode 100644
index 2d61598..0000000
--- a/ojluni/annotations/mmodule/java/lang/Byte.annotated.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package java.lang;
-
-
-@SuppressWarnings({"unchecked", "deprecation", "all"})
-public final class Byte extends java.lang.Number implements java.lang.Comparable<java.lang.Byte> {
-
-public Byte(byte value) { throw new RuntimeException("Stub!"); }
-
-public Byte(java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
-
-public static java.lang.String toString(byte b) { throw new RuntimeException("Stub!"); }
-
-public static java.lang.Byte valueOf(byte b) { throw new RuntimeException("Stub!"); }
-
-public static byte parseByte(java.lang.String s, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
-
-public static byte parseByte(java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
-
-public static java.lang.Byte valueOf(java.lang.String s, int radix) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
-
-public static java.lang.Byte valueOf(java.lang.String s) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
-
-public static java.lang.Byte decode(java.lang.String nm) throws java.lang.NumberFormatException { throw new RuntimeException("Stub!"); }
-
-public byte byteValue() { throw new RuntimeException("Stub!"); }
-
-public short shortValue() { throw new RuntimeException("Stub!"); }
-
-public int intValue() { throw new RuntimeException("Stub!"); }
-
-public long longValue() { throw new RuntimeException("Stub!"); }
-
-public float floatValue() { throw new RuntimeException("Stub!"); }
-
-public double doubleValue() { throw new RuntimeException("Stub!"); }
-
-public java.lang.String toString() { throw new RuntimeException("Stub!"); }
-
-public int hashCode() { throw new RuntimeException("Stub!"); }
-
-public static int hashCode(byte value) { throw new RuntimeException("Stub!"); }
-
-public boolean equals(java.lang.Object obj) { throw new RuntimeException("Stub!"); }
-
-public int compareTo(java.lang.Byte anotherByte) { throw new RuntimeException("Stub!"); }
-
-public static int compare(byte x, byte y) { throw new RuntimeException("Stub!"); }
-
-public static int toUnsignedInt(byte x) { throw new RuntimeException("Stub!"); }
-
-public static long toUnsignedLong(byte x) { throw new RuntimeException("Stub!"); }
-
-@libcore.api.CorePlatformApi
-public static java.lang.String toHexString(byte b, boolean upperCase) { throw new RuntimeException("Stub!"); }
-
-public static final int BYTES = 1; // 0x1
-
-public static final byte MAX_VALUE = 127; // 0x7f
-
-public static final byte MIN_VALUE = -128; // 0xffffff80
-
-public static final int SIZE = 8; // 0x8
-
-public static final java.lang.Class<java.lang.Byte> TYPE;
-static { TYPE = null; }
-}
-
diff --git a/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java b/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java
new file mode 100644
index 0000000..f272a9a
--- /dev/null
+++ b/ojluni/annotations/mmodule/sun/misc/Unsafe.annotated.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.misc;
+
+@libcore.api.CorePlatformApi
+@libcore.api.Hide
+@SuppressWarnings({"unchecked", "deprecation", "all"})
+public final class Unsafe {
+
+ private Unsafe() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @libcore.api.CorePlatformApi
+ public static sun.misc.Unsafe getUnsafe() {
+ throw new RuntimeException("Stub!");
+ }
+
+ @libcore.api.CorePlatformApi
+ public long objectFieldOffset(java.lang.reflect.Field field) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @libcore.api.CorePlatformApi
+ public int arrayBaseOffset(java.lang.Class clazz) {
+ throw new RuntimeException("Stub!");
+ }
+
+ @libcore.api.CorePlatformApi
+ public native byte getByte(java.lang.Object obj, long offset);
+
+ @libcore.api.CorePlatformApi
+ public native byte getByte(long address);
+
+ @libcore.api.CorePlatformApi
+ public native long getLong(java.lang.Object obj, long offset);
+
+ @libcore.api.CorePlatformApi
+ public native long getLong(long address);
+
+ @libcore.api.CorePlatformApi
+ public native void putByte(java.lang.Object obj, long offset, byte newValue);
+
+ @libcore.api.CorePlatformApi
+ public native void putByte(long address, byte x);
+}
diff --git a/ojluni/src/main/java/java/io/ObjectStreamClass.java b/ojluni/src/main/java/java/io/ObjectStreamClass.java
index 7561aa8..10babed 100644
--- a/ojluni/src/main/java/java/io/ObjectStreamClass.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamClass.java
@@ -1797,15 +1797,27 @@
}
}
- // Android-changed: 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
// or below in order to maintain backwards compatibility.
+ //
+ // if (hasStaticInitializer(cl)) {
boolean inheritStaticInitializer =
(VMRuntime.getRuntime().getTargetSdkVersion()
<= MAX_SDK_TARGET_FOR_CLINIT_UIDGEN_WORKAROUND);
+ boolean warnIncompatibleSUIDChange = false;
if (hasStaticInitializer(cl, inheritStaticInitializer)) {
+ // If a static initializer was found but the current class does not have one then
+ // the class's default SUID will change if the app targets SDK > 24 so send a
+ // warning.
+ if (inheritStaticInitializer && !hasStaticInitializer(cl, false)) {
+ // Defer until hash has been calculated so the warning message can give precise
+ // instructions to the developer on how to fix the problems.
+ warnIncompatibleSUIDChange = true;
+ }
+ // END Android-changed: Fix/log clinit serialization workaround b/29064453
dout.writeUTF("<clinit>");
dout.writeInt(Modifier.STATIC);
dout.writeUTF("()V");
@@ -1870,6 +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
+ // 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
return hash;
} catch (IOException ex) {
throw new InternalError(ex);
@@ -1878,8 +1898,38 @@
}
}
- // BEGIN Android-changed: Clinit serialization workaround b/29064453
- /** Max SDK target version for which we use buggy hasStaticIntializier implementation. */
+ // 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.
+ *
+ * @hide
+ */
+ public interface DefaultSUIDCompatibilityListener {
+ /**
+ * Called when a class being serialized/deserialized relies on the default SUID computation
+ * (because it has no explicit {@code serialVersionUID} field) where that computation is
+ * dependent on the app's targetSdkVersion.
+ *
+ * @param clazz the clazz for which the default SUID is being computed.
+ * @param hash the computed value.
+ */
+ void warnDefaultSUIDTargetVersionDependent(Class<?> clazz, long hash);
+ }
+
+ /**
+ * Public and mutable for testing purposes.
+ *
+ * @hide
+ */
+ public static DefaultSUIDCompatibilityListener suidCompatibilityListener =
+ (clazz, hash) -> {
+ System.logW("Class " + clazz.getCanonicalName() + " relies on its default SUID which"
+ + " is dependent on the app's targetSdkVersion. To avoid problems during upgrade"
+ + " add the following to class " + clazz.getCanonicalName() + "\n"
+ + " private static final long serialVersionUID = " + hash + "L;");
+ };
+
+ /** Max SDK target version for which we use buggy hasStaticInitializer implementation. */
static final int MAX_SDK_TARGET_FOR_CLINIT_UIDGEN_WORKAROUND = 23;
/**
@@ -1893,7 +1943,7 @@
*/
private native static boolean hasStaticInitializer(
Class<?> cl, boolean inheritStaticInitializer);
- // END Android-changed: 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/Byte.java b/ojluni/src/main/java/java/lang/Byte.java
index e53899c..deb4ecb 100644
--- a/ojluni/src/main/java/java/lang/Byte.java
+++ b/ojluni/src/main/java/java/lang/Byte.java
@@ -25,6 +25,8 @@
package java.lang;
+import libcore.util.HexEncoding;
+
/**
*
* The {@code Byte} class wraps a value of primitive type {@code byte}
@@ -523,24 +525,8 @@
* @hide
*/
public static String toHexString(byte b, boolean upperCase) {
- char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
- char[] buf = new char[2]; // We always want two digits.
- buf[0] = digits[(b >> 4) & 0xf];
- buf[1] = digits[b & 0xf];
- return new String(0, 2, buf);
+ // This method currently retained because it is marked @UnsupportedAppUsage.
+ return HexEncoding.encodeToString(b, upperCase);
}
- private static final char[] DIGITS = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
- 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
- 'u', 'v', 'w', 'x', 'y', 'z'
- };
-
- private static final char[] UPPER_CASE_DIGITS = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
- 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
- 'U', 'V', 'W', 'X', 'Y', 'Z'
- };
// END Android-added: toHexString() for internal use.
}
diff --git a/openjdk_java_files.bp b/openjdk_java_files.bp
index 5c27228..c1f29ea 100644
--- a/openjdk_java_files.bp
+++ b/openjdk_java_files.bp
@@ -1387,6 +1387,7 @@
srcs: [
"ojluni/src/main/java/java/nio/DirectByteBuffer.java",
"ojluni/src/main/java/sun/misc/Cleaner.java",
+ "ojluni/src/main/java/sun/misc/Unsafe.java",
"ojluni/src/main/java/sun/nio/ch/DirectBuffer.java",
"ojluni/src/main/java/sun/security/jca/Providers.java",
"ojluni/src/main/java/sun/security/pkcs/ContentInfo.java",
@@ -1451,7 +1452,6 @@
"ojluni/src/main/java/sun/misc/Resource.java",
"ojluni/src/main/java/sun/misc/SharedSecrets.java",
"ojluni/src/main/java/sun/misc/URLClassPath.java",
- "ojluni/src/main/java/sun/misc/Unsafe.java",
"ojluni/src/main/java/sun/misc/Version.java",
"ojluni/src/main/java/sun/misc/VM.java",
"ojluni/src/main/java/sun/net/ApplicationProxy.java",