Merge changes I449d903b,I31bb2339
* changes:
Add a test for jarjar with Java 9 language features.
Move Java9LanguageFeaturesTest into its own directory.
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index c8dbef5..b229c2f 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -682,7 +682,7 @@
srcs: [":core_api_files"],
java_version: "1.9",
installable: false,
- sdk_version: "core_platform",
+ sdk_version: "none",
args: " --exclude-annotations " +
"--hide-annotation libcore.api.Hide",
merge_inclusion_annotations_dirs: ["ojluni-annotated-mmodule-stubs"],
@@ -741,7 +741,7 @@
name: "core-current-stubs-nullability-validation",
srcs: [":core_api_files"],
installable: false,
- sdk_version: "core_platform",
+ sdk_version: "none",
annotations_enabled: true,
args: "--hide-annotation libcore.api.Hide " +
"--validate-nullability-from-merged-stubs ",
diff --git a/NativeCode.bp b/NativeCode.bp
index 38f57b3..e40b9bc 100644
--- a/NativeCode.bp
+++ b/NativeCode.bp
@@ -66,6 +66,7 @@
"libz",
],
static_libs: [
+ "libandroidicuinit",
"libziparchive",
],
target: {
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index 64f1f70..9b19222 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -1312,12 +1312,6 @@
]
},
{
- description: "Known failure in MathTest 1^NAN should be NAN",
- bug: 11669804,
- result: EXEC_FAILED,
- name: "org.apache.harmony.tests.java.lang.MathTest#test_powDD"
-},
-{
description: "Known failures in URLTest and URLDecoderTest",
bug: 11686814,
names: [
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/MathTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/MathTest.java
index ed0a094..e3dc9fc 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/MathTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/lang/MathTest.java
@@ -1165,9 +1165,16 @@
assertEquals("Result should be Math.pow(" + negateDval + "," + 1.0
+ ")=" + negateDval, negateDval, Math.pow(negateDval, 1.0));
+ // The libm implementation of pow() has the following set of special case behaviors:
+ // If the first argument is 1.0, then the result is 1.0.
+ // i.e. the answer for the following case is not Double.NaN. http://b/11669804
+ {
+ double answer = dval == 1.0d ? 1.0d : Double.NaN;
+ assertEquals("Result should be Math.pow(" + dval + "," + Double.NaN
+ + ")=" + answer, answer, Math.pow(dval, Double.NaN));
+ }
+
// If the second argument is NaN, then the result is NaN.
- assertEquals("Result should be Math.pow(" + dval + "," + Double.NaN
- + ")=" + Double.NaN, Double.NaN, Math.pow(dval, Double.NaN));
assertEquals("Result should be Math.pow(" + negateDval + ","
+ Double.NaN + ")=" + Double.NaN, Double.NaN, Math.pow(negateDval,
Double.NaN));
@@ -1301,21 +1308,23 @@
}
}
- // If the absolute value of the first argument equals 1 and the
- // second argument is infinite, then the result is NaN.
if (dval == 1) {
+ // The libm implementation of pow() has the following set of special case behaviors:
+ // 1.0 or -1.0 to the power of positive or negative infinity is 1.0.
+ // i.e. the answer for the following cases is not Double.NaN. http://b/11669804
+
assertEquals("Result should be Math.pow(" + dval + ","
- + Double.POSITIVE_INFINITY + ")=" + Double.NaN, Double.NaN, Math
+ + Double.POSITIVE_INFINITY + ")=" + 1.0d, 1.0d, Math
.pow(dval, Double.POSITIVE_INFINITY));
assertEquals("Result should be Math.pow(" + dval + ","
- + Double.NEGATIVE_INFINITY + ")=" + Double.NaN, Double.NaN, Math
+ + Double.NEGATIVE_INFINITY + ")=" + 1.0d, 1.0d, Math
.pow(dval, Double.NEGATIVE_INFINITY));
assertEquals("Result should be Math.pow(" + negateDval + ","
- + Double.POSITIVE_INFINITY + ")=" + Double.NaN, Double.NaN, Math
+ + Double.POSITIVE_INFINITY + ")=" + 1.0d, 1.0d, Math
.pow(negateDval, Double.POSITIVE_INFINITY));
assertEquals("Result should be Math.pow(" + negateDval + ","
- + Double.NEGATIVE_INFINITY + ")=" + Double.NaN, Double.NaN, Math
+ + Double.NEGATIVE_INFINITY + ")=" + 1.0d, 1.0d, Math
.pow(negateDval, Double.NEGATIVE_INFINITY));
}
diff --git a/libart/src/main/java/dalvik/system/ClassExt.java b/libart/src/main/java/dalvik/system/ClassExt.java
index 9180d96..2c7dc6b 100644
--- a/libart/src/main/java/dalvik/system/ClassExt.java
+++ b/libart/src/main/java/dalvik/system/ClassExt.java
@@ -27,6 +27,19 @@
*/
public final class ClassExt {
/**
+ * A Pointer-sized-array of instance jfieldIDs in the same order as the ifields_ array.
+ * The jfieldID is associated with the ArtField at the corresonding index in the ifields_ array.
+ */
+ private Object instanceJfieldIDs;
+
+ /**
+ * A Pointer-sized-array of jmethodIDS in the same order as the methods_
+ * array. The jmethodID is associated with the ArtField at the corresonding
+ * index in the methods_ array.
+ */
+ private Object jmethodIDs;
+
+ /**
* An array of all obsolete DexCache objects that are needed for obsolete methods.
*
* These entries are associated with the obsolete ArtMethod pointers at the same indexes in the
@@ -63,6 +76,12 @@
private Object originalDexFile;
/**
+ * A Pointer-sized-array of static jfieldIDs in the same order as the sfields_ array.
+ * The jfieldID is associated with the ArtField at the corresonding index in the sfields_ array.
+ */
+ private Object staticJfieldIDs;
+
+ /**
* If class verify fails, we must return same error on subsequent tries. We may store either
* the class of the error, or an actual instance of Throwable here.
*
@@ -71,6 +90,16 @@
private Object verifyError;
/**
+ * ClassDef index of the related class in the pre-redefine dex file. Set together with
+ * {@code preRedefineDexFilePtr}.
+ *
+ * Needed in order to preserve access to dex-level hiddenapi flags after JVMTI redefine.
+ *
+ * This field is a logical part of the 'Class' type.
+ */
+ private int preRedefineClassDefIndex;
+
+ /**
* If set, native pointer to the initial, pre-redefine, dex file associated with the related
* class. This is different from the {@code originalDexFile} which is the pre-retransform dex
* file, i.e. could contain the bytes of the dex file provided during redefine.
@@ -86,16 +115,6 @@
private long preRedefineDexFilePtr;
/**
- * ClassDef index of the related class in the pre-redefine dex file. Set together with
- * {@code preRedefineDexFilePtr}.
- *
- * Needed in order to preserve access to dex-level hiddenapi flags after JVMTI redefine.
- *
- * This field is a logical part of the 'Class' type.
- */
- private int preRedefineClassDefIndex;
-
- /**
* Private constructor.
*
* Only created by the runtime.
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index 7d70680..3729468 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -272,6 +272,8 @@
* app starts to run, because it may change the VM's behavior in
* dangerous ways. Defaults to {@link #SDK_VERSION_CUR_DEVELOPMENT}.
*/
+ @UnsupportedAppUsage(maxTargetSdk=0, publicAlternatives="Use the {@code targetSdkVersion}"
+ +" attribute in the {@code uses-sdk} manifest tag instead.")
@libcore.api.CorePlatformApi
public synchronized void setTargetSdkVersion(int targetSdkVersion) {
this.targetSdkVersion = targetSdkVersion;
diff --git a/luni/src/main/java/android/compat/Compatibility.java b/luni/src/main/java/android/compat/Compatibility.java
new file mode 100644
index 0000000..baf46bf
--- /dev/null
+++ b/luni/src/main/java/android/compat/Compatibility.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2019 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 android.compat;
+
+import android.compat.annotation.ChangeId;
+
+import libcore.api.CorePlatformApi;
+import libcore.api.IntraCoreApi;
+
+/**
+ * Internal APIs for logging and gating compatibility changes.
+ *
+ * @see ChangeId
+ *
+ * @hide
+ */
+@CorePlatformApi
+@IntraCoreApi
+public final class Compatibility {
+
+ private Compatibility() {}
+
+ /**
+ * Reports that a compatibility change is affecting the current process now.
+ *
+ * <p>Calls to this method from a non-app process are ignored. This allows code implementing
+ * APIs that are used by apps and by other code (e.g. the system server) to report changes
+ * regardless of the process it's running in. When called in a non-app process, this method is
+ * a no-op.
+ *
+ * <p>Note: for changes that are gated using {@link #isChangeEnabled(long)}, you do not need to
+ * call this API directly. The change will be reported for you in the case that
+ * {@link #isChangeEnabled(long)} returns {@code true}.
+ *
+ * @param changeId The ID of the compatibility change taking effect.
+ */
+ @CorePlatformApi
+ @IntraCoreApi
+ public static void reportChange(@ChangeId long changeId) {
+ sCallbacks.reportChange(changeId);
+ }
+
+ /**
+ * Query if a given compatibility change is enabled for the current process. This method should
+ * only be called by code running inside a process of the affected app.
+ *
+ * <p>If this method returns {@code true}, the calling code should implement the compatibility
+ * change, resulting in differing behaviour compared to earlier releases. If this method returns
+ * {@code false}, the calling code should behave as it did in earlier releases.
+ *
+ * <p>When this method returns {@code true}, it will also report the change as
+ * {@link #reportChange(long)} would, so there is no need to call that method directly.
+ *
+ * @param changeId The ID of the compatibility change in question.
+ * @return {@code true} if the change is enabled for the current app.
+ */
+ @CorePlatformApi
+ @IntraCoreApi
+ public static boolean isChangeEnabled(@ChangeId long changeId) {
+ return sCallbacks.isChangeEnabled(changeId);
+ }
+
+ private volatile static Callbacks sCallbacks = new Callbacks();
+
+ @CorePlatformApi
+ public static void setCallbacks(Callbacks callbacks) {
+ sCallbacks = callbacks;
+ }
+
+ /**
+ * Base class for compatibility API implementations. The default implementation logs a warning
+ * to logcat.
+ *
+ * This is provided as a class rather than an interface to allow new methods to be added without
+ * breaking @CorePlatformApi binary compatibility.
+ */
+ @CorePlatformApi
+ public static class Callbacks {
+ @CorePlatformApi
+ protected Callbacks() {
+ }
+ @CorePlatformApi
+ protected void reportChange(long changeId) {
+ System.logW(String.format(
+ "No Compatibility callbacks set! Reporting change %d", changeId));
+ }
+ @CorePlatformApi
+ protected boolean isChangeEnabled(long changeId) {
+ System.logW(String.format(
+ "No Compatibility callbacks set! Querying change %d", changeId));
+ return true;
+ }
+ }
+
+}
diff --git a/luni/src/main/java/android/compat/annotation/ChangeId.java b/luni/src/main/java/android/compat/annotation/ChangeId.java
new file mode 100644
index 0000000..ea91223
--- /dev/null
+++ b/luni/src/main/java/android/compat/annotation/ChangeId.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 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 android.compat.annotation;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import libcore.api.CorePlatformApi;
+import libcore.api.IntraCoreApi;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that a field is a compatibility change ID.
+ *
+ * <p>A compatibility change is a change to the Android platform that may impact app behavior,
+ * relative to previous releases of Android. A change ID is a unique {@code long} identifying one
+ * such change. Compatibility change IDs should be defined as a {@code static final long}:
+ *
+ * <pre>{@code
+ * @ChangeId
+ * public static final long MY_CHANGE_ID = 123456789l;
+ * }</pre>
+ *
+ * <p>The value of the constant is the ID of an issue in <a href="https://issuetracker.google.com/">
+ * buganizer</a>.
+ *
+ * @hide
+ */
+@Retention(CLASS)
+@Target({FIELD, PARAMETER})
+@CorePlatformApi
+@IntraCoreApi
+public @interface ChangeId {
+}
diff --git a/luni/src/main/java/android/compat/annotation/Disabled.java b/luni/src/main/java/android/compat/annotation/Disabled.java
new file mode 100644
index 0000000..4779a24
--- /dev/null
+++ b/luni/src/main/java/android/compat/annotation/Disabled.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 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 android.compat.annotation;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import libcore.api.CorePlatformApi;
+import libcore.api.IntraCoreApi;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Used to indicate that a compatibility {@link ChangeId change} is disabled for all apps.
+ *
+ * <p>This annotation should only be applied to change ID constants that are also annotated with
+ * {@link ChangeId}. In any other context, this annotation will have no effect.
+ *
+ * @hide
+ */
+@Retention(CLASS)
+@Target({FIELD})
+@CorePlatformApi
+@IntraCoreApi
+public @interface Disabled {
+}
diff --git a/luni/src/main/java/android/compat/annotation/EnabledAfter.java b/luni/src/main/java/android/compat/annotation/EnabledAfter.java
new file mode 100644
index 0000000..aeb62fd
--- /dev/null
+++ b/luni/src/main/java/android/compat/annotation/EnabledAfter.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 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 android.compat.annotation;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import libcore.api.CorePlatformApi;
+import libcore.api.IntraCoreApi;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Used to indicate that a compatibility {@link ChangeId change} is enabled only for apps with a
+ * {@code targetSdkVersion} of <em>greater than</em> the given value.
+ *
+ * <p>This annotation should only be applied to change ID constants that are also annotated with
+ * {@link ChangeId}. In any other context, this annotation will have no effect.
+ *
+ * @hide
+ */
+@Retention(CLASS)
+@Target({FIELD})
+@CorePlatformApi
+@IntraCoreApi
+public @interface EnabledAfter {
+ /**
+ * @return The maximum {@code targetSdkVersion} for which this change does not apply. Apps with
+ * a {@code targetSdkVersion} of greater than this value will get the change.
+ */
+ @CorePlatformApi
+ @IntraCoreApi
+ int targetSdkVersion();
+}
diff --git a/luni/src/main/java/android/system/StructIcmpHdr.java b/luni/src/main/java/android/system/IcmpHeaders.java
similarity index 62%
rename from luni/src/main/java/android/system/StructIcmpHdr.java
rename to luni/src/main/java/android/system/IcmpHeaders.java
index 87ae679..2203d40 100644
--- a/luni/src/main/java/android/system/StructIcmpHdr.java
+++ b/luni/src/main/java/android/system/IcmpHeaders.java
@@ -19,22 +19,26 @@
import static android.system.OsConstants.ICMP6_ECHO_REQUEST;
import static android.system.OsConstants.ICMP_ECHO;
+import java.io.FileDescriptor;
+import java.net.SocketAddress;
+
/**
- * Corresponds to C's {@code struct icmphdr} from linux/icmp.h and {@code struct icmp6hdr} from
- * linux/icmpv6.h
+ * A utility class that can create ICMP header bytes corresponding to C's {@code struct icmphdr}
+ * from linux/icmp.h and {@code struct icmp6hdr} from linux/icmpv6.h. The bytes can be passed to
+ * methods like {@link Os#sendto(FileDescriptor, byte[], int, int, int, SocketAddress)}.
*
* @hide
*/
-public final class StructIcmpHdr {
- private byte[] packet;
+public final class IcmpHeaders {
- private StructIcmpHdr() {
- packet = new byte[8];
- }
+ private IcmpHeaders() {}
- /*
- * Echo or Echo Reply Message
+ /**
+ * Creates the header bytes for an {@link OsConstants#ICMP_ECHO} or
+ * {@link OsConstants#ICMP6_ECHO_REQUEST} message. Code, checksum and identifier are left as
+ * zeros.
*
+ * <pre>
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
@@ -42,21 +46,16 @@
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Identifier | Sequence Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Data ...
- * +-+-+-+-+-
+ * </pre>
*/
- public static StructIcmpHdr IcmpEchoHdr(boolean ipv4, int seq) {
- StructIcmpHdr hdr = new StructIcmpHdr();
- hdr.packet[0] = ipv4 ? (byte) ICMP_ECHO : (byte) ICMP6_ECHO_REQUEST;
+ public static byte[] createIcmpEchoHdr(boolean ipv4, int seq) {
+ byte[] bytes = new byte[8];
+ bytes[0] = ipv4 ? (byte) ICMP_ECHO : (byte) ICMP6_ECHO_REQUEST;
// packet[1]: Code is always zero.
// packet[2,3]: Checksum is computed by kernel.
// packet[4,5]: ID (= port) inserted by kernel.
- hdr.packet[6] = (byte) (seq >> 8);
- hdr.packet[7] = (byte) seq;
- return hdr;
- }
-
- public byte[] getBytes() {
- return packet.clone();
+ bytes[6] = (byte) (seq >> 8);
+ bytes[7] = (byte) seq;
+ return bytes;
}
}
diff --git a/luni/src/main/java/android/system/Int32Ref.java b/luni/src/main/java/android/system/Int32Ref.java
index 8f4a949..8ffcfc5 100644
--- a/luni/src/main/java/android/system/Int32Ref.java
+++ b/luni/src/main/java/android/system/Int32Ref.java
@@ -16,6 +16,8 @@
package android.system;
+import libcore.util.Objects;
+
import dalvik.annotation.compat.UnsupportedAppUsage;
/**
@@ -32,4 +34,8 @@
public Int32Ref(int value) {
this.value = value;
}
+
+ @Override public String toString() {
+ return Objects.toString(this);
+ }
}
diff --git a/luni/src/main/java/android/system/Int64Ref.java b/luni/src/main/java/android/system/Int64Ref.java
index f42450d8..77edaf0 100644
--- a/luni/src/main/java/android/system/Int64Ref.java
+++ b/luni/src/main/java/android/system/Int64Ref.java
@@ -16,6 +16,8 @@
package android.system;
+import libcore.util.Objects;
+
/**
* A signed 64bit integer reference suitable for passing to lower-level system calls.
*/
@@ -25,4 +27,8 @@
public Int64Ref(long value) {
this.value = value;
}
+
+ @Override public String toString() {
+ return Objects.toString(this);
+ }
}
diff --git a/luni/src/main/java/android/system/Os.java b/luni/src/main/java/android/system/Os.java
index ded3b1c..cc6b0a5 100644
--- a/luni/src/main/java/android/system/Os.java
+++ b/luni/src/main/java/android/system/Os.java
@@ -153,9 +153,6 @@
public static void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException { Libcore.os.fchown(fd, uid, gid); }
/** @hide */
- public static int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException, InterruptedIOException { return Libcore.os.fcntlFlock(fd, cmd, arg); }
-
- /** @hide */
@libcore.api.CorePlatformApi
public static int fcntlInt(FileDescriptor fd, int cmd, int arg) throws ErrnoException { return Libcore.os.fcntlInt(fd, cmd, arg); }
diff --git a/luni/src/main/java/android/system/OsConstants.java b/luni/src/main/java/android/system/OsConstants.java
index a119ec7..50448d0 100644
--- a/luni/src/main/java/android/system/OsConstants.java
+++ b/luni/src/main/java/android/system/OsConstants.java
@@ -130,6 +130,7 @@
public static final int ARPHRD_ETHER = placeholder();
/** @hide */
@UnsupportedAppUsage
+ @libcore.api.CorePlatformApi
public static final int ARPHRD_LOOPBACK = placeholder();
public static final int CAP_AUDIT_CONTROL = placeholder();
public static final int CAP_AUDIT_WRITE = placeholder();
diff --git a/luni/src/main/java/android/system/PacketSocketAddress.java b/luni/src/main/java/android/system/PacketSocketAddress.java
index d375226..ce4081d 100644
--- a/luni/src/main/java/android/system/PacketSocketAddress.java
+++ b/luni/src/main/java/android/system/PacketSocketAddress.java
@@ -29,24 +29,29 @@
*/
@libcore.api.CorePlatformApi
public final class PacketSocketAddress extends SocketAddress {
- /** Protocol. An Ethernet protocol type, e.g., {@code ETH_P_IPV6}. */
- public short sll_protocol;
+ /** Protocol. An Ethernet protocol type, e.g., {@link OsConstants#ETH_P_IPV6}. */
+ public final int sll_protocol;
/** Interface index. */
- public int sll_ifindex;
+ public final int sll_ifindex;
- /** ARP hardware type. One of the {@code ARPHRD_*} constants. */
- public short sll_hatype;
+ /**
+ * ARP hardware type. One of the {@code ARPHRD_*} constants, such as
+ * {@link OsConstants#ARPHRD_ETHER}.
+ */
+ public final int sll_hatype;
- /** Packet type. One of the {@code PACKET_*} constants, such as {@code PACKET_OTHERHOST}. */
- public byte sll_pkttype;
+ /**
+ * Packet type.
+ */
+ public final int sll_pkttype;
/** Hardware address. */
- public byte[] sll_addr;
+ public final byte[] sll_addr;
- /** Constructs a new PacketSocketAddress. */
- public PacketSocketAddress(short sll_protocol, int sll_ifindex,
- short sll_hatype, byte sll_pkttype, byte[] sll_addr) {
+ /** Constructs a new PacketSocketAddress. Used from native code. */
+ public PacketSocketAddress(int sll_protocol, int sll_ifindex, int sll_hatype, int sll_pkttype,
+ byte[] sll_addr) {
this.sll_protocol = sll_protocol;
this.sll_ifindex = sll_ifindex;
this.sll_hatype = sll_hatype;
@@ -54,17 +59,38 @@
this.sll_addr = sll_addr;
}
- /** Constructs a new PacketSocketAddress suitable for binding to. */
- @UnsupportedAppUsage
+ /** Constructs a new PacketSocketAddress with all the "in" parameters. */
@libcore.api.CorePlatformApi
- public PacketSocketAddress(short sll_protocol, int sll_ifindex) {
- this(sll_protocol, sll_ifindex, (short) 0, (byte) 0, null);
+ public PacketSocketAddress(int sll_protocol, int sll_ifindex, byte[] sll_addr) {
+ this.sll_protocol = sll_protocol;
+ this.sll_ifindex = sll_ifindex;
+ this.sll_hatype = 0;
+ this.sll_pkttype = 0;
+ this.sll_addr = sll_addr;
}
- /** Constructs a new PacketSocketAddress suitable for sending to. */
+ /** Legacy constructor. Kept for @UnsupportedAppUsage only. */
@UnsupportedAppUsage
- @libcore.api.CorePlatformApi
+ public PacketSocketAddress(short sll_protocol, int sll_ifindex) {
+ this.sll_protocol = sll_protocol;
+ this.sll_ifindex = sll_ifindex;
+ this.sll_hatype = 0;
+ this.sll_pkttype = 0;
+ this.sll_addr = null;
+ }
+
+ /** Legacy constructor. Kept for @UnsupportedAppUsage only. */
+ @UnsupportedAppUsage
public PacketSocketAddress(int sll_ifindex, byte[] sll_addr) {
- this((short) 0, sll_ifindex, (short) 0, (byte) 0, sll_addr);
+ this.sll_protocol = 0;
+ this.sll_ifindex = sll_ifindex;
+ this.sll_hatype = 0;
+ this.sll_pkttype = 0;
+ this.sll_addr = sll_addr;
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toString(this);
}
}
diff --git a/luni/src/main/java/android/system/StructFlock.java b/luni/src/main/java/android/system/StructFlock.java
deleted file mode 100644
index 0d93425..0000000
--- a/luni/src/main/java/android/system/StructFlock.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2011 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 android.system;
-
-import libcore.util.Objects;
-
-/**
- * Information returned/taken by fcntl(2) F_GETFL and F_SETFL. Corresponds to C's
- * {@code struct flock} from
- * <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html"><fcntl.h></a>
- *
- * @hide
- */
-public final class StructFlock {
- /** The operation type, one of F_RDLCK, F_WRLCK, or F_UNLCK. */
- public short l_type;
-
- /** How to interpret l_start, one of SEEK_CUR, SEEK_END, SEEK_SET. */
- public short l_whence;
-
- /** Start offset. */
- public long l_start; /*off_t*/
-
- /** Byte count to operate on. */
- public long l_len; /*off_t*/
-
- /** Process blocking our lock (filled in by F_GETLK, otherwise unused). */
- public int l_pid; /*pid_t*/
-
- @Override public String toString() {
- return Objects.toString(this);
- }
-}
diff --git a/luni/src/main/java/android/system/StructIfaddrs.java b/luni/src/main/java/android/system/StructIfaddrs.java
index 7769f28..81d180a 100644
--- a/luni/src/main/java/android/system/StructIfaddrs.java
+++ b/luni/src/main/java/android/system/StructIfaddrs.java
@@ -16,6 +16,8 @@
package android.system;
+import libcore.util.Objects;
+
import java.net.InetAddress;
/**
@@ -44,4 +46,8 @@
this.ifa_broadaddr = ifa_broadaddr;
this.hwaddr = hwaddr;
}
+
+ @Override public String toString() {
+ return Objects.toString(this);
+ }
}
diff --git a/luni/src/main/java/android/system/UnixSocketAddress.java b/luni/src/main/java/android/system/UnixSocketAddress.java
index be689b3..bd211ef 100644
--- a/luni/src/main/java/android/system/UnixSocketAddress.java
+++ b/luni/src/main/java/android/system/UnixSocketAddress.java
@@ -35,7 +35,7 @@
// 1) pathname: 0 < sun_path.length <= NAMED_PATH_LENGTH, sun_path[0] != 0.
// 2) unnamed: sun_path = [].
// 3) abstract: 0 < sun_path.length <= NAMED_PATH_LENGTH, sun_path[0] == 0.
- private byte[] sun_path;
+ private final byte[] sun_path;
/** This constructor is also used from JNI. */
private UnixSocketAddress(byte[] sun_path) {
diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java
index 1c1dec2..c82cbe0 100644
--- a/luni/src/main/java/libcore/io/ForwardingOs.java
+++ b/luni/src/main/java/libcore/io/ForwardingOs.java
@@ -23,7 +23,6 @@
import android.system.StructAddrinfo;
import android.system.StructCapUserData;
import android.system.StructCapUserHeader;
-import android.system.StructFlock;
import android.system.StructGroupReq;
import android.system.StructIfaddrs;
import android.system.StructLinger;
@@ -101,7 +100,6 @@
public void execve(String filename, String[] argv, String[] envp) throws ErrnoException { os.execve(filename, argv, envp); }
public void fchmod(FileDescriptor fd, int mode) throws ErrnoException { os.fchmod(fd, mode); }
public void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException { os.fchown(fd, uid, gid); }
- public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException, InterruptedIOException { return os.fcntlFlock(fd, cmd, arg); }
public int fcntlInt(FileDescriptor fd, int cmd, int arg) throws ErrnoException { return os.fcntlInt(fd, cmd, arg); }
public int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException { return os.fcntlVoid(fd, cmd); }
public void fdatasync(FileDescriptor fd) throws ErrnoException { os.fdatasync(fd); }
diff --git a/luni/src/main/java/libcore/io/Linux.java b/luni/src/main/java/libcore/io/Linux.java
index 3766ac1..e2a4c54 100644
--- a/luni/src/main/java/libcore/io/Linux.java
+++ b/luni/src/main/java/libcore/io/Linux.java
@@ -23,7 +23,6 @@
import android.system.StructAddrinfo;
import android.system.StructCapUserData;
import android.system.StructCapUserHeader;
-import android.system.StructFlock;
import android.system.StructGroupReq;
import android.system.StructIfaddrs;
import android.system.StructLinger;
@@ -76,7 +75,6 @@
public native void execve(String filename, String[] argv, String[] envp) throws ErrnoException;
public native void fchmod(FileDescriptor fd, int mode) throws ErrnoException;
public native void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException;
- public native int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException, InterruptedIOException;
public native int fcntlInt(FileDescriptor fd, int cmd, int arg) throws ErrnoException;
public native int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException;
public native void fdatasync(FileDescriptor fd) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java
index e1ffa48..a7bae10 100644
--- a/luni/src/main/java/libcore/io/Os.java
+++ b/luni/src/main/java/libcore/io/Os.java
@@ -23,7 +23,6 @@
import android.system.StructAddrinfo;
import android.system.StructCapUserData;
import android.system.StructCapUserHeader;
-import android.system.StructFlock;
import android.system.StructGroupReq;
import android.system.StructIfaddrs;
import android.system.StructLinger;
@@ -76,7 +75,6 @@
public void execve(String filename, String[] argv, String[] envp) throws ErrnoException;
public void fchmod(FileDescriptor fd, int mode) throws ErrnoException;
public void fchown(FileDescriptor fd, int uid, int gid) throws ErrnoException;
- public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException, InterruptedIOException;
public int fcntlInt(FileDescriptor fd, int cmd, int arg) throws ErrnoException;
public int fcntlVoid(FileDescriptor fd, int cmd) throws ErrnoException;
public void fdatasync(FileDescriptor fd) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java b/luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java
index 5919a19..5593ad4 100644
--- a/luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java
+++ b/luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java
@@ -28,11 +28,10 @@
}
public Type getGenericComponentType() {
- try {
+ if (componentType instanceof ParameterizedTypeImpl) {
return ((ParameterizedTypeImpl)componentType).getResolvedType();
- } catch (ClassCastException e) {
- return componentType;
}
+ return componentType;
}
@Override
diff --git a/luni/src/main/java/libcore/reflect/GenericSignatureParser.java b/luni/src/main/java/libcore/reflect/GenericSignatureParser.java
index 5e86c49..2216cd6 100644
--- a/luni/src/main/java/libcore/reflect/GenericSignatureParser.java
+++ b/luni/src/main/java/libcore/reflect/GenericSignatureParser.java
@@ -315,18 +315,18 @@
qualIdent.append(this.identifier);
ListOfTypes typeArgs = parseOptTypeArguments();
- ParameterizedTypeImpl parentType =
- new ParameterizedTypeImpl(null, qualIdent.toString(), typeArgs, loader);
- ParameterizedTypeImpl type = parentType;
+ ParameterizedTypeImpl type = new ParameterizedTypeImpl(
+ null /* ownerType */, qualIdent.toString(), typeArgs, loader);
+ ParameterizedTypeImpl ownerType;
while (symbol == '.') {
// Deal with Member Classes:
scanSymbol();
scanIdentifier();
qualIdent.append("$").append(identifier); // FIXME: is "$" correct?
typeArgs = parseOptTypeArguments();
- type = new ParameterizedTypeImpl(parentType, qualIdent.toString(), typeArgs,
- loader);
+ ownerType = type;
+ type = new ParameterizedTypeImpl(ownerType, qualIdent.toString(), typeArgs, loader);
}
expect(';');
diff --git a/luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java b/luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java
index 2cd5ac3..47f64a8 100644
--- a/luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java
+++ b/luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java
@@ -40,11 +40,12 @@
this.loader = loader;
}
-
+ @Override
public Type[] getActualTypeArguments() {
return args.getResolvedTypes().clone();
}
+ @Override
public Type getOwnerType() {
if (ownerTypeRes == null) {
if (ownerType0 != null) {
@@ -56,6 +57,7 @@
return ownerTypeRes;
}
+ @Override
public Class getRawType() {
if (rawType == null) {
// Here the actual loading of the class has to be performed and the
@@ -70,9 +72,8 @@
return rawType;
}
-
Type getResolvedType() {
- if (args.getResolvedTypes().length == 0) {
+ if (ownerType0 == null && args.getResolvedTypes().length == 0) {
return getRawType();
} else {
return this;
@@ -99,7 +100,15 @@
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append(rawTypeName);
+ if (ownerType0 != null) {
+ // For nested types, use the ownerType because it or its parents may have their own
+ // type arguments.
+ sb.append(ownerType0);
+ sb.append('$');
+ sb.append(getRawType().getSimpleName());
+ } else {
+ sb.append(rawTypeName);
+ }
if (args.length() > 0) {
sb.append("<").append(args).append(">");
}
diff --git a/luni/src/main/java/libcore/timezone/TimeZoneDataFiles.java b/luni/src/main/java/libcore/timezone/TimeZoneDataFiles.java
index e3c015d..a571ec7 100644
--- a/luni/src/main/java/libcore/timezone/TimeZoneDataFiles.java
+++ b/luni/src/main/java/libcore/timezone/TimeZoneDataFiles.java
@@ -98,6 +98,9 @@
public static String generateIcuDataPath() {
List<String> paths = new ArrayList<>(3);
+ // Note: This logic below should match the logic in IcuRegistration.cpp in external/icu/
+ // to ensure consistent behavior between ICU4C and ICU4J.
+
// ICU should first look in ANDROID_DATA. This is used for (optional) time zone data
// delivered by APK (https://source.android.com/devices/tech/config/timezone-rules)
String dataIcuDataPath =
diff --git a/luni/src/main/native/Android.bp b/luni/src/main/native/Android.bp
index 58ea877..8621752 100644
--- a/luni/src/main/native/Android.bp
+++ b/luni/src/main/native/Android.bp
@@ -2,7 +2,6 @@
name: "luni_native_srcs",
srcs: [
"ExecStrings.cpp",
- "IcuRegistration.cpp",
"IcuUtilities.cpp",
"JniConstants.cpp",
"JniException.cpp",
diff --git a/luni/src/main/native/IcuRegistration.cpp b/luni/src/main/native/IcuRegistration.cpp
deleted file mode 100644
index f73560f..0000000
--- a/luni/src/main/native/IcuRegistration.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 2019 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.
- */
-
-#include "IcuRegistration.h"
-
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <android-base/logging.h>
-#include <android-base/unique_fd.h>
-#include <log/log.h>
-#include <unicode/uclean.h>
-#include <unicode/udata.h>
-#include <unicode/utypes.h>
-
-namespace libcore {
-namespace impl {
-
-// Map in ICU data at the path, returning null if it failed (prints error to
-// ALOGE).
-std::unique_ptr<IcuDataMap> IcuDataMap::Create(const std::string& path) {
- std::unique_ptr<IcuDataMap> map(new IcuDataMap(path));
-
- if (!map->TryMap()) {
- // madvise or ICU could fail but mmap still succeeds.
- // Destructor will take care of cleaning up a partial init.
- return nullptr;
- }
-
- return map;
-}
-
-// Unmap the ICU data.
-IcuDataMap::~IcuDataMap() { TryUnmap(); }
-
-bool IcuDataMap::TryMap() {
- // Open the file and get its length.
- android::base::unique_fd fd(
- TEMP_FAILURE_RETRY(open(path_.c_str(), O_RDONLY)));
-
- if (fd.get() == -1) {
- ALOGE("Couldn't open '%s': %s", path_.c_str(), strerror(errno));
- return false;
- }
-
- struct stat sb;
- if (fstat(fd.get(), &sb) == -1) {
- ALOGE("Couldn't stat '%s': %s", path_.c_str(), strerror(errno));
- return false;
- }
-
- data_length_ = sb.st_size;
-
- // Map it.
- data_ =
- mmap(NULL, data_length_, PROT_READ, MAP_SHARED, fd.get(), 0 /* offset */);
- if (data_ == MAP_FAILED) {
- ALOGE("Couldn't mmap '%s': %s", path_.c_str(), strerror(errno));
- return false;
- }
-
- // Tell the kernel that accesses are likely to be random rather than
- // sequential.
- if (madvise(data_, data_length_, MADV_RANDOM) == -1) {
- ALOGE("Couldn't madvise(MADV_RANDOM) '%s': %s", path_.c_str(),
- strerror(errno));
- return false;
- }
-
- UErrorCode status = U_ZERO_ERROR;
-
- // Tell ICU to use our memory-mapped data.
- udata_setCommonData(data_, &status);
- if (status != U_ZERO_ERROR) {
- ALOGE("Couldn't initialize ICU (udata_setCommonData): %s (%s)",
- u_errorName(status), path_.c_str());
- return false;
- }
-
- return true;
-}
-
-bool IcuDataMap::TryUnmap() {
- // Don't need to do opposite of udata_setCommonData,
- // u_cleanup (performed in IcuRegistration::~IcuRegistration()) takes care of
- // it.
-
- // Don't need to opposite of madvise, munmap will take care of it.
-
- if (data_ != nullptr && data_ != MAP_FAILED) {
- if (munmap(data_, data_length_) == -1) {
- ALOGE("Couldn't munmap '%s': %s", path_.c_str(), strerror(errno));
- return false;
- }
- }
-
- // Don't need to close the file, it was closed automatically during TryMap.
- return true;
-}
-
-} // namespace impl
-
-// A pointer to the singleton instance used by Register and Deregister.
-static std::unique_ptr<IcuRegistration> gIcuRegistration;
-
-void IcuRegistration::Register() {
- CHECK(gIcuRegistration.get() == nullptr);
-
- gIcuRegistration.reset(new IcuRegistration());
-}
-
-void IcuRegistration::Deregister() {
- gIcuRegistration.reset();
-}
-
-// Init ICU, configuring it and loading the data files.
-IcuRegistration::IcuRegistration() {
- UErrorCode status = U_ZERO_ERROR;
- // Tell ICU it can *only* use our memory-mapped data.
- udata_setFileAccess(UDATA_NO_FILES, &status);
- if (status != U_ZERO_ERROR) {
- ALOGE("Couldn't initialize ICU (s_setFileAccess): %s", u_errorName(status));
- abort();
- }
-
- // Check the timezone /data override file exists from the "Time zone update
- // via APK" feature.
- // https://source.android.com/devices/tech/config/timezone-rules
- // If it does, map it first so we use its data in preference to later ones.
- std::string dataPath = getDataTimeZonePath();
- if (pathExists(dataPath)) {
- ALOGD("Time zone override file found: %s", dataPath.c_str());
- icu_datamap_from_data_ = impl::IcuDataMap::Create(dataPath);
- if (icu_datamap_from_data_ == nullptr) {
- ALOGW(
- "TZ override /data file %s exists but could not be loaded. Skipping.",
- dataPath.c_str());
- }
- } else {
- ALOGV("No timezone override /data file found: %s", dataPath.c_str());
- }
-
- // Check the timezone override file exists from a mounted APEX file.
- // If it does, map it next so we use its data in preference to later ones.
- std::string tzModulePath = getTimeZoneModulePath();
- if (pathExists(tzModulePath)) {
- ALOGD("Time zone APEX file found: %s", tzModulePath.c_str());
- icu_datamap_from_tz_module_ = impl::IcuDataMap::Create(tzModulePath);
- if (icu_datamap_from_tz_module_ == nullptr) {
- ALOGW(
- "TZ module override file %s exists but could not be loaded. "
- "Skipping.",
- tzModulePath.c_str());
- }
- } else {
- ALOGV("No time zone module override file found: %s", tzModulePath.c_str());
- }
-
- // Use the ICU data files that shipped with the runtime module for everything
- // else.
- icu_datamap_from_runtime_module_ =
- impl::IcuDataMap::Create(getRuntimeModulePath());
- if (icu_datamap_from_runtime_module_ == nullptr) {
- // IcuDataMap::Create() will log on error so there is no need to log here.
- abort();
- }
-
- // Failures to find the ICU data tend to be somewhat obscure because ICU loads
- // its data on first use, which can be anywhere. Force initialization up front
- // so we can report a nice clear error and bail.
- u_init(&status);
- if (status != U_ZERO_ERROR) {
- ALOGE("Couldn't initialize ICU (u_init): %s", u_errorName(status));
- abort();
- }
-}
-
-// De-init ICU, unloading the data files. Do the opposite of the above function.
-IcuRegistration::~IcuRegistration() {
- // Reset libicu state to before it was loaded.
- u_cleanup();
-
- // Unmap ICU data files.
- icu_datamap_from_runtime_module_.reset();
- icu_datamap_from_tz_module_.reset();
- icu_datamap_from_data_.reset();
-
- // We don't need to call udata_setFileAccess because u_cleanup takes care of
- // it.
-}
-
-bool IcuRegistration::pathExists(const std::string path) {
- struct stat sb;
- return stat(path.c_str(), &sb) == 0;
-}
-
-// Returns a string containing the expected path of the (optional) /data tz data
-// file
-std::string IcuRegistration::getDataTimeZonePath() {
- const char* dataPathPrefix = getenv("ANDROID_DATA");
- if (dataPathPrefix == NULL) {
- ALOGE("ANDROID_DATA environment variable not set");
- abort();
- }
- std::string dataPath;
- dataPath = dataPathPrefix;
- dataPath += "/misc/zoneinfo/current/icu/icu_tzdata.dat";
-
- return dataPath;
-}
-
-// Returns a string containing the expected path of the (optional) /apex tz
-// module data file
-std::string IcuRegistration::getTimeZoneModulePath() {
- const char* tzdataModulePathPrefix = getenv("ANDROID_TZDATA_ROOT");
- if (tzdataModulePathPrefix == NULL) {
- ALOGE("ANDROID_TZDATA_ROOT environment variable not set");
- abort();
- }
-
- std::string tzdataModulePath;
- tzdataModulePath = tzdataModulePathPrefix;
- tzdataModulePath += "/etc/icu/icu_tzdata.dat";
- return tzdataModulePath;
-}
-
-std::string IcuRegistration::getRuntimeModulePath() {
- const char* runtimeModulePathPrefix = getenv("ANDROID_RUNTIME_ROOT");
- if (runtimeModulePathPrefix == NULL) {
- ALOGE("ANDROID_RUNTIME_ROOT environment variable not set");
- abort();
- }
-
- std::string runtimeModulePath;
- runtimeModulePath = runtimeModulePathPrefix;
- runtimeModulePath += "/etc/icu/";
- runtimeModulePath += U_ICUDATA_NAME;
- runtimeModulePath += ".dat";
- return runtimeModulePath;
-}
-
-} // namespace libcore
diff --git a/luni/src/main/native/IcuRegistration.h b/luni/src/main/native/IcuRegistration.h
deleted file mode 100644
index db8733f..0000000
--- a/luni/src/main/native/IcuRegistration.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2019 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 ICU_REGISTRATION_H_included
-#define ICU_REGISTRATION_H_included
-
-#include <memory>
-#include <string>
-
-#include <android-base/macros.h>
-#include <jni.h>
-
-namespace libcore {
-namespace impl {
-
-/*
- * Handles ICU data mapping for a single ICU .dat file.
- * The Create method handles mapping the file into memory and calling
- * udata_setCommonData(). The file is unmapped on object destruction.
- */
-class IcuDataMap final {
- public:
- // Maps in ICU data at the path and call udata_setCommonData(), returning
- // null if it failed (prints error to ALOGE).
- static std::unique_ptr<IcuDataMap> Create(const std::string& path);
- // Unmaps the ICU data.
- ~IcuDataMap();
-
- private:
- IcuDataMap(const std::string& path)
- : path_(path), data_(nullptr), data_length_(0) {}
- bool TryMap();
- bool TryUnmap();
-
- std::string path_; // Save for error messages.
- void* data_; // Save for munmap.
- size_t data_length_; // Save for munmap.
-
- DISALLOW_COPY_AND_ASSIGN(IcuDataMap);
-};
-
-} // namespace impl
-
-/*
- * Handles the mapping of all ICU data files into memory for the various files
- * used on Android. All data files are unmapped on object destruction.
- */
-class IcuRegistration final {
- public:
- static void Register();
- static void Deregister();
-
- // Required to be public so it can be destructed by unique_ptr.
- ~IcuRegistration();
-
- private:
- IcuRegistration();
-
- static bool pathExists(const std::string path);
- static std::string getDataTimeZonePath();
- static std::string getTimeZoneModulePath();
- static std::string getRuntimeModulePath();
-
- std::unique_ptr<impl::IcuDataMap> icu_datamap_from_data_;
- std::unique_ptr<impl::IcuDataMap> icu_datamap_from_tz_module_;
- std::unique_ptr<impl::IcuDataMap> icu_datamap_from_runtime_module_;
-
- DISALLOW_COPY_AND_ASSIGN(IcuRegistration);
-};
-
-} // namespace libcore
-
-#endif // ICU_REGISTRATION_H_included
diff --git a/luni/src/main/native/JniConstants.cpp b/luni/src/main/native/JniConstants.cpp
index 8427353..bf567aa 100644
--- a/luni/src/main/native/JniConstants.cpp
+++ b/luni/src/main/native/JniConstants.cpp
@@ -64,7 +64,6 @@
jclass patternSyntaxExceptionClass;
jclass stringClass;
jclass structAddrinfoClass;
-jclass structFlockClass;
jclass structGroupReqClass;
jclass structIfaddrsClass;
jclass structLingerClass;
@@ -112,7 +111,6 @@
patternSyntaxExceptionClass = findClass(env, "java/util/regex/PatternSyntaxException");
stringClass = findClass(env, "java/lang/String");
structAddrinfoClass = findClass(env, "android/system/StructAddrinfo");
- structFlockClass = findClass(env, "android/system/StructFlock");
structGroupReqClass = findClass(env, "android/system/StructGroupReq");
structIfaddrsClass = findClass(env, "android/system/StructIfaddrs");
structLingerClass = findClass(env, "android/system/StructLinger");
@@ -240,11 +238,6 @@
return structAddrinfoClass;
}
-jclass JniConstants::GetStructFlockClass(JNIEnv* env) {
- EnsureJniConstantsInitialized(env);
- return structFlockClass;
-}
-
jclass JniConstants::GetStructGroupReqClass(JNIEnv* env) {
EnsureJniConstantsInitialized(env);
return structGroupReqClass;
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index a246c25..2cbf40f 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -30,6 +30,7 @@
#include <memory>
#include <vector>
+#include <androidicuinit/IcuRegistration.h>
#include <log/log.h>
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedLocalRef.h>
@@ -37,7 +38,6 @@
#include <nativehelper/jni_macros.h>
#include <nativehelper/toStringArray.h>
-#include "IcuRegistration.h"
#include "IcuUtilities.h"
#include "JniConstants.h"
#include "JniException.h"
@@ -846,7 +846,7 @@
// Init ICU, configuring it and loading the data files.
void register_libcore_icu_ICU(JNIEnv* env) {
- libcore::IcuRegistration::Register();
+ androidicuinit::IcuRegistration::Register();
jniRegisterNativeMethods(env, "libcore/icu/ICU", gMethods, NELEM(gMethods));
}
@@ -856,5 +856,5 @@
// Skip unregistering JNI methods explicitly, class unloading takes care of
// it.
- libcore::IcuRegistration::Deregister();
+ androidicuinit::IcuRegistration::Deregister();
}
diff --git a/luni/src/main/native/libcore_io_Linux.cpp b/luni/src/main/native/libcore_io_Linux.cpp
index 6b8ee08..805b32f 100644
--- a/luni/src/main/native/libcore_io_Linux.cpp
+++ b/luni/src/main/native/libcore_io_Linux.cpp
@@ -418,7 +418,7 @@
} else if (ss.ss_family == AF_PACKET) {
const struct sockaddr_ll* sll = reinterpret_cast<const struct sockaddr_ll*>(&ss);
static jmethodID ctor = env->GetMethodID(JniConstants::GetPacketSocketAddressClass(env),
- "<init>", "(SISB[B)V");
+ "<init>", "(IIII[B)V");
if (ctor == NULL) {
return NULL;
}
@@ -429,10 +429,10 @@
env->SetByteArrayRegion(byteArray.get(), 0, sll->sll_halen,
reinterpret_cast<const jbyte*>(sll->sll_addr));
jobject packetSocketAddress = env->NewObject(JniConstants::GetPacketSocketAddressClass(env), ctor,
- static_cast<jshort>(ntohs(sll->sll_protocol)),
+ static_cast<jint>(ntohs(sll->sll_protocol)),
static_cast<jint>(sll->sll_ifindex),
- static_cast<jshort>(sll->sll_hatype),
- static_cast<jbyte>(sll->sll_pkttype),
+ static_cast<jint>(sll->sll_hatype),
+ static_cast<jint>(sll->sll_pkttype),
byteArray.get());
return packetSocketAddress;
}
@@ -686,22 +686,22 @@
static bool javaPacketSocketAddressToSockaddr(
JNIEnv* env, jobject javaSocketAddress, sockaddr_storage& ss, socklen_t& sa_len) {
static jfieldID protocolFid = env->GetFieldID(
- JniConstants::GetPacketSocketAddressClass(env), "sll_protocol", "S");
+ JniConstants::GetPacketSocketAddressClass(env), "sll_protocol", "I");
static jfieldID ifindexFid = env->GetFieldID(
JniConstants::GetPacketSocketAddressClass(env), "sll_ifindex", "I");
static jfieldID hatypeFid = env->GetFieldID(
- JniConstants::GetPacketSocketAddressClass(env), "sll_hatype", "S");
+ JniConstants::GetPacketSocketAddressClass(env), "sll_hatype", "I");
static jfieldID pkttypeFid = env->GetFieldID(
- JniConstants::GetPacketSocketAddressClass(env), "sll_pkttype", "B");
+ JniConstants::GetPacketSocketAddressClass(env), "sll_pkttype", "I");
static jfieldID addrFid = env->GetFieldID(
JniConstants::GetPacketSocketAddressClass(env), "sll_addr", "[B");
sockaddr_ll *sll = reinterpret_cast<sockaddr_ll *>(&ss);
sll->sll_family = AF_PACKET;
- sll->sll_protocol = htons(env->GetShortField(javaSocketAddress, protocolFid));
+ sll->sll_protocol = htons(env->GetIntField(javaSocketAddress, protocolFid));
sll->sll_ifindex = env->GetIntField(javaSocketAddress, ifindexFid);
- sll->sll_hatype = env->GetShortField(javaSocketAddress, hatypeFid);
- sll->sll_pkttype = env->GetByteField(javaSocketAddress, pkttypeFid);
+ sll->sll_hatype = env->GetIntField(javaSocketAddress, hatypeFid);
+ sll->sll_pkttype = env->GetIntField(javaSocketAddress, pkttypeFid);
jbyteArray sllAddr = (jbyteArray) env->GetObjectField(javaSocketAddress, addrFid);
if (sllAddr == NULL) {
@@ -1242,32 +1242,6 @@
throwIfMinusOne(env, "fchown", TEMP_FAILURE_RETRY(fchown(fd, uid, gid)));
}
-static jint Linux_fcntlFlock(JNIEnv* env, jobject, jobject javaFd, jint cmd, jobject javaFlock) {
- static jfieldID typeFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_type", "S");
- static jfieldID whenceFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_whence", "S");
- static jfieldID startFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_start", "J");
- static jfieldID lenFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_len", "J");
- static jfieldID pidFid = env->GetFieldID(JniConstants::GetStructFlockClass(env), "l_pid", "I");
-
- struct flock64 lock;
- memset(&lock, 0, sizeof(lock));
- lock.l_type = env->GetShortField(javaFlock, typeFid);
- lock.l_whence = env->GetShortField(javaFlock, whenceFid);
- lock.l_start = env->GetLongField(javaFlock, startFid);
- lock.l_len = env->GetLongField(javaFlock, lenFid);
- lock.l_pid = env->GetIntField(javaFlock, pidFid);
-
- int rc = IO_FAILURE_RETRY(env, int, fcntl, javaFd, cmd, &lock);
- if (rc != -1) {
- env->SetShortField(javaFlock, typeFid, lock.l_type);
- env->SetShortField(javaFlock, whenceFid, lock.l_whence);
- env->SetLongField(javaFlock, startFid, lock.l_start);
- env->SetLongField(javaFlock, lenFid, lock.l_len);
- env->SetIntField(javaFlock, pidFid, lock.l_pid);
- }
- return rc;
-}
-
static jint Linux_fcntlInt(JNIEnv* env, jobject, jobject javaFd, jint cmd, jint arg) {
int fd = jniGetFDFromFileDescriptor(env, javaFd);
return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd, arg)));
@@ -2603,7 +2577,6 @@
NATIVE_METHOD(Linux, execve, "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V"),
NATIVE_METHOD(Linux, fchmod, "(Ljava/io/FileDescriptor;I)V"),
NATIVE_METHOD(Linux, fchown, "(Ljava/io/FileDescriptor;II)V"),
- NATIVE_METHOD(Linux, fcntlFlock, "(Ljava/io/FileDescriptor;ILandroid/system/StructFlock;)I"),
NATIVE_METHOD(Linux, fcntlInt, "(Ljava/io/FileDescriptor;II)I"),
NATIVE_METHOD(Linux, fcntlVoid, "(Ljava/io/FileDescriptor;I)I"),
NATIVE_METHOD(Linux, fdatasync, "(Ljava/io/FileDescriptor;)V"),
diff --git a/luni/src/test/java/libcore/android/system/OsTest.java b/luni/src/test/java/libcore/android/system/OsTest.java
index dd5e698..8b8aea0 100644
--- a/luni/src/test/java/libcore/android/system/OsTest.java
+++ b/luni/src/test/java/libcore/android/system/OsTest.java
@@ -551,14 +551,18 @@
Os.close(nlSocket);
}
+ // This test is excluded from CTS via the knownfailures.txt because it requires extra
+ // permissions not available in CTS. To run it you have to use an -eng build and use a tool like
+ // vogar that runs the Android runtime as a privileged user.
public void test_PacketSocketAddress() throws Exception {
NetworkInterface lo = NetworkInterface.getByName("lo");
FileDescriptor fd = Os.socket(AF_PACKET, SOCK_DGRAM, ETH_P_IPV6);
- PacketSocketAddress addr = new PacketSocketAddress((short) ETH_P_IPV6, lo.getIndex());
+ PacketSocketAddress addr =
+ new PacketSocketAddress(ETH_P_IPV6, lo.getIndex(), null /* sll_addr */);
Os.bind(fd, addr);
PacketSocketAddress bound = (PacketSocketAddress) Os.getsockname(fd);
- assertEquals((short) ETH_P_IPV6, bound.sll_protocol); // ETH_P_IPV6 is an int.
+ assertEquals(ETH_P_IPV6, bound.sll_protocol);
assertEquals(lo.getIndex(), bound.sll_ifindex);
assertEquals(ARPHRD_LOOPBACK, bound.sll_hatype);
assertEquals(0, bound.sll_pkttype);
@@ -569,6 +573,57 @@
for (int i = 0; i < 6; i++) {
assertEquals(0, bound.sll_addr[i]);
}
+
+ // The following checks that the packet socket address was constructed correctly in a form
+ // that the kernel understands. If the address is correct, the bind should result in a
+ // socket that is listening only for IPv6 packets, and only on loopback.
+
+ // Send an IPv4 packet on loopback.
+ // We send ourselves an IPv4 packet first. If we don't receive it, that (with high
+ // probability) ensures that the packet socket does not see IPv4 packets.
+ try (DatagramSocket s = new DatagramSocket()) {
+ byte[] packet = new byte[64];
+ s.send(new DatagramPacket(packet, 0, packet.length, Inet4Address.LOOPBACK,
+ 53 /* arbitrary port */));
+ }
+
+ // Send an IPv6 packet on loopback.
+ // Sending ourselves an IPv6 packet should cause the socket to receive a packet.
+ // The idea is that if the code gets sll_protocol wrong, then the packet socket will receive
+ // no packets and the test will fail.
+ try (DatagramSocket s = new DatagramSocket()) {
+ byte[] packet = new byte[64];
+ s.send(new DatagramPacket(packet, 0, packet.length, Inet6Address.LOOPBACK,
+ 53 /* arbitrary port */));
+ }
+
+ // Check that the socket associated with fd has received an IPv6 packet, not necessarily the
+ // UDP one we sent above. IPv6 packets always begin with the nibble 6. If we get anything
+ // else it means we're catching non-IPv6 or non-loopback packets unexpectedly. Since the
+ // socket is not discriminating it may catch packets unrelated to this test from things
+ // happening on the device at the same time, so we can't assert too much about the received
+ // packet, i.e. no length / content check.
+ {
+ byte[] receivedPacket = new byte[4096];
+ Os.read(fd, receivedPacket, 0, receivedPacket.length);
+ assertEquals(6, (receivedPacket[0] & 0xf0) >> 4);
+
+ byte[] sourceAddress = getIPv6AddressBytesAtOffset(receivedPacket, 8);
+ assertArrayEquals(Inet6Address.LOOPBACK.getAddress(), sourceAddress);
+
+ byte[] destAddress = getIPv6AddressBytesAtOffset(receivedPacket, 24);
+ assertArrayEquals(Inet6Address.LOOPBACK.getAddress(), destAddress);
+ }
+
+ Os.close(fd);
+ }
+
+ private static byte[] getIPv6AddressBytesAtOffset(byte[] packet, int offsetIndex) {
+ byte[] address = new byte[16];
+ for (int i = 0; i < 16; i++) {
+ address[i] = packet[i + offsetIndex];
+ }
+ return address;
}
public void test_byteBufferPositions_sendto_recvfrom_af_inet() throws Exception {
diff --git a/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java b/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java
index 0e2c6b5..17f031b 100644
--- a/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java
+++ b/luni/src/test/java/libcore/libcore/io/BlockGuardOsTest.java
@@ -189,7 +189,6 @@
"dup(java.io.FileDescriptor)",
"dup2(java.io.FileDescriptor,int)",
"environ()",
- "fcntlFlock(java.io.FileDescriptor,int,android.system.StructFlock)",
"fcntlInt(java.io.FileDescriptor,int,int)",
"fcntlVoid(java.io.FileDescriptor,int)",
"gai_strerror(int)",
diff --git a/luni/src/test/java/libcore/libcore/reflect/ParameterizedTypeRegressionTest.java b/luni/src/test/java/libcore/libcore/reflect/ParameterizedTypeRegressionTest.java
new file mode 100644
index 0000000..7da1161
--- /dev/null
+++ b/luni/src/test/java/libcore/libcore/reflect/ParameterizedTypeRegressionTest.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2019 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 libcore.libcore.reflect;
+
+import com.google.common.base.Joiner;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+
+/**
+ * Regression tests for http://b/124315589
+ */
+public class ParameterizedTypeRegressionTest {
+
+ // A set of nested classes used by some of the tests in this class.
+ class A<X> {
+ class B<Y> {
+ class C1<Z> {
+ // Leaf not generic.
+ class D1 {
+ }
+ }
+ // Non-leaf not generic.
+ class C2 {
+ class D2<Z> {
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testNoGeneric() {
+ Type actual = new ParameterizedClass<List>() {
+ // Anonymous class declaration.
+ }.getArgumentType();
+ Class<List> expected = List.class;
+ Assert.assertEquals(expected, actual);
+ Assert.assertEquals("interface java.util.List", actual.toString());
+ }
+
+ @Test
+ public void testGeneric() {
+ Type actual = new ParameterizedClass<List<Integer>>() {
+ // Anonymous class declaration.
+ }.getArgumentType();
+ ParameterizedTypeImpl expected = new ParameterizedTypeImpl(
+ null,
+ List.class,
+ Integer.class
+ );
+ Assert.assertEquals(expected, actual);
+ Assert.assertEquals("java.util.List<java.lang.Integer>", actual.toString());
+ }
+
+ @Test
+ public void testGenericOfGeneric() {
+ Type actual = new ParameterizedClass<List<Map<String, Float>>>() {
+ // Anonymous class declaration.
+ }.getArgumentType();
+ ParameterizedTypeImpl expected = new ParameterizedTypeImpl(
+ null,
+ List.class,
+ new ParameterizedTypeImpl(
+ null,
+ Map.class,
+ String.class,
+ Float.class)
+ );
+ Assert.assertEquals(expected, actual);
+ Assert.assertEquals(
+ "java.util.List<java.util.Map<java.lang.String, java.lang.Float>>",
+ actual.toString());
+ }
+
+ @Test
+ public void testNested1() {
+ Type actual = new ParameterizedClass<A<Integer>>() {
+ // Anonymous class declaration.
+ }.getArgumentType();
+ ParameterizedTypeImpl expected = new ParameterizedTypeImpl(
+ ParameterizedTypeRegressionTest.class,
+ A.class,
+ Integer.class
+ );
+ Assert.assertEquals(expected, actual);
+ Assert.assertEquals(
+ "libcore.libcore.reflect.ParameterizedTypeRegressionTest$A<java.lang.Integer>",
+ actual.toString());
+ }
+
+ @Test
+ public void testNested2() {
+ Type actual = new ParameterizedClass<A<Integer>.B<Float>>() {
+ // Anonymous class declaration.
+ }.getArgumentType();
+ ParameterizedTypeImpl expected = new ParameterizedTypeImpl(
+ new ParameterizedTypeImpl(
+ ParameterizedTypeRegressionTest.class,
+ A.class,
+ Integer.class),
+ A.B.class,
+ Float.class
+ );
+ Assert.assertEquals(expected, actual);
+ Assert.assertEquals(
+ "libcore.libcore.reflect.ParameterizedTypeRegressionTest$A<java.lang.Integer>"
+ + "$B<java.lang.Float>",
+ actual.toString());
+ }
+
+ @Test
+ public void testNested3() {
+ Type actual = new ParameterizedClass<A<Integer>.B<Float>.C1<String>>() {
+ // Anonymous class declaration.
+ }.getArgumentType();
+ ParameterizedTypeImpl expected = new ParameterizedTypeImpl(
+ new ParameterizedTypeImpl(
+ new ParameterizedTypeImpl(
+ ParameterizedTypeRegressionTest.class,
+ A.class,
+ Integer.class),
+ A.B.class,
+ Float.class),
+ A.B.C1.class,
+ String.class);
+ Assert.assertEquals(expected, actual);
+ Assert.assertEquals(
+ "libcore.libcore.reflect.ParameterizedTypeRegressionTest$A<java.lang.Integer>"
+ + "$B<java.lang.Float>"
+ + "$C1<java.lang.String>",
+ actual.toString());
+ }
+
+ @Test
+ public void testNested4_nonGenericLeaf() {
+ // This anonymous class has a non-generic leaf class (D).
+ Type actual = new ParameterizedClass<A<Integer>.B<Float>.C1<String>.D1>() {
+ // Anonymous class declaration.
+ }.getArgumentType();
+ ParameterizedTypeImpl expected = new ParameterizedTypeImpl(
+ new ParameterizedTypeImpl(
+ new ParameterizedTypeImpl(
+ new ParameterizedTypeImpl(
+ ParameterizedTypeRegressionTest.class,
+ A.class,
+ Integer.class),
+ A.B.class,
+ Float.class),
+ A.B.C1.class,
+ String.class),
+ A.B.C1.D1.class
+ );
+ Assert.assertEquals(expected, actual);
+ Assert.assertEquals(
+ "libcore.libcore.reflect.ParameterizedTypeRegressionTest$A<java.lang.Integer>"
+ + "$B<java.lang.Float>$C1<java.lang.String>$D1",
+ actual.toString());
+ }
+
+ @Test
+ public void testNested4_nonGenericNonLeaf() {
+ // This anonymous class has a non-generic class (C2).
+ Type actual = new ParameterizedClass<A<Integer>.B<Float>.C2.D2<String>>() {
+ // Anonymous class declaration.
+ }.getArgumentType();
+ ParameterizedTypeImpl expected = new ParameterizedTypeImpl(
+ new ParameterizedTypeImpl(
+ new ParameterizedTypeImpl(
+ new ParameterizedTypeImpl(
+ ParameterizedTypeRegressionTest.class,
+ A.class,
+ Integer.class),
+ A.B.class,
+ Float.class),
+ A.B.C2.class),
+ A.B.C2.D2.class,
+ String.class
+ );
+ Assert.assertEquals(expected, actual);
+ Assert.assertEquals(
+ "libcore.libcore.reflect.ParameterizedTypeRegressionTest$A<java.lang.Integer>"
+ + "$B<java.lang.Float>$C2$D2<java.lang.String>",
+ actual.toString());
+ }
+
+ private static class ParameterizedClass<T> {
+ public Type getArgumentType() {
+ Class<?> parameterizedClass = getClass();
+ return ((ParameterizedType) parameterizedClass.getGenericSuperclass())
+ .getActualTypeArguments()[0];
+ }
+ }
+
+ /**
+ * A straightforward implementation of ParameterizedType that implements equals() and can be
+ * used when comparing against the platform behavior.
+ */
+ private static class ParameterizedTypeImpl implements ParameterizedType {
+ private final Type ownerType;
+ private final Class<?> rawType;
+ private final Type[] typeArguments;
+
+ ParameterizedTypeImpl(Type ownerType, Class<?> rawType, Type... typeArguments) {
+ this.ownerType = ownerType;
+ this.rawType = rawType;
+ this.typeArguments = typeArguments;
+ }
+
+ @Override
+ public Class getRawType() {
+ return rawType;
+ }
+
+ @Override
+ public Type[] getActualTypeArguments() {
+ return typeArguments;
+ }
+
+ @Override
+ public Type getOwnerType() {
+ return ownerType;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder stringBuilder = new StringBuilder();
+ if (ownerType != null) {
+ stringBuilder.append(ownerType.getTypeName());
+ stringBuilder.append('$');
+ stringBuilder.append(rawType.getSimpleName());
+ } else {
+ stringBuilder.append(rawType.getName());
+ }
+ stringBuilder.append('<');
+ List<String> typeArgumentNames = Arrays.stream(typeArguments)
+ .map(Type::getTypeName)
+ .collect(Collectors.toList());
+ stringBuilder.append(Joiner.on(", ").join(typeArgumentNames));
+ stringBuilder.append('>');
+ return stringBuilder.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ParameterizedType)) {
+ return false;
+ }
+ ParameterizedType other = (ParameterizedType) obj;
+ return getRawType().equals(other.getRawType()) &&
+ Arrays.equals(getActualTypeArguments(), other.getActualTypeArguments()) &&
+ Objects.equals(getOwnerType(), other.getOwnerType());
+ }
+ }
+}
diff --git a/mmodules/core_platform_api/api/platform/current-api.txt b/mmodules/core_platform_api/api/platform/current-api.txt
index d127436..b4bfc1a 100644
--- a/mmodules/core_platform_api/api/platform/current-api.txt
+++ b/mmodules/core_platform_api/api/platform/current-api.txt
@@ -1,4 +1,34 @@
// Signature format: 2.0
+package android.compat {
+
+ public final class Compatibility {
+ method public static boolean isChangeEnabled(@android.compat.annotation.ChangeId long);
+ method public static void reportChange(@android.compat.annotation.ChangeId long);
+ method public static void setCallbacks(android.compat.Compatibility.Callbacks);
+ }
+
+ public static class Compatibility.Callbacks {
+ ctor protected Compatibility.Callbacks();
+ method protected boolean isChangeEnabled(long);
+ method protected void reportChange(long);
+ }
+
+}
+
+package android.compat.annotation {
+
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.PARAMETER}) public @interface ChangeId {
+ }
+
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD}) public @interface Disabled {
+ }
+
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD}) public @interface EnabledAfter {
+ method public abstract int targetSdkVersion();
+ }
+
+}
+
package android.icu.impl {
public class CalendarAstronomer {
@@ -86,6 +116,7 @@
public final class OsConstants {
method @dalvik.annotation.compat.UnsupportedAppUsage public static int CAP_TO_INDEX(int);
method @dalvik.annotation.compat.UnsupportedAppUsage public static int CAP_TO_MASK(int);
+ field @dalvik.annotation.compat.UnsupportedAppUsage public static final int ARPHRD_LOOPBACK;
field @dalvik.annotation.compat.UnsupportedAppUsage public static final int ENONET;
field @dalvik.annotation.compat.UnsupportedAppUsage public static final int EUSERS;
field @dalvik.annotation.compat.UnsupportedAppUsage public static final int MAP_POPULATE;
@@ -105,8 +136,7 @@
}
public final class PacketSocketAddress extends java.net.SocketAddress {
- ctor @dalvik.annotation.compat.UnsupportedAppUsage public PacketSocketAddress(short, int);
- ctor @dalvik.annotation.compat.UnsupportedAppUsage public PacketSocketAddress(int, byte[]);
+ ctor public PacketSocketAddress(int, int, byte[]);
}
public final class StructCapUserData {
@@ -804,7 +834,7 @@
method public static void setProcessDataDirectory(String);
method public static void setProcessPackageName(String);
method @dalvik.annotation.compat.UnsupportedAppUsage public float setTargetHeapUtilization(float);
- method public void setTargetSdkVersion(int);
+ method @dalvik.annotation.compat.UnsupportedAppUsage(maxTargetSdk=0, publicAlternatives="Use the {@code targetSdkVersion}" + " attribute in the {@code uses-sdk} manifest tag instead.") public void setTargetSdkVersion(int);
method public void startJitCompilation();
method public void updateProcessState(int);
method @dalvik.annotation.compat.UnsupportedAppUsage public String vmInstructionSet();
diff --git a/mmodules/intracoreapi/api/intra/current-api.txt b/mmodules/intracoreapi/api/intra/current-api.txt
index 4250d3f..4eeebc2 100644
--- a/mmodules/intracoreapi/api/intra/current-api.txt
+++ b/mmodules/intracoreapi/api/intra/current-api.txt
@@ -1,4 +1,27 @@
// Signature format: 2.0
+package android.compat {
+
+ @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public final class Compatibility {
+ method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static boolean isChangeEnabled(@android.compat.annotation.ChangeId long);
+ method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public static void reportChange(@android.compat.annotation.ChangeId long);
+ }
+
+}
+
+package android.compat.annotation {
+
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.PARAMETER}) @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public @interface ChangeId {
+ }
+
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD}) @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public @interface Disabled {
+ }
+
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD}) @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public @interface EnabledAfter {
+ method @libcore.api.CorePlatformApi @libcore.api.IntraCoreApi public abstract int targetSdkVersion();
+ }
+
+}
+
package com.android.org.conscrypt {
@libcore.api.IntraCoreApi public class DESEDESecretKeyFactory extends javax.crypto.SecretKeyFactorySpi {
diff --git a/non_openjdk_java_files.bp b/non_openjdk_java_files.bp
index 1952687..caf3c99 100644
--- a/non_openjdk_java_files.bp
+++ b/non_openjdk_java_files.bp
@@ -1,8 +1,13 @@
filegroup {
name: "non_openjdk_javadoc_files",
srcs: [
+ "luni/src/main/java/android/compat/annotation/ChangeId.java",
+ "luni/src/main/java/android/compat/annotation/Disabled.java",
+ "luni/src/main/java/android/compat/annotation/EnabledAfter.java",
+ "luni/src/main/java/android/compat/Compatibility.java",
"luni/src/main/java/android/system/ErrnoException.java",
"luni/src/main/java/android/system/GaiException.java",
+ "luni/src/main/java/android/system/IcmpHeaders.java",
"luni/src/main/java/android/system/Int32Ref.java",
"luni/src/main/java/android/system/Int64Ref.java",
"luni/src/main/java/android/system/NetlinkSocketAddress.java",
@@ -12,9 +17,7 @@
"luni/src/main/java/android/system/StructAddrinfo.java",
"luni/src/main/java/android/system/StructCapUserData.java",
"luni/src/main/java/android/system/StructCapUserHeader.java",
- "luni/src/main/java/android/system/StructFlock.java",
"luni/src/main/java/android/system/StructGroupReq.java",
- "luni/src/main/java/android/system/StructIcmpHdr.java",
"luni/src/main/java/android/system/StructIfaddrs.java",
"luni/src/main/java/android/system/StructLinger.java",
"luni/src/main/java/android/system/StructPasswd.java",
diff --git a/ojluni/src/main/java/java/lang/Math.java b/ojluni/src/main/java/java/lang/Math.java
index bb84b81..17cbf6d 100644
--- a/ojluni/src/main/java/java/lang/Math.java
+++ b/ojluni/src/main/java/java/lang/Math.java
@@ -31,6 +31,10 @@
import sun.misc.FloatConsts;
import sun.misc.DoubleConsts;
+// Android-note: Document that the results from Math are based on libm's behavior.
+// For performance, Android implements many of the methods in this class in terms of the underlying
+// OS's libm functions. libm has well-defined behavior for special cases. Where known these are
+// marked with the tag above and the documentation has been modified as needed.
/**
* The class {@code Math} contains methods for performing basic
* numeric operations such as the elementary exponential, logarithm,
@@ -502,6 +506,11 @@
@CriticalNative
public static native double atan2(double y, double x);
+ // Android-changed: Document that the results from Math are based on libm's behavior.
+ // The cases known to differ with libm's pow():
+ // If the first argument is 1.0 then result is always 1.0 (not NaN).
+ // If the first argument is -1.0 and the second argument is infinite, the result is 1.0 (not
+ // NaN).
/**
* Returns the value of the first argument raised to the power of the
* second argument. Special cases:
@@ -510,7 +519,9 @@
* result is 1.0.
* <li>If the second argument is 1.0, then the result is the same as the
* first argument.
- * <li>If the second argument is NaN, then the result is NaN.
+ * <li>If the first argument is 1.0, then the result is 1.0.
+ * <li>If the second argument is NaN, then the result is NaN except where the first argument is
+ * 1.0.
* <li>If the first argument is NaN and the second argument is nonzero,
* then the result is NaN.
*
@@ -534,7 +545,7 @@
* then the result is positive zero.
*
* <li>If the absolute value of the first argument equals 1 and the
- * second argument is infinite, then the result is NaN.
+ * second argument is infinite, then the result is 1.0.
*
* <li>If
* <ul>
diff --git a/ojluni/src/main/java/java/net/Inet6AddressImpl.java b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
index bb722f3..29ccda2 100644
--- a/ojluni/src/main/java/java/net/Inet6AddressImpl.java
+++ b/ojluni/src/main/java/java/net/Inet6AddressImpl.java
@@ -27,7 +27,7 @@
import android.system.ErrnoException;
import android.system.GaiException;
import android.system.StructAddrinfo;
-import android.system.StructIcmpHdr;
+import android.system.IcmpHeaders;
import dalvik.system.BlockGuard;
@@ -263,7 +263,7 @@
IoBridge.setSocketOption(fd, SocketOptions.SO_TIMEOUT, sockTo);
- packet = StructIcmpHdr.IcmpEchoHdr(isIPv4, seq).getBytes();
+ packet = IcmpHeaders.createIcmpEchoHdr(isIPv4, seq);
IoBridge.sendto(fd, packet, 0, packet.length, 0, addr, 0);
final int icmpId = IoBridge.getLocalInetSocketAddress(fd).getPort();
diff --git a/openjdk_java_files.bp b/openjdk_java_files.bp
index 819c8ff..9480570 100644
--- a/openjdk_java_files.bp
+++ b/openjdk_java_files.bp
@@ -1828,7 +1828,7 @@
name: "openjdk-sdk-stubs-no-javadoc",
srcs: [":openjdk_javadoc_files"],
installable: false,
- sdk_version: "core_platform",
+ sdk_version: "none",
args: "--exclude-documentation-from-stubs",
}
@@ -1843,7 +1843,7 @@
":openjdk_mmodule_extra_files",
],
installable: false,
- sdk_version: "core_platform",
+ sdk_version: "none",
args: "--exclude-documentation-from-stubs " +
"--hide-annotation libcore.api.Hide ",
merge_inclusion_annotations_dirs: ["ojluni-annotated-mmodule-stubs"],