am a553773d: Improve backward compatibility of plurals formatting.
* commit 'a553773d208f874df5f94a79eec1e3a9d3fa3407':
Improve backward compatibility of plurals formatting.
diff --git a/NOTICE b/NOTICE
index 951e506..5136b4b 100644
--- a/NOTICE
+++ b/NOTICE
@@ -104,3 +104,14 @@
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See W3C License http://www.w3.org/Consortium/Legal/ for more details.
+
+ =========================================================================
+ == NOTICE file for the fdlibm License. ==
+ =========================================================================
+
+Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+
+Developed at SunSoft, a Sun Microsystems, Inc. business.
+Permission to use, copy, modify, and distribute this
+software is freely granted, provided that this notice
+is preserved.
diff --git a/NativeCode.mk b/NativeCode.mk
index 0ae615e..c06431f 100644
--- a/NativeCode.mk
+++ b/NativeCode.mk
@@ -87,7 +87,7 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libjavacore
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
-include external/stlport/libstlport.mk
+LOCAL_CXX_STL := libc++
include $(BUILD_SHARED_LIBRARY)
# Test JNI library.
@@ -102,7 +102,7 @@
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libjavacoretests
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
-include external/stlport/libstlport.mk
+LOCAL_CXX_STL := libc++
include $(BUILD_SHARED_LIBRARY)
endif # LIBCORE_SKIP_TESTS
@@ -128,6 +128,7 @@
LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libexpat-host libicuuc-host libicui18n-host libcrypto-host libz-host
LOCAL_STATIC_LIBRARIES += $(core_static_libraries) libziparchive-host libutils
LOCAL_MULTILIB := both
+LOCAL_CXX_STL := libc++
include $(BUILD_HOST_SHARED_LIBRARY)
ifeq ($(LIBCORE_SKIP_TESTS),)
@@ -142,5 +143,6 @@
LOCAL_MODULE := libjavacoretests
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
LOCAL_SHARED_LIBRARIES := libcrypto-host
+ LOCAL_CXX_STL := libc++
include $(BUILD_HOST_SHARED_LIBRARY)
endif # LIBCORE_SKIP_TESTS
diff --git a/dalvik/src/main/java/dalvik/system/ZygoteHooks.java b/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
index 11ea286..59d8820 100644
--- a/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
+++ b/dalvik/src/main/java/dalvik/system/ZygoteHooks.java
@@ -29,7 +29,7 @@
/**
* Called by the zygote prior to every fork. Each call to {@code preFork}
- * is followed by a matching call to {@link #postForkChild(int)} on the child
+ * is followed by a matching call to {@link #postForkChild(int, String)} on the child
* process and {@link #postForkCommon()} on both the parent and the child
* process. {@code postForkCommon} is called after {@code postForkChild} in
* the child process.
@@ -47,6 +47,8 @@
*/
public void postForkChild(int debugFlags, String instructionSet) {
nativePostForkChild(token, debugFlags, instructionSet);
+
+ Math.setRandomSeedInternal(System.currentTimeMillis());
}
/**
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index c5524b6..622d401 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -1419,14 +1419,6 @@
name: "com.android.org.apache.harmony.logging.tests.java.util.logging.LevelTest#testSerializationCompatibility"
},
{
- description: "java.util.logging: Tests that require java.util.logging code changes to fix.",
- bug: 13882147,
- names: [
- "com.android.org.apache.harmony.logging.tests.java.util.logging.SocketHandlerTest#testConstructor_NoProperties",
- "com.android.org.apache.harmony.logging.tests.java.util.logging.XMLFormatterTest#test_TestFileHandlerClass_constructor"
- ]
-},
-{
description: "java.util.beans: the harmony tests were broken by Android commit 19a270e90b1e992c1f6639f355ae13564c2f3a6a",
bug: 17394106,
names: [
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/EnumMapTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/EnumMapTest.java
index 2a37a18..676e373 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/EnumMapTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/EnumMapTest.java
@@ -233,6 +233,17 @@
}
}
+ @SuppressWarnings("unchecked")
+ public void testConstructor_badMapArg() {
+ HashMap badMap = new HashMap();
+ badMap.put("NotAnEnum", "Value");
+ try {
+ new EnumMap<Color, String>(badMap);
+ fail();
+ } catch (ClassCastException expected) {
+ }
+ }
+
/**
* java.util.EnumMap#clear()
*/
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index 43fa00e..f778af0 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -33,6 +33,10 @@
*/
private static final VMRuntime THE_ONE = new VMRuntime();
+ // Note: Instruction set names are used to construct the names of some
+ // system properties. To be sure that the properties stay valid the
+ // instruction set name should not exceed 7 characters. See installd
+ // and the package manager for the actual propeties.
private static final Map<String, String> ABI_TO_INSTRUCTION_SET_MAP
= new HashMap<String, String>();
static {
diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java
index 3ac359b..a833f6c 100644
--- a/libart/src/main/java/java/lang/Class.java
+++ b/libart/src/main/java/java/lang/Class.java
@@ -230,15 +230,15 @@
*/
private transient int objectSize;
- /** Primitive type value, or 0 if not a primitive type; set for generated primitive classes. */
+ /**
+ * The lower 16 bits is the primitive type value, or 0 if not a primitive type; set for
+ * generated primitive classes.
+ */
private transient int primitiveType;
/** Bitmap of offsets of iFields. */
private transient int referenceInstanceOffsets;
- /** Bitmap of offsets of sFields. */
- private transient int referenceStaticOffsets;
-
/** State of class initialization */
private transient int status;
@@ -1545,7 +1545,7 @@
* Tests whether this {@code Class} represents a primitive type.
*/
public boolean isPrimitive() {
- return primitiveType != 0;
+ return (primitiveType & 0xFFFF) != 0;
}
/**
diff --git a/libart/src/main/java/java/lang/Daemons.java b/libart/src/main/java/java/lang/Daemons.java
index 6b3344c..4f8285c 100644
--- a/libart/src/main/java/java/lang/Daemons.java
+++ b/libart/src/main/java/java/lang/Daemons.java
@@ -143,20 +143,14 @@
}
private void enqueue(Reference<?> list) {
- while (list != null) {
- Reference<?> reference;
- // pendingNext is owned by the GC so no synchronization is required
- if (list == list.pendingNext) {
- reference = list;
- reference.pendingNext = null;
- list = null;
- } else {
- reference = list.pendingNext;
- list.pendingNext = reference.pendingNext;
- reference.pendingNext = null;
- }
- reference.enqueueInternal();
- }
+ Reference<?> start = list;
+ do {
+ // pendingNext is owned by the GC so no synchronization is required.
+ Reference<?> next = list.pendingNext;
+ list.pendingNext = null;
+ list.enqueueInternal();
+ list = next;
+ } while (list != start);
}
}
diff --git a/luni/src/main/java/java/io/File.java b/luni/src/main/java/java/io/File.java
index d107c28..a07d34c 100644
--- a/luni/src/main/java/java/io/File.java
+++ b/luni/src/main/java/java/io/File.java
@@ -57,12 +57,6 @@
private static final long serialVersionUID = 301077366599181567L;
/**
- * Reusing a Random makes temporary filenames slightly harder to predict.
- * (Random is thread-safe.)
- */
- private static final Random tempFileRandom = new Random();
-
- /**
* The system-dependent character used to separate components in filenames ('/').
* Use of this (rather than hard-coding '/') helps portability to other operating systems.
*
@@ -1002,7 +996,7 @@
}
File result;
do {
- result = new File(tmpDirFile, prefix + tempFileRandom.nextInt() + suffix);
+ result = new File(tmpDirFile, prefix + Math.randomIntInternal() + suffix);
} while (!result.createNewFile());
return result;
}
diff --git a/luni/src/main/java/java/io/ObjectStreamField.java b/luni/src/main/java/java/io/ObjectStreamField.java
index 78a6903..2a9b107 100644
--- a/luni/src/main/java/java/io/ObjectStreamField.java
+++ b/luni/src/main/java/java/io/ObjectStreamField.java
@@ -58,13 +58,7 @@
* if {@code name} or {@code cl} is {@code null}.
*/
public ObjectStreamField(String name, Class<?> cl) {
- if (name == null) {
- throw new NullPointerException("name == null");
- } else if (cl == null) {
- throw new NullPointerException("cl == null");
- }
- this.name = name;
- this.type = new WeakReference<Class<?>>(cl);
+ this(name, cl, false);
}
/**
diff --git a/luni/src/main/java/java/lang/Math.java b/luni/src/main/java/java/lang/Math.java
index 86df784..a738511 100644
--- a/luni/src/main/java/java/lang/Math.java
+++ b/luni/src/main/java/java/lang/Math.java
@@ -35,7 +35,7 @@
*/
public static final double PI = 3.141592653589793;
- private static Random random;
+ private static final Random INSTANCE = new Random();
/**
* Prevents this class from being instantiated.
@@ -875,11 +875,25 @@
*
* @return a pseudo-random number.
*/
- public static synchronized double random() {
- if (random == null) {
- random = new Random();
- }
- return random.nextDouble();
+ public static double random() {
+ return INSTANCE.nextDouble();
+ }
+
+ /**
+ * Set the seed for the pseudo random generator used by {@link #random()}
+ * and {@link #randomIntInternal()}.
+ *
+ * @hide for internal use only.
+ */
+ public static void setRandomSeedInternal(long seed) {
+ INSTANCE.setSeed(seed);
+ }
+
+ /**
+ * @hide for internal use only.
+ */
+ public static int randomIntInternal() {
+ return INSTANCE.nextInt();
}
/**
diff --git a/luni/src/main/java/java/lang/StrictMath.java b/luni/src/main/java/java/lang/StrictMath.java
index f409c06..2e848f2 100644
--- a/luni/src/main/java/java/lang/StrictMath.java
+++ b/luni/src/main/java/java/lang/StrictMath.java
@@ -15,6 +15,18 @@
* limitations under the License.
*/
+/*
+ * acos, asin, atan, cosh, sinh, tanh, exp, expm1, log, log10, log1p, and cbrt
+ * have been implemented with the following license.
+ * ====================================================
+ * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
package java.lang;
/**
@@ -102,6 +114,21 @@
return Math.abs(l);
}
+ private static final double PIO2_HI = 1.57079632679489655800e+00;
+ private static final double PIO2_LO = 6.12323399573676603587e-17;
+ private static final double PS0 = 1.66666666666666657415e-01;
+ private static final double PS1 = -3.25565818622400915405e-01;
+ private static final double PS2 = 2.01212532134862925881e-01;
+ private static final double PS3 = -4.00555345006794114027e-02;
+ private static final double PS4 = 7.91534994289814532176e-04;
+ private static final double PS5 = 3.47933107596021167570e-05;
+ private static final double QS1 = -2.40339491173441421878e+00;
+ private static final double QS2 = 2.02094576023350569471e+00;
+ private static final double QS3 = -6.88283971605453293030e-01;
+ private static final double QS4 = 7.70381505559019352791e-02;
+ private static final double HUGE = 1.000e+300;
+ private static final double PIO4_HI = 7.85398163397448278999e-01;
+
/**
* Returns the closest double approximation of the arc cosine of the
* argument within the range {@code [0..pi]}.
@@ -113,11 +140,62 @@
* <li>{@code acos(NaN) = NaN}</li>
* </ul>
*
- * @param d
+ * @param x
* the value to compute arc cosine of.
* @return the arc cosine of the argument.
*/
- public static native double acos(double d);
+ public static double acos(double x) {
+ double z, p, q, r, w, s, c, df;
+ int hx, ix;
+ final long bits = Double.doubleToRawLongBits(x);
+ hx = (int) (bits >>> 32);
+ ix = hx & 0x7fffffff;
+ if (ix >= 0x3ff00000) { /* |x| >= 1 */
+ if ((((ix - 0x3ff00000) | ((int) bits))) == 0) { /* |x|==1 */
+ if (hx > 0) {
+ return 0.0; /* ieee_acos(1) = 0 */
+ } else {
+ return 3.14159265358979311600e+00 + 2.0 * PIO2_LO; /* ieee_acos(-1)= pi */
+ }
+ }
+ return (x - x) / (x - x); /* ieee_acos(|x|>1) is NaN */
+ }
+
+ if (ix < 0x3fe00000) { /* |x| < 0.5 */
+ if (ix <= 0x3c600000) {
+ return PIO2_HI + PIO2_LO;/* if|x|<2**-57 */
+ }
+
+ z = x * x;
+ p = z * (PS0 + z
+ * (PS1 + z * (PS2 + z * (PS3 + z * (PS4 + z * PS5)))));
+ q = 1.00000000000000000000e+00 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4)));
+ r = p / q;
+ return PIO2_HI - (x - (PIO2_LO - x * r));
+ } else if (hx < 0) { /* x < -0.5 */
+ z = (1.00000000000000000000e+00 + x) * 0.5;
+ p = z * (PS0 + z
+ * (PS1 + z * (PS2 + z * (PS3 + z * (PS4 + z * PS5)))));
+ q = 1.00000000000000000000e+00 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4)));
+ s = StrictMath.sqrt(z);
+ r = p / q;
+ w = r * s - PIO2_LO;
+ return 3.14159265358979311600e+00 - 2.0 * (s + w);
+ } else { /* x > 0.5 */
+ z = (1.00000000000000000000e+00 - x) * 0.5;
+ s = StrictMath.sqrt(z);
+ df = s;
+ df = Double.longBitsToDouble(
+ Double.doubleToRawLongBits(df) & 0xffffffffL << 32);
+ c = (z - df * df) / (s + df);
+ p = z * (PS0 + z
+ * (PS1 + z * (PS2 + z * (PS3 + z * (PS4 + z * PS5)))));
+ q = 1.00000000000000000000e+00 + z * (QS1 + z * (QS2 + z * (QS3 + z * QS4)));
+ r = p / q;
+ w = r * s + c;
+ return 2.0 * (df + w);
+ }
+ }
/**
* Returns the closest double approximation of the arc sine of the argument
@@ -130,11 +208,75 @@
* <li>{@code asin(NaN) = NaN}</li>
* </ul>
*
- * @param d
+ * @param x
* the value whose arc sine has to be computed.
* @return the arc sine of the argument.
*/
- public static native double asin(double d);
+ public static double asin(double x) {
+ double t, w, p, q, c, r, s;
+ int hx, ix;
+ final long bits = Double.doubleToRawLongBits(x);
+ hx = (int) (bits >>> 32);
+ ix = hx & 0x7fffffff;
+ if (ix >= 0x3ff00000) { /* |x|>= 1 */
+ if ((((ix - 0x3ff00000) | ((int) bits))) == 0) {
+ /* ieee_asin(1)=+-pi/2 with inexact */
+ return x * PIO2_HI + x * PIO2_LO;
+ }
+ return (x - x) / (x - x); /* ieee_asin(|x|>1) is NaN */
+ } else if (ix < 0x3fe00000) { /* |x|<0.5 */
+ if (ix < 0x3e400000) { /* if |x| < 2**-27 */
+ if (HUGE + x > 1.00000000000000000000e+00) {
+ return x;/* return x with inexact if x!=0 */
+ }
+ } else {
+ t = x * x;
+ p = t * (PS0 + t
+ * (PS1 + t * (PS2 + t * (PS3 + t * (PS4 + t * PS5)))));
+ q = 1.00000000000000000000e+00 + t * (QS1 + t * (QS2 + t * (QS3 + t * QS4)));
+ w = p / q;
+ return x + x * w;
+ }
+ }
+ /* 1> |x|>= 0.5 */
+ w = 1.00000000000000000000e+00 - Math.abs(x);
+ t = w * 0.5;
+ p = t * (PS0 + t * (PS1 + t * (PS2 + t * (PS3 + t * (PS4 + t * PS5)))));
+ q = 1.00000000000000000000e+00 + t * (QS1 + t * (QS2 + t * (QS3 + t * QS4)));
+ s = StrictMath.sqrt(t);
+ if (ix >= 0x3FEF3333) { /* if |x| > 0.975 */
+ w = p / q;
+ t = PIO2_HI - (2.0 * (s + s * w) - PIO2_LO);
+ } else {
+ w = s;
+ w = Double.longBitsToDouble(
+ Double.doubleToRawLongBits(w) & 0xffffffffL << 32);
+ c = (t - w * w) / (s + w);
+ r = p / q;
+ p = 2.0 * s * r - (PIO2_LO - 2.0 * c);
+ q = PIO4_HI - 2.0 * w;
+ t = PIO4_HI - (p - q);
+ }
+ return (hx > 0) ? t : -t;
+ }
+
+ private static final double[] ATANHI = { 4.63647609000806093515e-01,
+ 7.85398163397448278999e-01, 9.82793723247329054082e-01,
+ 1.57079632679489655800e+00 };
+ private static final double[] ATANLO = { 2.26987774529616870924e-17,
+ 3.06161699786838301793e-17, 1.39033110312309984516e-17,
+ 6.12323399573676603587e-17 };
+ private static final double AT0 = 3.33333333333329318027e-01;
+ private static final double AT1 = -1.99999999998764832476e-01;
+ private static final double AT2 = 1.42857142725034663711e-01;
+ private static final double AT3 = -1.11111104054623557880e-01;
+ private static final double AT4 = 9.09088713343650656196e-02;
+ private static final double AT5 = -7.69187620504482999495e-02;
+ private static final double AT6 = 6.66107313738753120669e-02;
+ private static final double AT7= -5.83357013379057348645e-02;
+ private static final double AT8 = 4.97687799461593236017e-02;
+ private static final double AT9 = -3.65315727442169155270e-02;
+ private static final double AT10 = 1.62858201153657823623e-02;
/**
* Returns the closest double approximation of the arc tangent of the
@@ -149,11 +291,73 @@
* <li>{@code atan(NaN) = NaN}</li>
* </ul>
*
- * @param d
+ * @param x
* the value whose arc tangent has to be computed.
* @return the arc tangent of the argument.
*/
- public static native double atan(double d);
+ public static double atan(double x) {
+ double w, s1, s2, z;
+ int ix, hx, id;
+
+ final long bits = Double.doubleToRawLongBits(x);
+ hx = (int) (bits >>> 32);
+ ix = hx & 0x7fffffff;
+ if (ix >= 0x44100000) { /* if |x| >= 2^66 */
+ if (ix > 0x7ff00000 || (ix == 0x7ff00000 && (((int) bits) != 0))) {
+ return x + x; /* NaN */
+ }
+ if (hx > 0) {
+ return ATANHI[3] + ATANLO[3];
+ } else {
+ return -ATANHI[3] - ATANLO[3];
+ }
+ }
+ if (ix < 0x3fdc0000) { /* |x| < 0.4375 */
+ if (ix < 0x3e200000) { /* |x| < 2^-29 */
+ if (HUGE + x > 1.00000000000000000000e+00) {
+ return x; /* raise inexact */
+ }
+ }
+ id = -1;
+ } else {
+ x = Math.abs(x);
+ if (ix < 0x3ff30000) { /* |x| < 1.1875 */
+ if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */
+ id = 0;
+ x = (2.0 * x - 1.00000000000000000000e+00) / (2.0 + x);
+ } else { /* 11/16<=|x|< 19/16 */
+ id = 1;
+ x = (x - 1.00000000000000000000e+00) / (x + 1.00000000000000000000e+00);
+ }
+ } else {
+ if (ix < 0x40038000) { /* |x| < 2.4375 */
+ id = 2;
+ x = (x - 1.5) / (1.00000000000000000000e+00 + 1.5 * x);
+ } else { /* 2.4375 <= |x| < 2^66 */
+ id = 3;
+ x = -1.0 / x;
+ }
+ }
+ }
+
+ /* end of argument reduction */
+ z = x * x;
+ w = z * z;
+ /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
+ s1 = z * (AT0 + w * (AT2 + w
+ * (AT4 + w * (AT6 + w * (AT8 + w * AT10)))));
+ s2 = w * (AT1 + w * (AT3 + w * (AT5 + w * (AT7 + w * AT9))));
+ if (id < 0) {
+ return x - x * (s1 + s2);
+ } else {
+ z = ATANHI[id] - ((x * (s1 + s2) - ATANLO[id]) - x);
+ return (hx < 0) ? -z : z;
+ }
+ }
+
+ private static final double PI_O_4 = 7.8539816339744827900E-01;
+ private static final double PI_O_2 = 1.5707963267948965580E+00;
+ private static final double PI_LO = 1.2246467991473531772E-16;
/**
* Returns the closest double approximation of the arc tangent of
@@ -192,7 +396,108 @@
* the denominator of the value whose atan has to be computed.
* @return the arc tangent of {@code y/x}.
*/
- public static native double atan2(double y, double x);
+ public static double atan2(double y, double x) {
+ double z;
+ int k, m, hx, hy, ix, iy;
+ int lx, ly; // watch out, should be unsigned
+
+ final long yBits = Double.doubleToRawLongBits(y);
+ final long xBits = Double.doubleToRawLongBits(x);
+
+ hx = (int) (xBits >>> 32); // __HI(x);
+ ix = hx & 0x7fffffff;
+ lx = (int) xBits; // __LO(x);
+ hy = (int) (yBits >>> 32); // __HI(y);
+ iy = hy & 0x7fffffff;
+ ly = (int) yBits; // __LO(y);
+ if (((ix | ((lx | -lx) >> 31)) > 0x7ff00000)
+ || ((iy | ((ly | -ly) >> 31)) > 0x7ff00000)) { /* x or y is NaN */
+ return x + y;
+ }
+ if ((hx - 0x3ff00000 | lx) == 0) {
+ return StrictMath.atan(y); /* x=1.0 */
+ }
+
+ m = ((hy >> 31) & 1) | ((hx >> 30) & 2); /* 2*sign(x)+sign(y) */
+
+ /* when y = 0 */
+ if ((iy | ly) == 0) {
+ switch (m) {
+ case 0:
+ case 1:
+ return y; /* ieee_atan(+-0,+anything)=+-0 */
+ case 2:
+ return 3.14159265358979311600e+00 + TINY;/* ieee_atan(+0,-anything) = pi */
+ case 3:
+ return -3.14159265358979311600e+00 - TINY;/* ieee_atan(-0,-anything) =-pi */
+ }
+ }
+ /* when x = 0 */
+ if ((ix | lx) == 0)
+ return (hy < 0) ? -PI_O_2 - TINY : PI_O_2 + TINY;
+
+ /* when x is INF */
+ if (ix == 0x7ff00000) {
+ if (iy == 0x7ff00000) {
+ switch (m) {
+ case 0:
+ return PI_O_4 + TINY;/* ieee_atan(+INF,+INF) */
+ case 1:
+ return -PI_O_4 - TINY;/* ieee_atan(-INF,+INF) */
+ case 2:
+ return 3.0 * PI_O_4 + TINY;/* ieee_atan(+INF,-INF) */
+ case 3:
+ return -3.0 * PI_O_4 - TINY;/* ieee_atan(-INF,-INF) */
+ }
+ } else {
+ switch (m) {
+ case 0:
+ return 0.0; /* ieee_atan(+...,+INF) */
+ case 1:
+ return -0.0; /* ieee_atan(-...,+INF) */
+ case 2:
+ return 3.14159265358979311600e+00 + TINY; /* ieee_atan(+...,-INF) */
+ case 3:
+ return -3.14159265358979311600e+00 - TINY; /* ieee_atan(-...,-INF) */
+ }
+ }
+ }
+ /* when y is INF */
+ if (iy == 0x7ff00000)
+ return (hy < 0) ? -PI_O_2 - TINY : PI_O_2 + TINY;
+
+ /* compute y/x */
+ k = (iy - ix) >> 20;
+ if (k > 60) {
+ z = PI_O_2 + 0.5 * PI_LO; /* |y/x| > 2**60 */
+ } else if (hx < 0 && k < -60) {
+ z = 0.0; /* |y|/x < -2**60 */
+ } else {
+ z = StrictMath.atan(Math.abs(y / x)); /* safe to do y/x */
+ }
+
+ switch (m) {
+ case 0:
+ return z; /* ieee_atan(+,+) */
+ case 1:
+ // __HI(z) ^= 0x80000000;
+ z = Double.longBitsToDouble(
+ Double.doubleToRawLongBits(z) ^ (0x80000000L << 32));
+ return z; /* ieee_atan(-,+) */
+ case 2:
+ return 3.14159265358979311600e+00 - (z - PI_LO);/* ieee_atan(+,-) */
+ default: /* case 3 */
+ return (z - PI_LO) - 3.14159265358979311600e+00;/* ieee_atan(-,-) */
+ }
+ }
+
+ private static final int B1 = 715094163;
+ private static final int B2 = 696219795;
+ private static final double C = 5.42857142857142815906e-01;
+ private static final double D = -7.05306122448979611050e-01;
+ private static final double CBRTE = 1.41428571428571436819e+00;
+ private static final double F = 1.60714285714285720630e+00;
+ private static final double G = 3.57142857142857150787e-01;
/**
* Returns the closest double approximation of the cube root of the
@@ -207,11 +512,79 @@
* <li>{@code cbrt(NaN) = NaN}</li>
* </ul>
*
- * @param d
+ * @param x
* the value whose cube root has to be computed.
* @return the cube root of the argument.
*/
- public static native double cbrt(double d);
+ public static double cbrt(double x) {
+ if (x < 0) {
+ return -cbrt(-x);
+ }
+ int hx;
+ double r, s, w;
+ int sign; // caution: should be unsigned
+ long bits = Double.doubleToRawLongBits(x);
+
+ hx = (int) (bits >>> 32);
+ sign = hx & 0x80000000; /* sign= sign(x) */
+ hx ^= sign;
+ if (hx >= 0x7ff00000) {
+ return (x + x); /* ieee_cbrt(NaN,INF) is itself */
+ }
+
+ if ((hx | ((int) bits)) == 0) {
+ return x; /* ieee_cbrt(0) is itself */
+ }
+
+ // __HI(x) = hx; /* x <- |x| */
+ bits &= 0x00000000ffffffffL;
+ bits |= ((long) hx << 32);
+
+ long tBits = Double.doubleToRawLongBits(0.0) & 0x00000000ffffffffL;
+ double t = 0.0;
+ /* rough cbrt to 5 bits */
+ if (hx < 0x00100000) { /* subnormal number */
+ // __HI(t)=0x43500000; /*set t= 2**54*/
+ tBits |= 0x43500000L << 32;
+ t = Double.longBitsToDouble(tBits);
+ t *= x;
+
+ // __HI(t)=__HI(t)/3+B2;
+ tBits = Double.doubleToRawLongBits(t);
+ long tBitsHigh = tBits >> 32;
+ tBits &= 0x00000000ffffffffL;
+ tBits |= ((tBitsHigh / 3) + B2) << 32;
+ t = Double.longBitsToDouble(tBits);
+
+ } else {
+ // __HI(t)=hx/3+B1;
+ tBits |= ((long) ((hx / 3) + B1)) << 32;
+ t = Double.longBitsToDouble(tBits);
+ }
+
+ /* new cbrt to 23 bits, may be implemented in single precision */
+ r = t * t / x;
+ s = C + r * t;
+ t *= G + F / (s + CBRTE + D / s);
+
+ /* chopped to 20 bits and make it larger than ieee_cbrt(x) */
+ tBits = Double.doubleToRawLongBits(t);
+ tBits &= 0xFFFFFFFFL << 32;
+ tBits += 0x00000001L << 32;
+ t = Double.longBitsToDouble(tBits);
+
+ /* one step newton iteration to 53 bits with error less than 0.667 ulps */
+ s = t * t; /* t*t is exact */
+ r = x / s;
+ w = t + t;
+ r = (r - t) / (w + r); /* r-s is exact */
+ t = t + t * r;
+
+ /* retore the sign bit */
+ tBits = Double.doubleToRawLongBits(t);
+ tBits |= ((long) sign) << 32;
+ return Double.longBitsToDouble(tBits);
+ }
/**
* Returns the double conversion of the most negative (closest to negative
@@ -229,6 +602,8 @@
*/
public static native double ceil(double d);
+ private static final long ONEBITS = Double.doubleToRawLongBits(1.00000000000000000000e+00)
+ & 0x00000000ffffffffL;
/**
* Returns the closest double approximation of the hyperbolic cosine of the
@@ -241,11 +616,54 @@
* <li>{@code cosh(NaN) = NaN}</li>
* </ul>
*
- * @param d
+ * @param x
* the value whose hyperbolic cosine has to be computed.
* @return the hyperbolic cosine of the argument.
*/
- public static native double cosh(double d);
+ public static double cosh(double x) {
+ double t, w;
+ int ix;
+ final long bits = Double.doubleToRawLongBits(x);
+ ix = (int) (bits >>> 32) & 0x7fffffff;
+
+ /* x is INF or NaN */
+ if (ix >= 0x7ff00000) {
+ return x * x;
+ }
+
+ /* |x| in [0,0.5*ln2], return 1+ieee_expm1(|x|)^2/(2*ieee_exp(|x|)) */
+ if (ix < 0x3fd62e43) {
+ t = expm1(Math.abs(x));
+ w = 1.00000000000000000000e+00 + t;
+ if (ix < 0x3c800000)
+ return w; /* ieee_cosh(tiny) = 1 */
+ return 1.00000000000000000000e+00 + (t * t) / (w + w);
+ }
+
+ /* |x| in [0.5*ln2,22], return (ieee_exp(|x|)+1/ieee_exp(|x|)/2; */
+ if (ix < 0x40360000) {
+ t = exp(Math.abs(x));
+ return 0.5 * t + 0.5 / t;
+ }
+
+ /* |x| in [22, ieee_log(maxdouble)] return half*ieee_exp(|x|) */
+ if (ix < 0x40862E42) {
+ return 0.5 * exp(Math.abs(x));
+ }
+
+ /* |x| in [log(maxdouble), overflowthresold] */
+ final long lx = ((ONEBITS >>> 29) + ((int) bits)) & 0x00000000ffffffffL;
+ // watch out: lx should be an unsigned int
+ // lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x);
+ if (ix < 0x408633CE || (ix == 0x408633ce) && (lx <= 0x8fb9f87dL)) {
+ w = exp(0.5 * Math.abs(x));
+ t = 0.5 * w;
+ return t * w;
+ }
+
+ /* |x| > overflowthresold, ieee_cosh(x) overflow */
+ return HUGE * HUGE;
+ }
/**
* Returns the closest double approximation of the cosine of the argument.
@@ -263,6 +681,19 @@
*/
public static native double cos(double d);
+ private static final double TWON24 = 5.96046447753906250000e-08;
+ private static final double TWO54 = 1.80143985094819840000e+16,
+ TWOM54 = 5.55111512312578270212e-17;
+ private static final double TWOM1000 = 9.33263618503218878990e-302;
+ private static final double O_THRESHOLD = 7.09782712893383973096e+02;
+ private static final double U_THRESHOLD = -7.45133219101941108420e+02;
+ private static final double INVLN2 = 1.44269504088896338700e+00;
+ private static final double P1 = 1.66666666666666019037e-01;
+ private static final double P2 = -2.77777777770155933842e-03;
+ private static final double P3 = 6.61375632143793436117e-05;
+ private static final double P4 = -1.65339022054652515390e-06;
+ private static final double P5 = 4.13813679705723846039e-08;
+
/**
* Returns the closest double approximation of the raising "e" to the power
* of the argument.
@@ -274,11 +705,88 @@
* <li>{@code exp(NaN) = NaN}</li>
* </ul>
*
- * @param d
+ * @param x
* the value whose exponential has to be computed.
* @return the exponential of the argument.
*/
- public static native double exp(double d);
+ public static double exp(double x) {
+ double y, c, t;
+ double hi = 0, lo = 0;
+ int k = 0, xsb;
+ int hx; // should be unsigned, be careful!
+ final long bits = Double.doubleToRawLongBits(x);
+ int lowBits = (int) bits;
+ int highBits = (int) (bits >>> 32);
+ hx = highBits & 0x7fffffff;
+ xsb = (highBits >>> 31) & 1;
+
+ /* filter out non-finite argument */
+ if (hx >= 0x40862E42) { /* if |x|>=709.78... */
+ if (hx >= 0x7ff00000) {
+ if (((hx & 0xfffff) | lowBits) != 0) {
+ return x + x; /* NaN */
+ } else {
+ return (xsb == 0) ? x : 0.0; /* ieee_exp(+-inf)={inf,0} */
+ }
+ }
+
+ if (x > O_THRESHOLD) {
+ return HUGE * HUGE; /* overflow */
+ }
+
+ if (x < U_THRESHOLD) {
+ return TWOM1000 * TWOM1000; /* underflow */
+ }
+ }
+
+ /* argument reduction */
+ if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
+ if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+ hi = x - ((xsb == 0) ? 6.93147180369123816490e-01 :
+ -6.93147180369123816490e-01); // LN2HI[xsb];
+ lo = (xsb == 0) ? 1.90821492927058770002e-10 :
+ -1.90821492927058770002e-10; // LN2LO[xsb];
+ k = 1 - xsb - xsb;
+ } else {
+ k = (int) (INVLN2 * x + ((xsb == 0) ? 0.5 : -0.5 ));//halF[xsb]);
+ t = k;
+ hi = x - t * 6.93147180369123816490e-01; //ln2HI[0]; /* t*ln2HI is exact here */
+ lo = t * 1.90821492927058770002e-10; //ln2LO[0];
+ }
+ x = hi - lo;
+ } else if (hx < 0x3e300000) { /* when |x|<2**-28 */
+ if (HUGE + x > 1.00000000000000000000e+00)
+ return 1.00000000000000000000e+00 + x;/* trigger inexact */
+ } else {
+ k = 0;
+ }
+
+ /* x is now in primary range */
+ t = x * x;
+ c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
+ if (k == 0) {
+ return 1.00000000000000000000e+00 - ((x * c) / (c - 2.0) - x);
+ } else {
+ y = 1.00000000000000000000e+00 - ((lo - (x * c) / (2.0 - c)) - hi);
+ }
+ long yBits = Double.doubleToRawLongBits(y);
+ if (k >= -1021) {
+ yBits += ((long) (k << 20)) << 32; /* add k to y's exponent */
+ return Double.longBitsToDouble(yBits);
+ } else {
+ yBits += ((long) ((k + 1000) << 20)) << 32;/* add k to y's exponent */
+ return Double.longBitsToDouble(yBits) * TWOM1000;
+ }
+ }
+
+ private static final double TINY = 1.0e-300;
+ private static final double LN2_HI = 6.93147180369123816490e-01;
+ private static final double LN2_LO = 1.90821492927058770002e-10;
+ private static final double Q1 = -3.33333333333331316428e-02;
+ private static final double Q2 = 1.58730158725481460165e-03;
+ private static final double Q3 = -7.93650757867487942473e-05;
+ private static final double Q4 = 4.00821782732936239552e-06;
+ private static final double Q5 = -2.01099218183624371326e-07;
/**
* Returns the closest double approximation of <i>{@code e}</i><sup>
@@ -295,17 +803,124 @@
* <li>{@code expm1(NaN) = NaN}</li>
* </ul>
*
- * @param d
+ * @param x
* the value to compute the <i>{@code e}</i><sup>{@code d}</sup>
* {@code - 1} of.
- * @return the <i>{@code e}</i><sup>{@code d}</sup>{@code - 1} value
- * of the argument.
+ * @return the <i>{@code e}</i><sup>{@code d}</sup>{@code - 1} value of the
+ * argument.
*/
- public static native double expm1(double d);
+ public static double expm1(double x) {
+ double y, hi, lo, t, e, hxs, hfx, r1, c = 0.0;
+ int k, xsb;
+ long yBits = 0;
+ final long bits = Double.doubleToRawLongBits(x);
+ int highBits = (int) (bits >>> 32);
+ int lowBits = (int) (bits);
+ int hx = highBits & 0x7fffffff; // caution: should be unsigned!
+ xsb = highBits & 0x80000000; /* sign bit of x */
+ y = xsb == 0 ? x : -x; /* y = |x| */
+
+ /* filter out huge and non-finite argument */
+ if (hx >= 0x4043687A) { /* if |x|>=56*ln2 */
+ if (hx >= 0x40862E42) { /* if |x|>=709.78... */
+ if (hx >= 0x7ff00000) {
+ if (((hx & 0xfffff) | lowBits) != 0) {
+ return x + x; /* NaN */
+ } else {
+ return (xsb == 0) ? x : -1.0;/* ieee_exp(+-inf)={inf,-1} */
+ }
+ }
+ if (x > O_THRESHOLD) {
+ return HUGE * HUGE; /* overflow */
+ }
+ }
+ if (xsb != 0) { /* x < -56*ln2, return -1.0 with inexact */
+ if (x + TINY < 0.0) { /* raise inexact */
+ return TINY - 1.00000000000000000000e+00; /* return -1 */
+ }
+ }
+ }
+ /* argument reduction */
+ if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
+ if (hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
+ if (xsb == 0) {
+ hi = x - LN2_HI;
+ lo = LN2_LO;
+ k = 1;
+ } else {
+ hi = x + LN2_HI;
+ lo = -LN2_LO;
+ k = -1;
+ }
+ } else {
+ k = (int) (INVLN2 * x + ((xsb == 0) ? 0.5 : -0.5));
+ t = k;
+ hi = x - t * LN2_HI; /* t*ln2_hi is exact here */
+ lo = t * LN2_LO;
+ }
+ x = hi - lo;
+ c = (hi - x) - lo;
+ } else if (hx < 0x3c900000) { /* when |x|<2**-54, return x */
+ // t = huge+x; /* return x with inexact flags when x!=0 */
+ // return x - (t-(huge+x));
+ return x; // inexact flag is not set, but Java ignors this flag
+ // anyway
+ } else {
+ k = 0;
+ }
+
+ /* x is now in primary range */
+ hfx = 0.5 * x;
+ hxs = x * hfx;
+ r1 = 1.00000000000000000000e+00 + hxs * (Q1 + hxs * (Q2 + hxs * (Q3 + hxs * (Q4 + hxs * Q5))));
+ t = 3.0 - r1 * hfx;
+ e = hxs * ((r1 - t) / (6.0 - x * t));
+ if (k == 0) {
+ return x - (x * e - hxs); /* c is 0 */
+ } else {
+ e = (x * (e - c) - c);
+ e -= hxs;
+ if (k == -1) {
+ return 0.5 * (x - e) - 0.5;
+ }
+
+ if (k == 1) {
+ if (x < -0.25) {
+ return -2.0 * (e - (x + 0.5));
+ } else {
+ return 1.00000000000000000000e+00 + 2.0 * (x - e);
+ }
+ }
+
+ if (k <= -2 || k > 56) { /* suffice to return ieee_exp(x)-1 */
+ y = 1.00000000000000000000e+00 - (e - x);
+ yBits = Double.doubleToRawLongBits(y);
+ yBits += (((long) k) << 52); /* add k to y's exponent */
+ return Double.longBitsToDouble(yBits) - 1.00000000000000000000e+00;
+ }
+
+ long tBits = Double.doubleToRawLongBits(1.00000000000000000000e+00) & 0x00000000ffffffffL;
+
+ if (k < 20) {
+ tBits |= (((long) 0x3ff00000) - (0x200000 >> k)) << 32;
+ y = Double.longBitsToDouble(tBits) - (e - x);
+ yBits = Double.doubleToRawLongBits(y);
+ yBits += (((long) k) << 52); /* add k to y's exponent */
+ return Double.longBitsToDouble(yBits);
+ } else {
+ tBits |= ((((long) 0x3ff) - k) << 52); /* 2^-k */
+ y = x - (e + Double.longBitsToDouble(tBits));
+ y += 1.00000000000000000000e+00;
+ yBits = Double.doubleToRawLongBits(y);
+ yBits += (((long) k) << 52); /* add k to y's exponent */
+ return Double.longBitsToDouble(yBits);
+ }
+ }
+ }
/**
- * Returns the double conversion of the most positive (closest to
- * positive infinity) integer less than or equal to the argument.
+ * Returns the double conversion of the most positive (closest to positive
+ * infinity) integer less than or equal to the argument.
* <p>
* Special cases:
* <ul>
@@ -319,9 +934,9 @@
public static native double floor(double d);
/**
- * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +}
- * <i> {@code y}</i><sup>{@code 2}</sup>{@code )}. The final result is
- * without medium underflow or overflow.
+ * Returns {@code sqrt(}<i>{@code x}</i><sup>{@code 2}</sup>{@code +} <i>
+ * {@code y}</i><sup>{@code 2}</sup>{@code )}. The final result is without
+ * medium underflow or overflow.
* <p>
* Special cases:
* <ul>
@@ -369,6 +984,14 @@
*/
public static native double IEEEremainder(double x, double y);
+ private static final double LG1 = 6.666666666666735130e-01;
+ private static final double LG2 = 3.999999999940941908e-01;
+ private static final double LG3 = 2.857142874366239149e-01;
+ private static final double LG4 = 2.222219843214978396e-01;
+ private static final double LG5 = 1.818357216161805012e-01;
+ private static final double LG6 = 1.531383769920937332e-01;
+ private static final double LG7 = 1.479819860511658591e-01;
+
/**
* Returns the closest double approximation of the natural logarithm of the
* argument.
@@ -383,11 +1006,95 @@
* <li>{@code log(NaN) = NaN}</li>
* </ul>
*
- * @param d
+ * @param x
* the value whose log has to be computed.
* @return the natural logarithm of the argument.
*/
- public static native double log(double d);
+ public static double log(double x) {
+ double hfsq, f, s, z, R, w, t1, t2, dk;
+ int hx, i, j, k = 0;
+ int lx; // watch out, should be unsigned
+
+ long bits = Double.doubleToRawLongBits(x);
+ hx = (int) (bits >>> 32); /* high word of x */
+ lx = (int) bits; /* low word of x */
+
+ if (hx < 0x00100000) { /* x < 2**-1022 */
+ if (((hx & 0x7fffffff) | lx) == 0) {
+ return -TWO54 / 0.0; /* ieee_log(+-0)=-inf */
+ }
+
+ if (hx < 0) {
+ return (x - x) / 0.0; /* ieee_log(-#) = NaN */
+ }
+
+ k -= 54;
+ x *= TWO54; /* subnormal number, scale up x */
+ bits = Double.doubleToRawLongBits(x);
+ hx = (int) (bits >>> 32); /* high word of x */
+ }
+
+ if (hx >= 0x7ff00000) {
+ return x + x;
+ }
+
+ k += (hx >> 20) - 1023;
+ hx &= 0x000fffff;
+ bits &= 0x00000000ffffffffL;
+ i = (hx + 0x95f64) & 0x100000;
+ bits |= ((long) hx | (i ^ 0x3ff00000)) << 32; /* normalize x or x/2 */
+ x = Double.longBitsToDouble(bits);
+ k += (i >> 20);
+ f = x - 1.0;
+
+ if ((0x000fffff & (2 + hx)) < 3) { /* |f| < 2**-20 */
+ if (f == 0.0) {
+ if (k == 0) {
+ return 0.0;
+ } else {
+ dk = k;
+ }
+ return dk * LN2_HI + dk * LN2_LO;
+ }
+
+ R = f * f * (0.5 - 0.33333333333333333 * f);
+ if (k == 0) {
+ return f - R;
+ } else {
+ dk = k;
+ return dk * LN2_HI - ((R - dk * LN2_LO) - f);
+ }
+ }
+ s = f / (2.0 + f);
+ dk = k;
+ z = s * s;
+ i = hx - 0x6147a;
+ w = z * z;
+ j = 0x6b851 - hx;
+ t1 = w * (LG2 + w * (LG4 + w * LG6));
+ t2 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7)));
+ i |= j;
+ R = t2 + t1;
+ if (i > 0) {
+ hfsq = 0.5 * f * f;
+ if (k == 0) {
+ return f - (hfsq - s * (hfsq + R));
+ } else {
+ return dk * LN2_HI
+ - ((hfsq - (s * (hfsq + R) + dk * LN2_LO)) - f);
+ }
+ } else {
+ if (k == 0) {
+ return f - s * (f - R);
+ } else {
+ return dk * LN2_HI - ((s * (f - R) - dk * LN2_LO) - f);
+ }
+ }
+ }
+
+ private static final double IVLN10 = 4.34294481903251816668e-01;
+ private static final double LOG10_2HI = 3.01029995663611771306e-01;
+ private static final double LOG10_2LO = 3.69423907715893078616e-13;
/**
* Returns the closest double approximation of the base 10 logarithm of the
@@ -403,11 +1110,54 @@
* <li>{@code log10(NaN) = NaN}</li>
* </ul>
*
- * @param d
+ * @param x
* the value whose base 10 log has to be computed.
- * @return the natural logarithm of the argument.
+ * @return the the base 10 logarithm of x
*/
- public static native double log10(double d);
+ public static double log10(double x) {
+ double y, z;
+ int i, k = 0, hx;
+ int lx; // careful: lx should be unsigned!
+ long bits = Double.doubleToRawLongBits(x);
+ hx = (int) (bits >> 32); /* high word of x */
+ lx = (int) bits; /* low word of x */
+ if (hx < 0x00100000) { /* x < 2**-1022 */
+ if (((hx & 0x7fffffff) | lx) == 0) {
+ return -TWO54 / 0.0; /* ieee_log(+-0)=-inf */
+ }
+
+ if (hx < 0) {
+ return (x - x) / 0.0; /* ieee_log(-#) = NaN */
+ }
+
+ k -= 54;
+ x *= TWO54; /* subnormal number, scale up x */
+ bits = Double.doubleToRawLongBits(x);
+ hx = (int) (bits >> 32); /* high word of x */
+ }
+
+ if (hx >= 0x7ff00000) {
+ return x + x;
+ }
+
+ k += (hx >> 20) - 1023;
+ i = (int) (((k & 0x00000000ffffffffL) & 0x80000000) >>> 31);
+ hx = (hx & 0x000fffff) | ((0x3ff - i) << 20);
+ y = k + i;
+ bits &= 0x00000000ffffffffL;
+ bits |= ((long) hx) << 32;
+ x = Double.longBitsToDouble(bits); // __HI(x) = hx;
+ z = y * LOG10_2LO + IVLN10 * log(x);
+ return z + y * LOG10_2HI;
+ }
+
+ private static final double LP1 = 6.666666666666735130e-01,
+ LP2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */
+ LP3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */
+ LP4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
+ LP5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */
+ LP6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */
+ LP7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */
/**
* Returns the closest double approximation of the natural logarithm of the
@@ -426,11 +1176,107 @@
* <li>{@code log1p(NaN) = NaN}</li>
* </ul>
*
- * @param d
+ * @param x
* the value to compute the {@code ln(1+d)} of.
* @return the natural logarithm of the sum of the argument and 1.
*/
- public static native double log1p(double d);
+
+ public static double log1p(double x) {
+ double hfsq, f = 0.0, c = 0.0, s, z, R, u = 0.0;
+ int k, hx, hu = 0, ax;
+
+ final long bits = Double.doubleToRawLongBits(x);
+ hx = (int) (bits >>> 32); /* high word of x */
+ ax = hx & 0x7fffffff;
+
+ k = 1;
+ if (hx < 0x3FDA827A) { /* x < 0.41422 */
+ if (ax >= 0x3ff00000) { /* x <= -1.0 */
+ if (x == -1.0) {
+ return -TWO54 / 0.0; /* ieee_log1p(-1)=+inf */
+ } else {
+ return (x - x) / (x - x); /* ieee_log1p(x<-1)=NaN */
+ }
+ }
+ if (ax < 0x3e200000) {
+ if (TWO54 + x > 0.0 && ax < 0x3c900000) {
+ return x;
+ } else {
+ return x - x * x * 0.5;
+ }
+ }
+ if (hx > 0 || hx <= 0xbfd2bec3) {
+ k = 0;
+ f = x;
+ hu = 1;
+ } /* -0.2929<x<0.41422 */
+ }
+
+ if (hx >= 0x7ff00000) {
+ return x + x;
+ }
+
+ if (k != 0) {
+ long uBits;
+ if (hx < 0x43400000) {
+ u = 1.0 + x;
+ uBits = Double.doubleToRawLongBits(u);
+ hu = (int) (uBits >>> 32);
+ k = (hu >> 20) - 1023;
+ c = (k > 0) ? 1.0 - (u - x) : x - (u - 1.0);/* correction term */
+ c /= u;
+ } else {
+ uBits = Double.doubleToRawLongBits(x);
+ hu = (int) (uBits >>> 32);
+ k = (hu >> 20) - 1023;
+ c = 0;
+ }
+ hu &= 0x000fffff;
+ if (hu < 0x6a09e) {
+ // __HI(u) = hu|0x3ff00000; /* normalize u */
+ uBits &= 0x00000000ffffffffL;
+ uBits |= ((long) hu | 0x3ff00000) << 32;
+ u = Double.longBitsToDouble(uBits);
+ } else {
+ k += 1;
+ // __HI(u) = hu|0x3fe00000; /* normalize u/2 */
+ uBits &= 0xffffffffL;
+ uBits |= ((long) hu | 0x3fe00000) << 32;
+ u = Double.longBitsToDouble(uBits);
+ hu = (0x00100000 - hu) >> 2;
+ }
+ f = u - 1.0;
+ }
+ hfsq = 0.5 * f * f;
+ if (hu == 0) { /* |f| < 2**-20 */
+ if (f == 0.0) {
+ if (k == 0) {
+ return 0.0;
+ } else {
+ c += k * LN2_LO;
+ return k * LN2_HI + c;
+ }
+ }
+
+ R = hfsq * (1.0 - 0.66666666666666666 * f);
+ if (k == 0) {
+ return f - R;
+ } else {
+ return k * LN2_HI - ((R - (k * LN2_LO + c)) - f);
+ }
+ }
+
+ s = f / (2.0 + f);
+ z = s * s;
+ R = z * (LP1 + z * (LP2 + z
+ * (LP3 + z * (LP4 + z * (LP5 + z * (LP6 + z * LP7))))));
+ if (k == 0) {
+ return f - (hfsq - s * (hfsq + R));
+ } else {
+ return k * LN2_HI
+ - ((hfsq - (s * (hfsq + R) + (k * LN2_LO + c))) - f);
+ }
+ }
/**
* Returns the most positive (closest to positive infinity) of the two
@@ -453,8 +1299,8 @@
if (d1 != d2)
return Double.NaN;
/* max( +0.0,-0.0) == +0.0 */
- if (d1 == 0.0
- && ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0)
+ if (d1 == 0.0 &&
+ ((Double.doubleToLongBits(d1) & Double.doubleToLongBits(d2)) & 0x8000000000000000L) == 0)
return 0.0;
return d1;
}
@@ -480,8 +1326,8 @@
if (f1 != f2)
return Float.NaN;
/* max( +0.0,-0.0) == +0.0 */
- if (f1 == 0.0f
- && ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0)
+ if (f1 == 0.0f &&
+ ((Float.floatToIntBits(f1) & Float.floatToIntBits(f2)) & 0x80000000) == 0)
return 0.0f;
return f1;
}
@@ -523,8 +1369,8 @@
if (d1 != d2)
return Double.NaN;
/* min( +0.0,-0.0) == -0.0 */
- if (d1 == 0.0
- && ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0)
+ if (d1 == 0.0 &&
+ ((Double.doubleToLongBits(d1) | Double.doubleToLongBits(d2)) & 0x8000000000000000l) != 0)
return 0.0 * (-1.0);
return d1;
}
@@ -550,8 +1396,8 @@
if (f1 != f2)
return Float.NaN;
/* min( +0.0,-0.0) == -0.0 */
- if (f1 == 0.0f
- && ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0)
+ if (f1 == 0.0f &&
+ ((Float.floatToIntBits(f1) | Float.floatToIntBits(f2)) & 0x80000000) != 0)
return 0.0f * (-1.0f);
return f1;
}
@@ -706,7 +1552,7 @@
* the value whose signum has to be computed.
* @return the value of the signum function.
*/
- public static double signum(double d){
+ public static double signum(double d) {
return Math.signum(d);
}
@@ -729,10 +1575,12 @@
* the value whose signum has to be computed.
* @return the value of the signum function.
*/
- public static float signum(float f){
+ public static float signum(float f) {
return Math.signum(f);
}
+ private static final double shuge = 1.0e307;
+
/**
* Returns the closest double approximation of the hyperbolic sine of the
* argument.
@@ -746,11 +1594,57 @@
* <li>{@code sinh(NaN) = NaN}</li>
* </ul>
*
- * @param d
+ * @param x
* the value whose hyperbolic sine has to be computed.
* @return the hyperbolic sine of the argument.
*/
- public static native double sinh(double d);
+ public static double sinh(double x) {
+ double t, w, h;
+ int ix, jx;
+ final long bits = Double.doubleToRawLongBits(x);
+
+ jx = (int) (bits >>> 32);
+ ix = jx & 0x7fffffff;
+
+ /* x is INF or NaN */
+ if (ix >= 0x7ff00000) {
+ return x + x;
+ }
+
+ h = 0.5;
+ if (jx < 0) {
+ h = -h;
+ }
+
+ /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */
+ if (ix < 0x40360000) { /* |x|<22 */
+ if (ix < 0x3e300000) /* |x|<2**-28 */
+ if (shuge + x > 1.00000000000000000000e+00) {
+ return x;/* ieee_sinh(tiny) = tiny with inexact */
+ }
+ t = expm1(Math.abs(x));
+ if (ix < 0x3ff00000)
+ return h * (2.0 * t - t * t / (t + 1.00000000000000000000e+00));
+ return h * (t + t / (t + 1.00000000000000000000e+00));
+ }
+
+ /* |x| in [22, ieee_log(maxdouble)] return 0.5*ieee_exp(|x|) */
+ if (ix < 0x40862E42) {
+ return h * exp(Math.abs(x));
+ }
+
+ /* |x| in [log(maxdouble), overflowthresold] */
+ final long lx = ((ONEBITS >>> 29) + ((int) bits)) & 0x00000000ffffffffL;
+ // lx = *( (((*(unsigned*)&one)>>29)) + (unsigned*)&x);
+ if (ix < 0x408633CE || (ix == 0x408633ce) && (lx <= 0x8fb9f87dL)) {
+ w = exp(0.5 * Math.abs(x));
+ t = h * w;
+ return t * w;
+ }
+
+ /* |x| > overflowthresold, ieee_sinh(x) overflow */
+ return x * shuge;
+ }
/**
* Returns the closest double approximation of the sine of the argument.
@@ -816,11 +1710,47 @@
* <li>{@code tanh(NaN) = NaN}</li>
* </ul>
*
- * @param d
+ * @param x
* the value whose hyperbolic tangent has to be computed.
* @return the hyperbolic tangent of the argument
*/
- public static native double tanh(double d);
+ public static double tanh(double x) {
+ double t, z;
+ int jx, ix;
+
+ final long bits = Double.doubleToRawLongBits(x);
+ /* High word of |x|. */
+ jx = (int) (bits >>> 32);
+ ix = jx & 0x7fffffff;
+
+ /* x is INF or NaN */
+ if (ix >= 0x7ff00000) {
+ if (jx >= 0) {
+ return 1.00000000000000000000e+00 / x + 1.00000000000000000000e+00; /* ieee_tanh(+-inf)=+-1 */
+ } else {
+ return 1.00000000000000000000e+00 / x - 1.00000000000000000000e+00; /* ieee_tanh(NaN) = NaN */
+ }
+ }
+
+ /* |x| < 22 */
+ if (ix < 0x40360000) { /* |x|<22 */
+ if (ix < 0x3c800000) { /* |x|<2**-55 */
+ return x * (1.00000000000000000000e+00 + x);/* ieee_tanh(small) = small */
+ }
+
+ if (ix >= 0x3ff00000) { /* |x|>=1 */
+ t = Math.expm1(2.0 * Math.abs(x));
+ z = 1.00000000000000000000e+00 - 2.0 / (t + 2.0);
+ } else {
+ t = Math.expm1(-2.0 * Math.abs(x));
+ z = -t / (t + 2.0);
+ }
+ /* |x| > 22, return +-1 */
+ } else {
+ z = 1.00000000000000000000e+00 - TINY; /* raised inexact flag */
+ }
+ return (jx >= 0) ? z : -z;
+ }
/**
* Returns the measure in degrees of the supplied radian angle. The result
@@ -922,6 +1852,7 @@
/**
* Returns a double with the given magnitude and the sign of {@code sign}.
* If {@code sign} is NaN, the sign of the result is positive.
+ *
* @since 1.6
*/
public static double copySign(double magnitude, double sign) {
@@ -932,13 +1863,15 @@
// (Tested on a Nexus One.)
long magnitudeBits = Double.doubleToRawLongBits(magnitude);
long signBits = Double.doubleToRawLongBits((sign != sign) ? 1.0 : sign);
- magnitudeBits = (magnitudeBits & ~Double.SIGN_MASK) | (signBits & Double.SIGN_MASK);
+ magnitudeBits = (magnitudeBits & ~Double.SIGN_MASK)
+ | (signBits & Double.SIGN_MASK);
return Double.longBitsToDouble(magnitudeBits);
}
/**
- * Returns a float with the given magnitude and the sign of {@code sign}.
- * If {@code sign} is NaN, the sign of the result is positive.
+ * Returns a float with the given magnitude and the sign of {@code sign}. If
+ * {@code sign} is NaN, the sign of the result is positive.
+ *
* @since 1.6
*/
public static float copySign(float magnitude, float sign) {
@@ -949,12 +1882,14 @@
// (Tested on a Nexus One.)
int magnitudeBits = Float.floatToRawIntBits(magnitude);
int signBits = Float.floatToRawIntBits((sign != sign) ? 1.0f : sign);
- magnitudeBits = (magnitudeBits & ~Float.SIGN_MASK) | (signBits & Float.SIGN_MASK);
+ magnitudeBits = (magnitudeBits & ~Float.SIGN_MASK)
+ | (signBits & Float.SIGN_MASK);
return Float.intBitsToFloat(magnitudeBits);
}
/**
* Returns the exponent of float {@code f}.
+ *
* @since 1.6
*/
public static int getExponent(float f) {
@@ -963,14 +1898,17 @@
/**
* Returns the exponent of double {@code d}.
+ *
* @since 1.6
*/
- public static int getExponent(double d){
+ public static int getExponent(double d) {
return Math.getExponent(d);
}
/**
- * Returns the next double after {@code start} in the given {@code direction}.
+ * Returns the next double after {@code start} in the given
+ * {@code direction}.
+ *
* @since 1.6
*/
public static double nextAfter(double start, double direction) {
@@ -981,7 +1919,9 @@
}
/**
- * Returns the next float after {@code start} in the given {@code direction}.
+ * Returns the next float after {@code start} in the given {@code direction}
+ * .
+ *
* @since 1.6
*/
public static float nextAfter(float start, double direction) {
@@ -990,6 +1930,7 @@
/**
* Returns the next double larger than {@code d}.
+ *
* @since 1.6
*/
public static double nextUp(double d) {
@@ -998,6 +1939,7 @@
/**
* Returns the next float larger than {@code f}.
+ *
* @since 1.6
*/
public static float nextUp(float f) {
@@ -1006,6 +1948,7 @@
/**
* Returns {@code d} * 2^{@code scaleFactor}. The result may be rounded.
+ *
* @since 1.6
*/
public static double scalb(double d, int scaleFactor) {
@@ -1049,12 +1992,10 @@
} else {
if (Math.abs(d) >= Double.MIN_NORMAL) {
// common situation
- result = ((factor + Double.EXPONENT_BIAS) << Double.MANTISSA_BITS)
- | (bits & Double.MANTISSA_MASK);
+ result = ((factor + Double.EXPONENT_BIAS) << Double.MANTISSA_BITS) | (bits & Double.MANTISSA_MASK);
} else {
// origin d is sub-normal, change mantissa to normal style
- result = ((factor + Double.EXPONENT_BIAS) << Double.MANTISSA_BITS)
- | ((bits << (subNormalFactor + 1)) & Double.MANTISSA_MASK);
+ result = ((factor + Double.EXPONENT_BIAS) << Double.MANTISSA_BITS) | ((bits << (subNormalFactor + 1)) & Double.MANTISSA_MASK);
}
}
return Double.longBitsToDouble(result | sign);
@@ -1062,6 +2003,7 @@
/**
* Returns {@code d} * 2^{@code scaleFactor}. The result may be rounded.
+ *
* @since 1.6
*/
public static float scalb(float d, int scaleFactor) {
@@ -1073,8 +2015,7 @@
int factor = ((bits & Float.EXPONENT_MASK) >> Float.MANTISSA_BITS)
- Float.EXPONENT_BIAS + scaleFactor;
// calculates the factor of sub-normal values
- int subNormalFactor = Integer.numberOfLeadingZeros(bits & ~Float.SIGN_MASK)
- - Float.EXPONENT_BITS;
+ int subNormalFactor = Integer.numberOfLeadingZeros(bits & ~Float.SIGN_MASK) - Float.EXPONENT_BITS;
if (subNormalFactor < 0) {
// not sub-normal values
subNormalFactor = 0;
@@ -1105,8 +2046,9 @@
| (bits & Float.MANTISSA_MASK);
} else {
// origin d is sub-normal, change mantissa to normal style
- result = ((factor + Float.EXPONENT_BIAS) << Float.MANTISSA_BITS)
- | ((bits << (subNormalFactor + 1)) & Float.MANTISSA_MASK);
+ result = ((factor + Float.EXPONENT_BIAS)
+ << Float.MANTISSA_BITS) | (
+ (bits << (subNormalFactor + 1)) & Float.MANTISSA_MASK);
}
}
return Float.intBitsToFloat(result | sign);
@@ -1120,10 +2062,10 @@
}
// change it to positive
int absDigits = -digits;
- if (Integer.numberOfLeadingZeros(bits & ~Float.SIGN_MASK) <= (32 - absDigits)) {
+ if (Integer.numberOfLeadingZeros(bits & ~Float.SIGN_MASK)
+ <= (32 - absDigits)) {
// some bits will remain after shifting, calculates its carry
- if ((((bits >> (absDigits - 1)) & 0x1) == 0)
- || Integer.numberOfTrailingZeros(bits) == (absDigits - 1)) {
+ if ((((bits >> (absDigits - 1)) & 0x1) == 0) || Integer.numberOfTrailingZeros(bits) == (absDigits - 1)) {
return bits >> absDigits;
}
return ((bits >> absDigits) + 1);
@@ -1139,10 +2081,10 @@
}
// change it to positive
long absDigits = -digits;
- if (Long.numberOfLeadingZeros(bits & ~Double.SIGN_MASK) <= (64 - absDigits)) {
+ if (Long.numberOfLeadingZeros(bits & ~Double.SIGN_MASK)
+ <= (64 - absDigits)) {
// some bits will remain after shifting, calculates its carry
- if ((((bits >> (absDigits - 1)) & 0x1) == 0)
- || Long.numberOfTrailingZeros(bits) == (absDigits - 1)) {
+ if ((((bits >> (absDigits - 1)) & 0x1) == 0) || Long.numberOfTrailingZeros(bits) == (absDigits - 1)) {
return bits >> absDigits;
}
return ((bits >> absDigits) + 1);
diff --git a/luni/src/main/java/java/util/EnumMap.java b/luni/src/main/java/java/util/EnumMap.java
index dfacb46..eee6ff4 100644
--- a/luni/src/main/java/java/util/EnumMap.java
+++ b/luni/src/main/java/java/util/EnumMap.java
@@ -36,9 +36,9 @@
private Class<K> keyType;
- transient Enum[] keys;
+ transient K[] keys;
- transient Object[] values;
+ transient V[] values;
transient boolean[] hasMapping;
@@ -48,8 +48,7 @@
private transient EnumMapEntrySet<K, V> entrySet = null;
- private static class Entry<KT extends Enum<KT>, VT> extends
- MapEntry<KT, VT> {
+ private static class Entry<KT extends Enum<KT>, VT> extends MapEntry<KT, VT> {
private final EnumMap<KT, VT> enumMap;
private final int ordinal;
@@ -57,10 +56,9 @@
Entry(KT theKey, VT theValue, EnumMap<KT, VT> em) {
super(theKey, theValue);
enumMap = em;
- ordinal = ((Enum) theKey).ordinal();
+ ordinal = theKey.ordinal();
}
- @SuppressWarnings("unchecked")
@Override
public boolean equals(Object object) {
if (!enumMap.hasMapping[ordinal]) {
@@ -68,7 +66,7 @@
}
boolean isEqual = false;
if (object instanceof Map.Entry) {
- Map.Entry<KT, VT> entry = (Map.Entry<KT, VT>) object;
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
Object enumKey = entry.getKey();
if (key.equals(enumKey)) {
Object theValue = entry.getValue();
@@ -84,37 +82,32 @@
@Override
public int hashCode() {
- return (enumMap.keys[ordinal] == null ? 0 : enumMap.keys[ordinal]
- .hashCode())
+ return (enumMap.keys[ordinal] == null ? 0 : enumMap.keys[ordinal].hashCode())
^ (enumMap.values[ordinal] == null ? 0
: enumMap.values[ordinal].hashCode());
}
- @SuppressWarnings("unchecked")
@Override
public KT getKey() {
checkEntryStatus();
- return (KT) enumMap.keys[ordinal];
+ return enumMap.keys[ordinal];
}
- @SuppressWarnings("unchecked")
@Override
public VT getValue() {
checkEntryStatus();
- return (VT) enumMap.values[ordinal];
+ return enumMap.values[ordinal];
}
- @SuppressWarnings("unchecked")
@Override
public VT setValue(VT value) {
checkEntryStatus();
- return enumMap.put((KT) enumMap.keys[ordinal], value);
+ return enumMap.put(enumMap.keys[ordinal], value);
}
@Override
public String toString() {
- StringBuilder result = new StringBuilder(enumMap.keys[ordinal]
- .toString());
+ StringBuilder result = new StringBuilder(enumMap.keys[ordinal].toString());
result.append("=");
result.append(enumMap.values[ordinal] == null
? "null" : enumMap.values[ordinal].toString());
@@ -128,8 +121,7 @@
}
}
- private static class EnumMapIterator<E, KT extends Enum<KT>, VT> implements
- Iterator<E> {
+ private static class EnumMapIterator<E, KT extends Enum<KT>, VT> implements Iterator<E> {
int position = 0;
int prePosition = -1;
@@ -153,13 +145,12 @@
return position != length;
}
- @SuppressWarnings("unchecked")
public E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
prePosition = position++;
- return type.get(new MapEntry(enumMap.keys[prePosition],
+ return type.get(new MapEntry<KT, VT>(enumMap.keys[prePosition],
enumMap.values[prePosition]));
}
@@ -172,13 +163,12 @@
}
@Override
- @SuppressWarnings("unchecked")
public String toString() {
if (prePosition == -1) {
return super.toString();
}
return type.get(
- new MapEntry(enumMap.keys[prePosition],
+ new MapEntry<KT, VT>(enumMap.keys[prePosition],
enumMap.values[prePosition])).toString();
}
@@ -208,8 +198,7 @@
}
@Override
- @SuppressWarnings("unchecked")
- public Iterator iterator() {
+ public Iterator<KT> iterator() {
return new EnumMapIterator<KT, KT, VT>(
new MapEntry.Type<KT, KT, VT>() {
public KT get(MapEntry<KT, VT> entry) {
@@ -219,7 +208,6 @@
}
@Override
- @SuppressWarnings("unchecked")
public boolean remove(Object object) {
if (contains(object)) {
enumMap.remove(object);
@@ -252,9 +240,8 @@
return enumMap.containsValue(object);
}
- @SuppressWarnings("unchecked")
@Override
- public Iterator iterator() {
+ public Iterator<VT> iterator() {
return new EnumMapIterator<VT, KT, VT>(
new MapEntry.Type<VT, KT, VT>() {
public VT get(MapEntry<KT, VT> entry) {
@@ -296,15 +283,14 @@
super(value, em);
}
- @SuppressWarnings("unchecked")
@Override
public E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
prePosition = position++;
- return type.get(new Entry<KT, VT>((KT) enumMap.keys[prePosition],
- (VT) enumMap.values[prePosition], enumMap));
+ return type.get(new EnumMap.Entry<KT, VT>(enumMap.keys[prePosition],
+ enumMap.values[prePosition], enumMap));
}
}
@@ -325,8 +311,8 @@
public boolean contains(Object object) {
boolean isEqual = false;
if (object instanceof Map.Entry) {
- Object enumKey = ((Map.Entry) object).getKey();
- Object enumValue = ((Map.Entry) object).getValue();
+ Object enumKey = ((Map.Entry<?, ?>) object).getKey();
+ Object enumValue = ((Map.Entry<?, ?>) object).getValue();
if (enumMap.containsKey(enumKey)) {
VT value = enumMap.get(enumKey);
if (value == null) {
@@ -352,7 +338,7 @@
@Override
public boolean remove(Object object) {
if (contains(object)) {
- enumMap.remove(((Map.Entry) object).getKey());
+ enumMap.remove(((Map.Entry<?, ?>) object).getKey());
return true;
}
return false;
@@ -369,21 +355,22 @@
return toArray(entryArray);
}
- @SuppressWarnings("unchecked")
@Override
- public Object[] toArray(Object[] array) {
+ public <T> T[] toArray(T[] array) {
int size = enumMap.size();
int index = 0;
- Object[] entryArray = array;
+ T[] entryArray = array;
if (size > array.length) {
Class<?> clazz = array.getClass().getComponentType();
- entryArray = (Object[]) Array.newInstance(clazz, size);
+ @SuppressWarnings("unchecked") T[] newArray = (T[]) Array.newInstance(clazz, size);
+ entryArray = newArray;
}
Iterator<Map.Entry<KT, VT>> iter = iterator();
for (; index < size; index++) {
Map.Entry<KT, VT> entry = iter.next();
- entryArray[index] = new MapEntry<KT, VT>(entry.getKey(), entry
- .getValue());
+ @SuppressWarnings("unchecked") T newEntry =
+ (T) new MapEntry<KT, VT>(entry.getKey(), entry.getValue());
+ entryArray[index] = newEntry;
}
if (index < array.length) {
entryArray[index] = null;
@@ -431,22 +418,27 @@
* @throws NullPointerException
* if {@code map} is {@code null}.
*/
- @SuppressWarnings("unchecked")
public EnumMap(Map<K, ? extends V> map) {
if (map instanceof EnumMap) {
- initialization((EnumMap<K, V>) map);
+ @SuppressWarnings("unchecked") EnumMap<K, ? extends V> enumMap =
+ (EnumMap<K, ? extends V>) map;
+ initialization(enumMap);
} else {
if (map.isEmpty()) {
throw new IllegalArgumentException("map is empty");
}
Iterator<K> iter = map.keySet().iterator();
K enumKey = iter.next();
- Class clazz = enumKey.getClass();
- if (clazz.isEnum()) {
- initialization(clazz);
- } else {
- initialization(clazz.getSuperclass());
+ // Confirm the key is actually an enum: Throw ClassCastException if not.
+ Enum.class.cast(enumKey);
+ Class<?> clazz = enumKey.getClass();
+ if (!clazz.isEnum()) {
+ // Each enum value can have its own subclass. In this case we want the abstract
+ // super-class which has the values() method.
+ clazz = clazz.getSuperclass();
}
+ @SuppressWarnings("unchecked") Class<K> enumClass = (Class<K>) clazz;
+ initialization(enumClass);
putAllImpl(map);
}
}
@@ -469,11 +461,10 @@
*
* @return a shallow copy of this {@code EnumMap}.
*/
- @SuppressWarnings("unchecked")
@Override
public EnumMap<K, V> clone() {
try {
- EnumMap<K, V> enumMap = (EnumMap<K, V>) super.clone();
+ @SuppressWarnings("unchecked") EnumMap<K, V> enumMap = (EnumMap<K, V>) super.clone();
enumMap.initialization(this);
return enumMap;
} catch (CloneNotSupportedException e) {
@@ -553,7 +544,6 @@
* @see #hashCode()
* @see #entrySet()
*/
- @SuppressWarnings("unchecked")
@Override
public boolean equals(Object object) {
if (this == object) {
@@ -562,7 +552,7 @@
if (!(object instanceof EnumMap)) {
return super.equals(object);
}
- EnumMap<K, V> enumMap = (EnumMap<K, V>) object;
+ @SuppressWarnings("unchecked") EnumMap<K, V> enumMap = (EnumMap<K, V>) object;
if (keyType != enumMap.keyType || size() != enumMap.size()) {
return false;
}
@@ -579,13 +569,12 @@
* if no mapping for the specified key is found.
*/
@Override
- @SuppressWarnings("unchecked")
public V get(Object key) {
if (!isValidKeyType(key)) {
return null;
}
int keyOrdinal = ((Enum) key).ordinal();
- return (V) values[keyOrdinal];
+ return values[keyOrdinal];
}
/**
@@ -627,7 +616,6 @@
* support {@code null} keys or values.
*/
@Override
- @SuppressWarnings("unchecked")
public V put(K key, V value) {
return putImpl(key, value);
}
@@ -649,7 +637,6 @@
* support {@code null} keys or values.
*/
@Override
- @SuppressWarnings("unchecked")
public void putAll(Map<? extends K, ? extends V> map) {
putAllImpl(map);
}
@@ -665,7 +652,6 @@
* if removing from this {@code EnumMap} is not supported.
*/
@Override
- @SuppressWarnings("unchecked")
public V remove(Object key) {
if (!isValidKeyType(key)) {
return null;
@@ -675,7 +661,7 @@
hasMapping[keyOrdinal] = false;
mappingsCount--;
}
- V oldValue = (V) values[keyOrdinal];
+ V oldValue = values[keyOrdinal];
values[keyOrdinal] = null;
return oldValue;
}
@@ -716,35 +702,29 @@
stream.defaultReadObject();
initialization(keyType);
int elementCount = stream.readInt();
- Enum<K> enumKey;
- Object value;
+ K enumKey;
+ V value;
for (int i = elementCount; i > 0; i--) {
- enumKey = (Enum<K>) stream.readObject();
- value = stream.readObject();
- putImpl((K) enumKey, (V) value);
+ enumKey = (K) stream.readObject();
+ value = (V) stream.readObject();
+ putImpl(enumKey, value);
}
}
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeInt(mappingsCount);
- Iterator<Map.Entry<K, V>> iterator = entrySet().iterator();
- while (iterator.hasNext()) {
- Map.Entry<K, V> entry = iterator.next();
+ for (Map.Entry<K, V> entry : entrySet()) {
stream.writeObject(entry.getKey());
stream.writeObject(entry.getValue());
}
}
private boolean isValidKeyType(Object key) {
- if (key != null && keyType.isInstance(key)) {
- return true;
- }
- return false;
+ return key != null && keyType.isInstance(key);
}
- @SuppressWarnings("unchecked")
- private void initialization(EnumMap enumMap) {
+ private void initialization(EnumMap<K, ? extends V> enumMap) {
keyType = enumMap.keyType;
keys = enumMap.keys;
enumSize = enumMap.enumSize;
@@ -757,20 +737,19 @@
keyType = type;
keys = Enum.getSharedConstants(keyType);
enumSize = keys.length;
- values = new Object[enumSize];
+ // The value array is actually Object[] for speed of creation. It is treated as a V[]
+ // because it is safe to do so and eliminates unchecked warning suppression throughout.
+ @SuppressWarnings("unchecked") V[] valueArray = (V[]) new Object[enumSize];
+ values = valueArray;
hasMapping = new boolean[enumSize];
}
- @SuppressWarnings("unchecked")
- private void putAllImpl(Map map) {
- Iterator iter = map.entrySet().iterator();
- while (iter.hasNext()) {
- Map.Entry entry = (Map.Entry) iter.next();
- putImpl((K) entry.getKey(), (V) entry.getValue());
+ private void putAllImpl(Map<? extends K, ? extends V> map) {
+ for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
+ putImpl(entry.getKey(), entry.getValue());
}
}
- @SuppressWarnings("unchecked")
private V putImpl(K key, V value) {
if (key == null) {
throw new NullPointerException("key == null");
@@ -781,7 +760,7 @@
hasMapping[keyOrdinal] = true;
mappingsCount++;
}
- V oldValue = (V) values[keyOrdinal];
+ V oldValue = values[keyOrdinal];
values[keyOrdinal] = value;
return oldValue;
}
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
index 803cd49..4a76104 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
@@ -293,11 +293,13 @@
private static final long serialVersionUID = -8627078645895051609L;
- /**
- * Generates the initial random seed for the cheaper per-instance
- * random number generators used in randomLevel.
- */
- private static final Random seedGenerator = new Random();
+// BEGIN android-removed
+// /**
+// * Generates the initial random seed for the cheaper per-instance
+// * random number generators used in randomLevel.
+// */
+// private static final Random seedGenerator = new Random();
+// END android-removed
/**
* Special value used to identify base-level header
@@ -341,7 +343,13 @@
entrySet = null;
values = null;
descendingMap = null;
- randomSeed = seedGenerator.nextInt() | 0x0100; // ensure nonzero
+ // BEGIN android-changed
+ //
+ // Most processes are forked from the zygote, so they'll end up
+ // with the same random seed unless we take additional post fork
+ // measures.
+ randomSeed = Math.randomIntInternal() | 0x0100; // ensure nonzero
+ // END android-changed
head = new HeadIndex<K,V>(new Node<K,V>(null, BASE_HEADER, null),
null, null, 1);
}
diff --git a/luni/src/main/java/java/util/jar/StrictJarFile.java b/luni/src/main/java/java/util/jar/StrictJarFile.java
index 4a8af5f..0a8eaa2 100644
--- a/luni/src/main/java/java/util/jar/StrictJarFile.java
+++ b/luni/src/main/java/java/util/jar/StrictJarFile.java
@@ -53,7 +53,7 @@
private final CloseGuard guard = CloseGuard.get();
private boolean closed;
- public StrictJarFile(String fileName) throws IOException {
+ public StrictJarFile(String fileName) throws IOException, SecurityException {
this.nativeHandle = nativeOpenJarFile(fileName);
this.raf = new RandomAccessFile(fileName, "r");
@@ -66,9 +66,10 @@
this.verifier = new JarVerifier(fileName, manifest, metaEntries);
isSigned = verifier.readCertificates() && verifier.isSignedJar();
- } catch (IOException ioe) {
+ } catch (IOException | SecurityException e) {
nativeClose(this.nativeHandle);
- throw ioe;
+ IoUtils.closeQuietly(this.raf);
+ throw e;
}
guard.open("close");
diff --git a/luni/src/main/java/java/util/logging/FileHandler.java b/luni/src/main/java/java/util/logging/FileHandler.java
index 6ffef87..1fd1dbf 100644
--- a/luni/src/main/java/java/util/logging/FileHandler.java
+++ b/luni/src/main/java/java/util/logging/FileHandler.java
@@ -261,15 +261,15 @@
boolean hasUniqueID = false;
boolean hasGeneration = false;
- // TODO privilege code?
+ String homePath = System.getProperty("user.home");
+ if (homePath == null) {
+ throw new NullPointerException("System property \"user.home\" is null");
+ }
+ boolean homePathHasSepEnd = homePath.endsWith(File.separator);
String tempPath = System.getProperty("java.io.tmpdir");
- boolean tempPathHasSepEnd = (tempPath == null ? false : tempPath
- .endsWith(File.separator));
-
- String homePath = System.getProperty("user.home");
- boolean homePathHasSepEnd = (homePath == null ? false : homePath
- .endsWith(File.separator));
+ tempPath = tempPath == null ? homePath : tempPath;
+ boolean tempPathHasSepEnd = tempPath.endsWith(File.separator);
StringBuilder sb = new StringBuilder();
pattern = pattern.replace('/', File.separatorChar);
diff --git a/luni/src/main/java/java/util/logging/SocketHandler.java b/luni/src/main/java/java/util/logging/SocketHandler.java
index 48bfc0e..c6d4be0 100644
--- a/luni/src/main/java/java/util/logging/SocketHandler.java
+++ b/luni/src/main/java/java/util/logging/SocketHandler.java
@@ -106,9 +106,13 @@
throw new IllegalArgumentException("host == null || host.isEmpty()");
}
// check the validity of the port number
- int p = 0;
+ int p;
try {
p = Integer.parsePositiveInt(port);
+ // Must be >= 0 to get this far. 0 is invalid too.
+ if (p == 0) {
+ throw new IllegalArgumentException("Illegal port argument " + port);
+ }
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Illegal port argument " + port);
}
diff --git a/luni/src/main/java/java/util/logging/XMLFormatter.java b/luni/src/main/java/java/util/logging/XMLFormatter.java
index 0d80b3e..3952596 100644
--- a/luni/src/main/java/java/util/logging/XMLFormatter.java
+++ b/luni/src/main/java/java/util/logging/XMLFormatter.java
@@ -17,6 +17,7 @@
package java.util.logging;
+import java.io.IOException;
import java.text.MessageFormat;
import java.util.Date;
import java.util.ResourceBundle;
@@ -50,7 +51,7 @@
// call a method of LogRecord to ensure not null
long time = r.getMillis();
// format to date
- String date = MessageFormat.format("{0, date} {0, time}", new Object[] { new Date(time) });
+ String date = MessageFormat.format("{0, date} {0, time}", new Date(time));
String nl = System.lineSeparator();
StringBuilder sb = new StringBuilder();
@@ -59,21 +60,21 @@
append(sb, 1, "millis", time);
append(sb, 1, "sequence", r.getSequenceNumber());
if (r.getLoggerName() != null) {
- append(sb, 1, "logger", r.getLoggerName());
+ escapeAndAppend(sb, 1, "logger", r.getLoggerName());
}
append(sb, 1, "level", r.getLevel().getName());
if (r.getSourceClassName() != null) {
append(sb, 1, "class", r.getSourceClassName());
}
if (r.getSourceMethodName() != null) {
- append(sb, 1, "method", r.getSourceMethodName());
+ escapeAndAppend(sb, 1, "method", r.getSourceMethodName());
}
append(sb, 1, "thread", r.getThreadID());
formatMessages(r, sb);
Object[] params = r.getParameters();
if (params != null) {
for (Object element : params) {
- append(sb, 1, "param", element);
+ escapeAndAppend(sb, 1, "param", element);
}
}
formatThrowable(r, sb);
@@ -96,14 +97,14 @@
if (message == null) {
message = pattern;
- append(sb, 1, "message", message);
+ escapeAndAppend(sb, 1, "message", message);
} else {
- append(sb, 1, "message", message);
- append(sb, 1, "key", pattern);
- append(sb, 1, "catalog", r.getResourceBundleName());
+ escapeAndAppend(sb, 1, "message", message);
+ escapeAndAppend(sb, 1, "key", pattern);
+ escapeAndAppend(sb, 1, "catalog", r.getResourceBundleName());
}
} else if (pattern != null) {
- append(sb, 1, "message", pattern);
+ escapeAndAppend(sb, 1, "message", pattern);
} else {
sb.append(indent).append("<message/>");
}
@@ -114,13 +115,13 @@
if ((t = r.getThrown()) != null) {
String nl = System.lineSeparator();
sb.append(indent).append("<exception>").append(nl);
- append(sb, 2, "message", t.toString());
+ escapeAndAppend(sb, 2, "message", t.toString());
// format throwable's stack trace
StackTraceElement[] elements = t.getStackTrace();
for (StackTraceElement e : elements) {
sb.append(indent).append(indent).append("<frame>").append(nl);
append(sb, 3, "class", e.getClassName());
- append(sb, 3, "method", e.getMethodName());
+ escapeAndAppend(sb, 3, "method", e.getMethodName());
append(sb, 3, "line", e.getLineNumber());
sb.append(indent).append(indent).append("</frame>").append(nl);
}
@@ -138,6 +139,49 @@
sb.append(System.lineSeparator());
}
+ private static void escapeAndAppend(StringBuilder sb, int indentCount, String tag, Object value) {
+ if (value == null) {
+ append(sb, indentCount, tag, value);
+ } else {
+ for (int i = 0; i < indentCount; ++i) {
+ sb.append(indent);
+ }
+ sb.append("<").append(tag).append(">");
+ try {
+ escapeXml(sb, value.toString());
+ } catch (IOException e) {
+ throw new AssertionError();
+ }
+ sb.append("</").append(tag).append(">");
+ sb.append(System.lineSeparator());
+ }
+ }
+
+ private static void escapeXml(Appendable valueBuilder, String value) throws IOException {
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+ switch (c) {
+ case '\"':
+ valueBuilder.append(""");
+ break;
+ case '>':
+ valueBuilder.append(">");
+ break;
+ case '<':
+ valueBuilder.append("<");
+ break;
+ case '&':
+ valueBuilder.append("&");
+ break;
+ case '\'':
+ valueBuilder.append("'");
+ break;
+ default:
+ valueBuilder.append(c);
+ }
+ }
+ }
+
/**
* Returns the header string for a set of log records formatted as XML
* strings, using the output handler's encoding if it is defined, otherwise
diff --git a/luni/src/main/java/java/util/zip/ZipEntry.java b/luni/src/main/java/java/util/zip/ZipEntry.java
index 217cc3c..d007b0f 100644
--- a/luni/src/main/java/java/util/zip/ZipEntry.java
+++ b/luni/src/main/java/java/util/zip/ZipEntry.java
@@ -52,7 +52,6 @@
byte[] extra;
- int nameLength = -1;
long localHeaderRelOffset = -1;
long dataOffset = -1;
@@ -69,7 +68,7 @@
ZipEntry(String name, String comment, long crc, long compressedSize,
long size, int compressionMethod, int time, int modDate, byte[] extra,
- int nameLength, long localHeaderRelOffset, long dataOffset) {
+ long localHeaderRelOffset, long dataOffset) {
this.name = name;
this.comment = comment;
this.crc = crc;
@@ -79,7 +78,6 @@
this.time = time;
this.modDate = modDate;
this.extra = extra;
- this.nameLength = nameLength;
this.localHeaderRelOffset = localHeaderRelOffset;
this.dataOffset = dataOffset;
}
@@ -340,7 +338,6 @@
compressionMethod = ze.compressionMethod;
modDate = ze.modDate;
extra = ze.extra;
- nameLength = ze.nameLength;
localHeaderRelOffset = ze.localHeaderRelOffset;
dataOffset = ze.dataOffset;
}
@@ -412,7 +409,7 @@
compressedSize = ((long) it.readInt()) & 0xffffffffL;
size = ((long) it.readInt()) & 0xffffffffL;
- nameLength = it.readShort() & 0xffff;
+ int nameLength = it.readShort() & 0xffff;
int extraLength = it.readShort() & 0xffff;
int commentByteCount = it.readShort() & 0xffff;
diff --git a/luni/src/main/java/javax/net/ssl/DefaultHostnameVerifier.java b/luni/src/main/java/javax/net/ssl/DefaultHostnameVerifier.java
index fd84c3e..ffa995c 100644
--- a/luni/src/main/java/javax/net/ssl/DefaultHostnameVerifier.java
+++ b/luni/src/main/java/javax/net/ssl/DefaultHostnameVerifier.java
@@ -131,12 +131,24 @@
return false;
}
+ if (hostName.endsWith(".") && !cn.endsWith(".")) {
+ // "www.android.com." matches "www.android.com"
+ // This is needed because server certificates do not normally contain absolute names
+ // or patterns. Connections via absolute hostnames should be supported and even
+ // preferred over those via relative hostnames, to avoid DNS suffixes being appended.
+ cn += '.';
+ }
+
cn = cn.toLowerCase(Locale.US);
if (!cn.contains("*")) {
return hostName.equals(cn);
}
+ if (!containsAtLeastTwoDomainNameLabelsExcludingRoot(cn)) {
+ return false; // reject matches where the wildcard pattern consists of only one label.
+ }
+
if (cn.startsWith("*.") && hostName.equals(cn.substring(2))) {
return true; // "*.foo.com" matches "foo.com"
}
@@ -154,10 +166,7 @@
int suffixLength = cn.length() - (asterisk + 1);
int suffixStart = hostName.length() - suffixLength;
if (hostName.indexOf('.', asterisk) < suffixStart) {
- // TODO: remove workaround for *.clients.google.com http://b/5426333
- if (!hostName.endsWith(".clients.google.com")) {
- return false; // wildcard '*' can't match a '.'
- }
+ return false; // wildcard '*' can't match a '.'
}
if (!hostName.regionMatches(suffixStart, cn, asterisk + 1, suffixLength)) {
@@ -166,4 +175,27 @@
return true;
}
+
+ /**
+ * Checks whether the provided hostname consists of at least two domain name labels, excluding
+ * the root label.
+ *
+ * <p>For example, this method returns {@code true} for {@code www.android.com} and
+ * {@code foo.com} and {@code foo.com.}, and returns {@code false} for {@code foo} and
+ * {@code foo.}.
+ */
+ private static boolean containsAtLeastTwoDomainNameLabelsExcludingRoot(String hostname) {
+ int delimiterIndex = hostname.indexOf('.');
+ if (delimiterIndex == -1) {
+ // No delimiters -- only one label
+ return false;
+ }
+ if (delimiterIndex == hostname.length() - 1) {
+ // Only one delimiter at the every end of the hostname -- this is an absolute hostname
+ // consisting of one label
+ return false;
+ }
+ // At least two labels
+ return true;
+ }
}
diff --git a/luni/src/main/java/javax/net/ssl/SSLEngine.java b/luni/src/main/java/javax/net/ssl/SSLEngine.java
index cbf02ac..7da8f1f 100644
--- a/luni/src/main/java/javax/net/ssl/SSLEngine.java
+++ b/luni/src/main/java/javax/net/ssl/SSLEngine.java
@@ -62,6 +62,7 @@
* </table>
*
* <h4>Cipher suites</h4>
+ * <!-- STOPSHIP: Update this table to reflect the removal of DSS cipher suites. -->
* <table>
* <thead>
* <tr>
diff --git a/luni/src/main/java/javax/net/ssl/SSLSocket.java b/luni/src/main/java/javax/net/ssl/SSLSocket.java
index dc406e1..043b005 100644
--- a/luni/src/main/java/javax/net/ssl/SSLSocket.java
+++ b/luni/src/main/java/javax/net/ssl/SSLSocket.java
@@ -106,6 +106,7 @@
* standard names for cipher suites since API Level 9, as listed in the table
* below. Prior to API Level 9, non-standard (OpenSSL) names had been used (see
* the table following this table).
+ * <!-- STOPSHIP: Update this table to reflect the removal of DSS cipher suites. -->
* <table>
* <thead>
* <tr>
diff --git a/luni/src/main/java/libcore/icu/LocaleData.java b/luni/src/main/java/libcore/icu/LocaleData.java
index cca38e1..cf52b9c 100644
--- a/luni/src/main/java/libcore/icu/LocaleData.java
+++ b/luni/src/main/java/libcore/icu/LocaleData.java
@@ -88,15 +88,12 @@
public String shortDateFormat4;
// Used by DateFormat to implement 12- and 24-hour SHORT and MEDIUM.
+ // The first two are also used directly by frameworks code.
public String timeFormat_hm;
public String timeFormat_Hm;
public String timeFormat_hms;
public String timeFormat_Hms;
- // Used by android.text.format.DateFormat.getTimeFormat.
- public String timeFormat12; // "hh:mm a"
- public String timeFormat24; // "HH:mm"
-
// Used by DecimalFormatSymbols.
public char zeroDigit;
public char decimalSeparator;
@@ -213,12 +210,6 @@
localeData.timeFormat_Hm = ICU.getBestDateTimePattern("Hm", locale);
localeData.timeFormat_hms = ICU.getBestDateTimePattern("hms", locale);
localeData.timeFormat_Hms = ICU.getBestDateTimePattern("Hms", locale);
- // We could move callers over to the other fields, but these seem simpler and discourage
- // people from shooting themselves in the foot by learning about patterns and skeletons.
- // TODO: the right fix here is probably to move callers over to java.text.DateFormat,
- // so nothing outside libcore references these any more.
- localeData.timeFormat12 = localeData.timeFormat_hm;
- localeData.timeFormat24 = localeData.timeFormat_Hm;
// Fix up a couple of patterns.
if (localeData.fullTimeFormat != null) {
diff --git a/luni/src/main/java/libcore/io/IoUtils.java b/luni/src/main/java/libcore/io/IoUtils.java
index 5a19f17..737ceeb 100644
--- a/luni/src/main/java/libcore/io/IoUtils.java
+++ b/luni/src/main/java/libcore/io/IoUtils.java
@@ -30,8 +30,6 @@
import static android.system.OsConstants.*;
public final class IoUtils {
- private static final Random TEMPORARY_DIRECTORY_PRNG = new Random();
-
private IoUtils() {
}
@@ -142,7 +140,7 @@
*/
public static File createTemporaryDirectory(String prefix) {
while (true) {
- String candidateName = prefix + TEMPORARY_DIRECTORY_PRNG.nextInt();
+ String candidateName = prefix + Math.randomIntInternal();
File result = new File(System.getProperty("java.io.tmpdir"), candidateName);
if (result.mkdir()) {
return result;
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
index 917a3a8..020663e 100644
--- a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
+++ b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
@@ -198,8 +198,8 @@
}
}
- // RFC 3852 section 9.2: it authAttrs is present, it must have a
- // message digest entry.
+ // RFC 2315 section 9.1: if authenticatedAttributes is present, it
+ // must have a message-digest attribute.
if (existingDigest == null) {
throw new SecurityException("Missing MessageDigest in Authenticated Attributes");
}
diff --git a/luni/src/main/native/IcuUtilities.cpp b/luni/src/main/native/IcuUtilities.cpp
index 7ce2168..b740719 100644
--- a/luni/src/main/native/IcuUtilities.cpp
+++ b/luni/src/main/native/IcuUtilities.cpp
@@ -22,7 +22,6 @@
#include "JniException.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
-#include "UniquePtr.h"
#include "cutils/log.h"
#include "unicode/strenum.h"
#include "unicode/uloc.h"
diff --git a/luni/src/main/native/ZipUtilities.cpp b/luni/src/main/native/ZipUtilities.cpp
index 745b3b1..50da6f6 100644
--- a/luni/src/main/native/ZipUtilities.cpp
+++ b/luni/src/main/native/ZipUtilities.cpp
@@ -15,9 +15,10 @@
* limitations under the License.
*/
+#include <memory>
+
#include "JniConstants.h"
#include "JniException.h"
-#include "UniquePtr.h"
#include "ZipUtilities.h"
void throwExceptionForZlibError(JNIEnv* env, const char* exceptionClassName, int error,
@@ -31,7 +32,7 @@
}
}
-NativeZipStream::NativeZipStream() : input(NULL), inCap(0), mDict(NULL) {
+NativeZipStream::NativeZipStream() : inCap(0) {
// Let zlib use its default allocator.
stream.opaque = Z_NULL;
stream.zalloc = Z_NULL;
@@ -43,7 +44,7 @@
void NativeZipStream::setDictionary(JNIEnv* env, jbyteArray javaDictionary, int off, int len,
bool inflate) {
- UniquePtr<jbyte[]> dictionaryBytes(new jbyte[len]);
+ std::unique_ptr<jbyte[]> dictionaryBytes(new jbyte[len]);
if (dictionaryBytes.get() == NULL) {
jniThrowOutOfMemoryError(env, NULL);
return;
diff --git a/luni/src/main/native/ZipUtilities.h b/luni/src/main/native/ZipUtilities.h
index fe0f977..0c27bb8 100644
--- a/luni/src/main/native/ZipUtilities.h
+++ b/luni/src/main/native/ZipUtilities.h
@@ -18,13 +18,13 @@
#ifndef ZIP_UTILITIES_H_included
#define ZIP_UTILITIES_H_included
-#include "UniquePtr.h"
+#include <memory>
#include "jni.h"
#include "zlib.h"
class NativeZipStream {
public:
- UniquePtr<jbyte[]> input;
+ std::unique_ptr<jbyte[]> input;
int inCap;
z_stream stream;
@@ -34,7 +34,7 @@
void setInput(JNIEnv* env, jbyteArray buf, jint off, jint len);
private:
- UniquePtr<jbyte[]> mDict;
+ std::unique_ptr<jbyte[]> mDict;
// Disallow copy and assignment.
NativeZipStream(const NativeZipStream&);
diff --git a/luni/src/main/native/java_lang_StrictMath.cpp b/luni/src/main/native/java_lang_StrictMath.cpp
index cfe375e..e8c6dfb 100644
--- a/luni/src/main/native/java_lang_StrictMath.cpp
+++ b/luni/src/main/native/java_lang_StrictMath.cpp
@@ -34,26 +34,6 @@
return ieee_tan(a);
}
-static jdouble StrictMath_asin(JNIEnv*, jclass, jdouble a) {
- return ieee_asin(a);
-}
-
-static jdouble StrictMath_acos(JNIEnv*, jclass, jdouble a) {
- return ieee_acos(a);
-}
-
-static jdouble StrictMath_atan(JNIEnv*, jclass, jdouble a) {
- return ieee_atan(a);
-}
-
-static jdouble StrictMath_exp(JNIEnv*, jclass, jdouble a) {
- return ieee_exp(a);
-}
-
-static jdouble StrictMath_log(JNIEnv*, jclass, jdouble a) {
- return ieee_log(a);
-}
-
static jdouble StrictMath_sqrt(JNIEnv*, jclass, jdouble a) {
return ieee_sqrt(a);
}
@@ -74,75 +54,30 @@
return ieee_rint(a);
}
-static jdouble StrictMath_atan2(JNIEnv*, jclass, jdouble a, jdouble b) {
- return ieee_atan2(a, b);
-}
-
static jdouble StrictMath_pow(JNIEnv*, jclass, jdouble a, jdouble b) {
return ieee_pow(a,b);
}
-static jdouble StrictMath_sinh(JNIEnv*, jclass, jdouble a) {
- return ieee_sinh(a);
-}
-
-static jdouble StrictMath_tanh(JNIEnv*, jclass, jdouble a) {
- return ieee_tanh(a);
-}
-
-static jdouble StrictMath_cosh(JNIEnv*, jclass, jdouble a) {
- return ieee_cosh(a);
-}
-
-static jdouble StrictMath_log10(JNIEnv*, jclass, jdouble a) {
- return ieee_log10(a);
-}
-
-static jdouble StrictMath_cbrt(JNIEnv*, jclass, jdouble a) {
- return ieee_cbrt(a);
-}
-
-static jdouble StrictMath_expm1(JNIEnv*, jclass, jdouble a) {
- return ieee_expm1(a);
-}
-
static jdouble StrictMath_hypot(JNIEnv*, jclass, jdouble a, jdouble b) {
return ieee_hypot(a, b);
}
-static jdouble StrictMath_log1p(JNIEnv*, jclass, jdouble a) {
- return ieee_log1p(a);
-}
-
static jdouble StrictMath_nextafter(JNIEnv*, jclass, jdouble a, jdouble b) {
return ieee_nextafter(a, b);
}
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(StrictMath, IEEEremainder, "!(DD)D"),
- NATIVE_METHOD(StrictMath, acos, "!(D)D"),
- NATIVE_METHOD(StrictMath, asin, "!(D)D"),
- NATIVE_METHOD(StrictMath, atan, "!(D)D"),
- NATIVE_METHOD(StrictMath, atan2, "!(DD)D"),
- NATIVE_METHOD(StrictMath, cbrt, "!(D)D"),
NATIVE_METHOD(StrictMath, ceil, "!(D)D"),
NATIVE_METHOD(StrictMath, cos, "!(D)D"),
- NATIVE_METHOD(StrictMath, cosh, "!(D)D"),
- NATIVE_METHOD(StrictMath, exp, "!(D)D"),
- NATIVE_METHOD(StrictMath, expm1, "!(D)D"),
NATIVE_METHOD(StrictMath, floor, "!(D)D"),
NATIVE_METHOD(StrictMath, hypot, "!(DD)D"),
- NATIVE_METHOD(StrictMath, log, "!(D)D"),
- NATIVE_METHOD(StrictMath, log10, "!(D)D"),
- NATIVE_METHOD(StrictMath, log1p, "!(D)D"),
NATIVE_METHOD(StrictMath, nextafter, "!(DD)D"),
NATIVE_METHOD(StrictMath, pow, "!(DD)D"),
NATIVE_METHOD(StrictMath, rint, "!(D)D"),
NATIVE_METHOD(StrictMath, sin, "!(D)D"),
- NATIVE_METHOD(StrictMath, sinh, "!(D)D"),
NATIVE_METHOD(StrictMath, sqrt, "!(D)D"),
NATIVE_METHOD(StrictMath, tan, "!(D)D"),
- NATIVE_METHOD(StrictMath, tanh, "!(D)D"),
};
void register_java_lang_StrictMath(JNIEnv* env) {
jniRegisterNativeMethods(env, "java/lang/StrictMath", gMethods, NELEM(gMethods));
diff --git a/luni/src/main/native/java_lang_System.cpp b/luni/src/main/native/java_lang_System.cpp
index 944c0c3..c237ce4 100644
--- a/luni/src/main/native/java_lang_System.cpp
+++ b/luni/src/main/native/java_lang_System.cpp
@@ -84,7 +84,11 @@
properties.push_back(std::string("user.dir=") + getcwd(path, sizeof(path)));
properties.push_back("android.zlib.version=" ZLIB_VERSION);
+#if defined(OPENSSL_IS_BORINGSSL)
+ properties.push_back("android.openssl.version=BoringSSL");
+#else
properties.push_back("android.openssl.version=" OPENSSL_VERSION_TEXT);
+#endif
const char* library_path = getenv("LD_LIBRARY_PATH");
#if defined(HAVE_ANDROID_OS)
diff --git a/luni/src/main/native/java_math_NativeBN.cpp b/luni/src/main/native/java_math_NativeBN.cpp
index be87ea6..7e77e23 100644
--- a/luni/src/main/native/java_math_NativeBN.cpp
+++ b/luni/src/main/native/java_math_NativeBN.cpp
@@ -21,19 +21,31 @@
#include "JniException.h"
#include "ScopedPrimitiveArray.h"
#include "ScopedUtfChars.h"
-#include "UniquePtr.h"
#include "jni.h"
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <stdio.h>
+#include <memory>
+
+#if defined(OPENSSL_IS_BORINGSSL)
+/* BoringSSL no longer exports |bn_check_top|. */
+static void bn_check_top(const BIGNUM* bn) {
+ /* This asserts that |bn->top| (which contains the number of elements of
+ * |bn->d| that are valid) is minimal. In other words, that there aren't
+ * superfluous zeros. */
+ if (bn != NULL && bn->top != 0 && bn->d[bn->top-1] == 0) {
+ abort();
+ }
+}
+#endif
struct BN_CTX_Deleter {
void operator()(BN_CTX* p) const {
BN_CTX_free(p);
}
};
-typedef UniquePtr<BN_CTX, BN_CTX_Deleter> Unique_BN_CTX;
+typedef std::unique_ptr<BN_CTX, BN_CTX_Deleter> Unique_BN_CTX;
static BIGNUM* toBigNum(jlong address) {
return reinterpret_cast<BIGNUM*>(static_cast<uintptr_t>(address));
@@ -109,28 +121,32 @@
}
static void NativeBN_putULongInt(JNIEnv* env, jclass, jlong a0, jlong java_dw, jboolean neg) {
- if (!oneValidHandle(env, a0)) return;
+ if (!oneValidHandle(env, a0)) return;
- uint64_t dw = java_dw;
+ uint64_t dw = java_dw;
+ BIGNUM* a = toBigNum(a0);
+ int ok;
- // cf. litEndInts2bn:
- BIGNUM* a = toBigNum(a0);
- bn_check_top(a);
- if (bn_wexpand(a, 8/BN_BYTES) != NULL) {
-#ifdef __LP64__
+ static_assert(sizeof(dw) == sizeof(BN_ULONG) ||
+ sizeof(dw) == 2*sizeof(BN_ULONG), "Unknown BN configuration");
+
+ if (sizeof(dw) == sizeof(BN_ULONG)) {
+ ok = BN_set_word(a, dw);
+ } else if (sizeof(dw) == 2 * sizeof(BN_ULONG)) {
+ ok = (bn_wexpand(a, 2) != NULL);
+ if (ok) {
a->d[0] = dw;
-#else
- unsigned int hi = dw >> 32; // This shifts without sign extension.
- int lo = (int)dw; // This truncates implicitly.
- a->d[0] = lo;
- a->d[1] = hi;
-#endif
- a->top = 8 / BN_BYTES;
- a->neg = neg;
+ a->d[1] = dw >> 32;
+ a->top = 2;
bn_correct_top(a);
- } else {
- throwExceptionIfNecessary(env);
}
+ }
+
+ BN_set_negative(a, neg);
+
+ if (!ok) {
+ throwExceptionIfNecessary(env);
+ }
}
static void NativeBN_putLongInt(JNIEnv* env, jclass cls, jlong a, jlong dw) {
@@ -240,25 +256,25 @@
bn_check_top(ret);
// FIXME: assert bytesLen > 0
- int wLen = (bytesLen + BN_BYTES - 1) / BN_BYTES;
+ int wLen = (bytesLen + sizeof(BN_ULONG) - 1) / sizeof(BN_ULONG);
int firstNonzeroDigit = -2;
if (bn_wexpand(ret, wLen) != NULL) {
BN_ULONG* d = ret->d;
BN_ULONG di;
ret->top = wLen;
- int highBytes = bytesLen % BN_BYTES;
+ int highBytes = bytesLen % sizeof(BN_ULONG);
int k = bytesLen;
// Put bytes to the int array starting from the end of the byte array
int i = 0;
while (k > highBytes) {
- k -= BN_BYTES;
+ k -= sizeof(BN_ULONG);
di = BYTES2ULONG(bytes, k);
if (di != 0) {
d[i] = -di;
firstNonzeroDigit = i;
i++;
while (k > highBytes) {
- k -= BN_BYTES;
+ k -= sizeof(BN_ULONG);
d[i] = ~BYTES2ULONG(bytes, k);
i++;
}
@@ -394,7 +410,7 @@
if (wLen == 0) {
return NULL;
}
- jintArray result = env->NewIntArray(wLen * BN_BYTES/sizeof(unsigned int));
+ jintArray result = env->NewIntArray(wLen * sizeof(BN_ULONG)/sizeof(unsigned int));
if (result == NULL) {
return NULL;
}
@@ -445,7 +461,7 @@
do { i--; } while (!((i < 0) || (d[i] != 0)));
if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
}
- return (wLen - 1) * BN_BYTES * 8 + BN_num_bits_word(msd);
+ return (wLen - 1) * sizeof(BN_ULONG) * 8 + BN_num_bits_word(msd);
}
static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, jlong a, int n) {
diff --git a/luni/src/main/native/java_text_Bidi.cpp b/luni/src/main/native/java_text_Bidi.cpp
index d9ef35d..6a3e751 100644
--- a/luni/src/main/native/java_text_Bidi.cpp
+++ b/luni/src/main/native/java_text_Bidi.cpp
@@ -22,14 +22,14 @@
#include "JniConstants.h"
#include "JniException.h"
#include "ScopedPrimitiveArray.h"
-#include "UniquePtr.h"
#include "unicode/ubidi.h"
#include <stdlib.h>
#include <string.h>
+#include <memory>
struct BiDiData {
- BiDiData(UBiDi* biDi) : mBiDi(biDi), mEmbeddingLevels(NULL) {
+ BiDiData(UBiDi* biDi) : mBiDi(biDi) {
}
~BiDiData() {
@@ -50,7 +50,7 @@
private:
UBiDi* mBiDi;
- UniquePtr<jbyte[]> mEmbeddingLevels;
+ std::unique_ptr<jbyte[]> mEmbeddingLevels;
// Disallow copy and assignment.
BiDiData(const BiDiData&);
@@ -98,7 +98,7 @@
if (maybeThrowIcuException(env, "ubidi_openSized", status)) {
return 0;
}
- UniquePtr<BiDiData> lineData(new BiDiData(sized));
+ std::unique_ptr<BiDiData> lineData(new BiDiData(sized));
ubidi_setLine(uBiDi(ptr), start, limit, lineData->uBiDi(), &status);
maybeThrowIcuException(env, "ubidi_setLine", status);
return reinterpret_cast<uintptr_t>(lineData.release());
@@ -168,7 +168,7 @@
const UBiDiLevel* levels = reinterpret_cast<const UBiDiLevel*>(levelBytes.get());
- UniquePtr<int[]> indexMap(new int[length]);
+ std::unique_ptr<int[]> indexMap(new int[length]);
ubidi_reorderVisual(levels, length, &indexMap[0]);
jintArray result = env->NewIntArray(length);
diff --git a/luni/src/main/native/java_util_jar_StrictJarFile.cpp b/luni/src/main/native/java_util_jar_StrictJarFile.cpp
index 7611749..f0cdbed 100644
--- a/luni/src/main/native/java_util_jar_StrictJarFile.cpp
+++ b/luni/src/main/native/java_util_jar_StrictJarFile.cpp
@@ -17,13 +17,13 @@
#define LOG_TAG "StrictJarFile"
+#include <memory>
#include <string>
#include "JNIHelp.h"
#include "JniConstants.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
-#include "UniquePtr.h"
#include "jni.h"
#include "ziparchive/zip_archive.h"
#include "cutils/log.h"
@@ -32,11 +32,10 @@
jniThrowException(env, "java/io/IOException", ErrorCodeString(errorCode));
}
-static jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName,
- const uint16_t nameLength) {
+static jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName) {
ScopedLocalRef<jclass> zipEntryClass(env, env->FindClass("java/util/zip/ZipEntry"));
const jmethodID zipEntryCtor = env->GetMethodID(zipEntryClass.get(), "<init>",
- "(Ljava/lang/String;Ljava/lang/String;JJJIII[BIJJ)V");
+ "(Ljava/lang/String;Ljava/lang/String;JJJIII[BJJ)V");
return env->NewObject(zipEntryClass.get(),
zipEntryCtor,
@@ -49,7 +48,6 @@
static_cast<jint>(0), // time
static_cast<jint>(0), // modData
NULL, // byte[] extra
- static_cast<jint>(nameLength),
static_cast<jlong>(-1), // local header offset
static_cast<jlong>(entry.offset));
}
@@ -72,25 +70,20 @@
class IterationHandle {
public:
- IterationHandle(const char* prefix) :
- cookie_(NULL), prefix_(strdup(prefix)) {
+ IterationHandle() :
+ cookie_(NULL) {
}
void** CookieAddress() {
return &cookie_;
}
- const char* Prefix() const {
- return prefix_;
- }
-
~IterationHandle() {
- free(prefix_);
+ EndIteration(cookie_);
}
private:
void* cookie_;
- char* prefix_;
};
@@ -101,14 +94,15 @@
return static_cast<jlong>(-1);
}
- IterationHandle* handle = new IterationHandle(prefixChars.c_str());
+ IterationHandle* handle = new IterationHandle();
int32_t error = 0;
if (prefixChars.size() == 0) {
error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
handle->CookieAddress(), NULL);
} else {
+ ZipEntryName entry_name(prefixChars.c_str());
error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
- handle->CookieAddress(), handle->Prefix());
+ handle->CookieAddress(), &entry_name);
}
if (error) {
@@ -130,12 +124,12 @@
return NULL;
}
- UniquePtr<char[]> entryNameCString(new char[entryName.name_length + 1]);
+ std::unique_ptr<char[]> entryNameCString(new char[entryName.name_length + 1]);
memcpy(entryNameCString.get(), entryName.name, entryName.name_length);
entryNameCString[entryName.name_length] = '\0';
ScopedLocalRef<jstring> entryNameString(env, env->NewStringUTF(entryNameCString.get()));
- return newZipEntry(env, data, entryNameString.get(), entryName.name_length);
+ return newZipEntry(env, data, entryNameString.get());
}
static jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeHandle,
@@ -147,12 +141,12 @@
ZipEntry data;
const int32_t error = FindEntry(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
- entryNameChars.c_str(), &data);
+ ZipEntryName(entryNameChars.c_str()), &data);
if (error) {
return NULL;
}
- return newZipEntry(env, data, entryName, entryNameChars.size());
+ return newZipEntry(env, data, entryName);
}
static void StrictJarFile_nativeClose(JNIEnv*, jobject, jlong nativeHandle) {
diff --git a/luni/src/main/native/java_util_regex_Matcher.cpp b/luni/src/main/native/java_util_regex_Matcher.cpp
index 2e5259e..f2f1bf3 100644
--- a/luni/src/main/native/java_util_regex_Matcher.cpp
+++ b/luni/src/main/native/java_util_regex_Matcher.cpp
@@ -23,7 +23,6 @@
#include "JniConstants.h"
#include "JniException.h"
#include "ScopedPrimitiveArray.h"
-#include "UniquePtr.h"
#include "jni.h"
#include "unicode/parseerr.h"
#include "unicode/regex.h"
diff --git a/luni/src/main/native/java_util_zip_Deflater.cpp b/luni/src/main/native/java_util_zip_Deflater.cpp
index 1afd36e..43adae7 100644
--- a/luni/src/main/native/java_util_zip_Deflater.cpp
+++ b/luni/src/main/native/java_util_zip_Deflater.cpp
@@ -40,7 +40,7 @@
}
static jlong Deflater_createStream(JNIEnv * env, jobject, jint level, jint strategy, jboolean noHeader) {
- UniquePtr<NativeZipStream> jstream(new NativeZipStream);
+ std::unique_ptr<NativeZipStream> jstream(new NativeZipStream);
if (jstream.get() == NULL) {
jniThrowOutOfMemoryError(env, NULL);
return -1;
diff --git a/luni/src/main/native/java_util_zip_Inflater.cpp b/luni/src/main/native/java_util_zip_Inflater.cpp
index ca3ee09..a8a4744 100644
--- a/luni/src/main/native/java_util_zip_Inflater.cpp
+++ b/luni/src/main/native/java_util_zip_Inflater.cpp
@@ -25,7 +25,7 @@
#include <errno.h>
static jlong Inflater_createStream(JNIEnv* env, jobject, jboolean noHeader) {
- UniquePtr<NativeZipStream> jstream(new NativeZipStream);
+ std::unique_ptr<NativeZipStream> jstream(new NativeZipStream);
if (jstream.get() == NULL) {
jniThrowOutOfMemoryError(env, NULL);
return -1;
diff --git a/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
index a3258c1..5221baa 100644
--- a/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
+++ b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
@@ -20,7 +20,6 @@
#include "JniConstants.h"
#include "ScopedIcuLocale.h"
#include "ScopedJavaUnicodeString.h"
-#include "UniquePtr.h"
#include "cutils/log.h"
#include "unicode/dtitvfmt.h"
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index d27b11d..34b8ee0 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -25,7 +25,6 @@
#include "ScopedJavaUnicodeString.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
-#include "UniquePtr.h"
#include "cutils/log.h"
#include "toStringArray.h"
#include "unicode/brkiter.h"
@@ -62,15 +61,9 @@
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
+#include <memory>
#include <vector>
-// TODO: put this in a header file and use it everywhere!
-// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions.
-// It goes in the private: declarations in a class.
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
-
class ScopedResourceBundle {
public:
ScopedResourceBundle(UResourceBundle* bundle) : bundle_(bundle) {
@@ -386,7 +379,7 @@
UErrorCode status = U_ZERO_ERROR;
UnicodeString pattern;
- UniquePtr<DecimalFormat> fmt(static_cast<DecimalFormat*>(NumberFormat::createInstance(locale, UNUM_CURRENCY, status)));
+ std::unique_ptr<DecimalFormat> fmt(static_cast<DecimalFormat*>(NumberFormat::createInstance(locale, UNUM_CURRENCY, status)));
pattern = fmt->toPattern(pattern.remove());
setStringField(env, obj, "currencyPattern", pattern);
@@ -521,7 +514,7 @@
}
// We title-case the strings so they have consistent capitalization (http://b/14493853).
- UniquePtr<BreakIterator> brk(BreakIterator::createSentenceInstance(locale, status));
+ std::unique_ptr<BreakIterator> brk(BreakIterator::createSentenceInstance(locale, status));
if (U_FAILURE(status)) {
ALOGE("Error getting yesterday/today/tomorrow break iterator for %s: %s", locale_name, u_errorName(status));
return false;
@@ -591,7 +584,7 @@
}
status = U_ZERO_ERROR;
- UniquePtr<Calendar> cal(Calendar::createInstance(icuLocale.locale(), status));
+ std::unique_ptr<Calendar> cal(Calendar::createInstance(icuLocale.locale(), status));
if (U_FAILURE(status)) {
return JNI_FALSE;
}
@@ -746,7 +739,7 @@
}
UErrorCode status = U_ZERO_ERROR;
- UniquePtr<DateTimePatternGenerator> generator(DateTimePatternGenerator::createInstance(icuLocale.locale(), status));
+ std::unique_ptr<DateTimePatternGenerator> generator(DateTimePatternGenerator::createInstance(icuLocale.locale(), status));
if (maybeThrowIcuException(env, "DateTimePatternGenerator::createInstance", status)) {
return NULL;
}
diff --git a/luni/src/main/native/libcore_icu_NativeCollation.cpp b/luni/src/main/native/libcore_icu_NativeCollation.cpp
index 4ce42ec..f27d72e 100644
--- a/luni/src/main/native/libcore_icu_NativeCollation.cpp
+++ b/luni/src/main/native/libcore_icu_NativeCollation.cpp
@@ -15,10 +15,10 @@
#include "JniException.h"
#include "ScopedStringChars.h"
#include "ScopedUtfChars.h"
-#include "UniquePtr.h"
#include "unicode/ucol.h"
#include "unicode/ucoleitr.h"
#include <cutils/log.h>
+#include <memory>
// Manages a UCollationElements instance along with the jchar
// array it is iterating over. The associated array can be unpinned
@@ -124,7 +124,7 @@
return -1;
}
- UniquePtr<CollationElements> ce(new CollationElements);
+ std::unique_ptr<CollationElements> ce(new CollationElements);
UErrorCode status = ce->start(env, javaSource, toCollator(address));
maybeThrowIcuException(env, "ucol_openElements", status);
if (status == U_ZERO_ERROR) {
@@ -156,7 +156,7 @@
const UCollator* collator = toCollator(address);
// The buffer size prevents reallocation for most strings.
uint8_t byteArray[128];
- UniquePtr<uint8_t[]> largerByteArray;
+ std::unique_ptr<uint8_t[]> largerByteArray;
uint8_t* usedByteArray = byteArray;
size_t byteArraySize = ucol_getSortKey(collator, source.get(), source.size(), usedByteArray, sizeof(byteArray) - 1);
if (byteArraySize > sizeof(byteArray) - 1) {
diff --git a/luni/src/main/native/libcore_icu_NativeConverter.cpp b/luni/src/main/native/libcore_icu_NativeConverter.cpp
index 8dd439a..717bfc3 100644
--- a/luni/src/main/native/libcore_icu_NativeConverter.cpp
+++ b/luni/src/main/native/libcore_icu_NativeConverter.cpp
@@ -23,7 +23,6 @@
#include "ScopedPrimitiveArray.h"
#include "ScopedStringChars.h"
#include "ScopedUtfChars.h"
-#include "UniquePtr.h"
#include "cutils/log.h"
#include "toStringArray.h"
#include "unicode/ucnv.h"
@@ -32,6 +31,7 @@
#include "unicode/ustring.h"
#include "unicode/utypes.h"
+#include <memory>
#include <vector>
#include <stdlib.h>
@@ -150,7 +150,7 @@
if (name == NULL) {
name = icuCanonicalName;
}
- UniquePtr<char[]> result(new char[2 + strlen(name) + 1]);
+ std::unique_ptr<char[]> result(new char[2 + strlen(name) + 1]);
strcpy(&result[0], "x-");
strcat(&result[0], name);
return env->NewStringUTF(&result[0]);
diff --git a/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp b/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp
index 8e440e9..0527213 100644
--- a/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp
+++ b/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <string.h>
+#include <memory>
#include <vector>
#include "cutils/log.h"
@@ -36,7 +37,6 @@
#include "unicode/numfmt.h"
#include "unicode/unum.h"
#include "unicode/ustring.h"
-#include "UniquePtr.h"
#include "valueOf.h"
static DecimalFormat* toDecimalFormat(jlong addr) {
@@ -179,7 +179,7 @@
UNumberFormatTextAttribute attr = static_cast<UNumberFormatTextAttribute>(javaAttr);
// Find out how long the result will be...
- UniquePtr<UChar[]> chars;
+ std::unique_ptr<UChar[]> chars;
uint32_t charCount = 0;
uint32_t desiredCount = unum_getTextAttribute(fmt, attr, chars.get(), charCount, &status);
if (status == U_BUFFER_OVERFLOW_ERROR) {
diff --git a/luni/src/main/native/libcore_icu_TimeZoneNames.cpp b/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
index a7c9098..2fa06c7 100644
--- a/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
+++ b/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
@@ -16,6 +16,8 @@
#define LOG_TAG "TimeZoneNames"
+#include <memory>
+
#include "IcuUtilities.h"
#include "JNIHelp.h"
#include "JniConstants.h"
@@ -24,7 +26,6 @@
#include "ScopedJavaUnicodeString.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
-#include "UniquePtr.h"
#include "unicode/calendar.h"
#include "unicode/timezone.h"
#include "unicode/tznames.h"
@@ -67,7 +68,7 @@
}
UErrorCode status = U_ZERO_ERROR;
- UniquePtr<TimeZoneNames> names(TimeZoneNames::createInstance(icuLocale.locale(), status));
+ std::unique_ptr<TimeZoneNames> names(TimeZoneNames::createInstance(icuLocale.locale(), status));
if (maybeThrowIcuException(env, "TimeZoneNames::createInstance", status)) {
return;
}
@@ -123,7 +124,7 @@
}
UErrorCode status = U_ZERO_ERROR;
- UniquePtr<TimeZoneNames> names(TimeZoneNames::createInstance(icuLocale.locale(), status));
+ std::unique_ptr<TimeZoneNames> names(TimeZoneNames::createInstance(icuLocale.locale(), status));
if (maybeThrowIcuException(env, "TimeZoneNames::createInstance", status)) {
return NULL;
}
diff --git a/luni/src/main/native/libcore_io_Memory.cpp b/luni/src/main/native/libcore_io_Memory.cpp
index 9edbfb8..70bd9e4 100644
--- a/luni/src/main/native/libcore_io_Memory.cpp
+++ b/luni/src/main/native/libcore_io_Memory.cpp
@@ -21,7 +21,6 @@
#include "Portability.h"
#include "ScopedBytes.h"
#include "ScopedPrimitiveArray.h"
-#include "UniquePtr.h"
#include <errno.h>
#include <stdlib.h>
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index e8e8efb..9ae2378 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -31,7 +31,6 @@
#include "ScopedPrimitiveArray.h"
#include "ScopedUtfChars.h"
#include "toStringArray.h"
-#include "UniquePtr.h"
#include <arpa/inet.h>
#include <errno.h>
@@ -61,7 +60,7 @@
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
-
+#include <memory>
#ifndef __unused
#define __unused __attribute__((__unused__))
@@ -451,7 +450,7 @@
}
JNIEnv* mEnv;
- UniquePtr<char[]> mBuffer;
+ std::unique_ptr<char[]> mBuffer;
size_t mBufferSize;
struct passwd mPwd;
struct passwd* mResult;
@@ -684,7 +683,7 @@
addrinfo* addressList = NULL;
errno = 0;
int rc = android_getaddrinfofornet(node.c_str(), NULL, &hints, netId, 0, &addressList);
- UniquePtr<addrinfo, addrinfo_deleter> addressListDeleter(addressList);
+ std::unique_ptr<addrinfo, addrinfo_deleter> addressListDeleter(addressList);
if (rc != 0) {
throwGaiException(env, "android_getaddrinfo", rc);
return NULL;
@@ -873,8 +872,9 @@
return 0;
}
return static_cast<jint>(owner);
+#elif defined(__BIONIC__)
+ return gettid();
#else
- // Neither bionic nor glibc exposes gettid(2).
return syscall(__NR_gettid);
#endif
}
@@ -1068,7 +1068,7 @@
// Turn the Java android.system.StructPollfd[] into a C++ struct pollfd[].
size_t arrayLength = env->GetArrayLength(javaStructs);
- UniquePtr<struct pollfd[]> fds(new struct pollfd[arrayLength]);
+ std::unique_ptr<struct pollfd[]> fds(new struct pollfd[arrayLength]);
memset(fds.get(), 0, sizeof(struct pollfd) * arrayLength);
size_t count = 0; // Some trailing array elements may be irrelevant. (See below.)
for (size_t i = 0; i < arrayLength; ++i) {
diff --git a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index 2ea8806..ed0ee8b 100644
--- a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -24,11 +24,12 @@
#include "ScopedPrimitiveArray.h"
#include "ScopedStringChars.h"
#include "ScopedUtfChars.h"
-#include "UniquePtr.h"
#include "jni.h"
#include "cutils/log.h"
#include "unicode/unistr.h"
+#include <memory>
+
#include <string.h>
#include <libexpat/expat.h>
@@ -253,7 +254,7 @@
*/
static InternedString* newInternedString(JNIEnv* env, const char* bytes, int hash) {
// Allocate a new wrapper.
- UniquePtr<InternedString> wrapper(new InternedString);
+ std::unique_ptr<InternedString> wrapper(new InternedString);
if (wrapper.get() == NULL) {
jniThrowOutOfMemoryError(env, NULL);
return NULL;
@@ -962,7 +963,7 @@
static jlong ExpatParser_initialize(JNIEnv* env, jobject object, jstring javaEncoding,
jboolean processNamespaces) {
// Allocate parsing context.
- UniquePtr<ParsingContext> context(new ParsingContext(object));
+ std::unique_ptr<ParsingContext> context(new ParsingContext(object));
if (context.get() == NULL) {
jniThrowOutOfMemoryError(env, NULL);
return 0;
diff --git a/luni/src/test/java/libcore/icu/LocaleDataTest.java b/luni/src/test/java/libcore/icu/LocaleDataTest.java
index 0a83c53..9ad6687 100644
--- a/luni/src/test/java/libcore/icu/LocaleDataTest.java
+++ b/luni/src/test/java/libcore/icu/LocaleDataTest.java
@@ -24,7 +24,7 @@
for (Locale l : Locale.getAvailableLocales()) {
LocaleData d = LocaleData.get(l);
// System.err.format("%20s %s %s %s\n", l, d.yesterday, d.today, d.tomorrow);
- // System.err.format("%20s %10s %10s\n", l, d.timeFormat12, d.timeFormat24);
+ // System.err.format("%20s %10s %10s\n", l, d.timeFormat_hm, d.timeFormat_Hm);
}
}
@@ -124,11 +124,11 @@
// http://b/7924970
public void testTimeFormat12And24() throws Exception {
LocaleData en_US = LocaleData.get(Locale.US);
- assertEquals("h:mm a", en_US.timeFormat12);
- assertEquals("HH:mm", en_US.timeFormat24);
+ assertEquals("h:mm a", en_US.timeFormat_hm);
+ assertEquals("HH:mm", en_US.timeFormat_Hm);
LocaleData ja_JP = LocaleData.get(Locale.JAPAN);
- assertEquals("aK:mm", ja_JP.timeFormat12);
- assertEquals("H:mm", ja_JP.timeFormat24);
+ assertEquals("aK:mm", ja_JP.timeFormat_hm);
+ assertEquals("H:mm", ja_JP.timeFormat_Hm);
}
}
diff --git a/luni/src/test/java/libcore/java/net/OldSocketTest.java b/luni/src/test/java/libcore/java/net/OldSocketTest.java
index b0125ac..6575d8c 100644
--- a/luni/src/test/java/libcore/java/net/OldSocketTest.java
+++ b/luni/src/test/java/libcore/java/net/OldSocketTest.java
@@ -37,6 +37,7 @@
import java.nio.channels.IllegalBlockingModeException;
import java.nio.channels.SocketChannel;
import java.security.Permission;
+import tests.net.StuckServer;
import tests.support.Support_Configuration;
public class OldSocketTest extends OldSocketTestCase {
@@ -931,25 +932,15 @@
}
// start by validating the error checks
- int portNumber = 0;
+
+ byte[] theBytes = { 0, 0, 0, 0 };
+ SocketAddress theAddress = new InetSocketAddress(InetAddress.getLocalHost(), 0);
+ SocketAddress nonConnectableAddress = new InetSocketAddress(InetAddress.getByAddress(theBytes), 0);
+ SocketAddress nonReachableAddress = new InetSocketAddress(StuckServer.UNREACHABLE_ADDRESS, 0);
+ SocketAddress invalidType = new mySocketAddress();
+
Socket theSocket = null;
ServerSocket serverSocket = null;
- SocketAddress theAddress = null;
- SocketAddress nonConnectableAddress = null;
- SocketAddress nonReachableAddress = null;
- SocketAddress invalidType = null;
- // byte[] theBytes = {-1,-1,-1,-1};
- byte[] theBytes = { 0, 0, 0, 0 };
- theAddress = new InetSocketAddress(InetAddress.getLocalHost(),
- portNumber);
- nonConnectableAddress = new InetSocketAddress(InetAddress
- .getByAddress(theBytes), portNumber);
- nonReachableAddress = new InetSocketAddress(InetAddress
- .getByName(Support_Configuration.ResolvedNotExistingHost),
- portNumber);
-
- invalidType = new mySocketAddress();
-
try {
theSocket = new Socket();
theSocket.connect(null);
@@ -1164,7 +1155,7 @@
byte[] theBytes = { 0, 0, 0, 0 };
SocketAddress theAddress = new InetSocketAddress(InetAddress.getLocalHost(), 0);
SocketAddress nonConnectableAddress = new InetSocketAddress(InetAddress.getByAddress(theBytes), 0);
- SocketAddress nonReachableAddress = new InetSocketAddress(InetAddress.getByName(Support_Configuration.ResolvedNotExistingHost), 0);
+ SocketAddress nonReachableAddress = new InetSocketAddress(StuckServer.UNREACHABLE_ADDRESS, 0);
SocketAddress invalidType = new mySocketAddress();
Socket theSocket = null;
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index a2fd6f4..8319882 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -642,42 +642,32 @@
* Tolerate bad https proxy response when using HttpResponseCache. http://b/6754912
*/
public void testConnectViaHttpProxyToHttpsUsingBadProxyAndHttpResponseCache() throws Exception {
- ProxyConfig proxyConfig = ProxyConfig.PROXY_SYSTEM_PROPERTY;
-
TestSSLContext testSSLContext = TestSSLContext.create();
initResponseCache();
server.useHttps(testSSLContext.serverContext.getSocketFactory(), true);
+
+ // The inclusion of a body in the response to the CONNECT is key to reproducing b/6754912.
MockResponse badProxyResponse = new MockResponse()
.setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END)
.clearHeaders()
- .setBody("bogus proxy connect response content"); // Key to reproducing b/6754912
+ .setBody("bogus proxy connect response content");
- // We enqueue the bad response twice because the connection will
- // be retried with TLS_MODE_COMPATIBLE after the first connection
- // fails.
server.enqueue(badProxyResponse);
- server.enqueue(badProxyResponse);
+ server.enqueue(new MockResponse().setBody("response"));
server.play();
URL url = new URL("https://android.com/foo");
+ ProxyConfig proxyConfig = ProxyConfig.PROXY_SYSTEM_PROPERTY;
HttpsURLConnection connection = (HttpsURLConnection) proxyConfig.connect(server, url);
connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
-
- try {
- connection.connect();
- fail();
- } catch (SSLHandshakeException expected) {
- // Thrown when the connect causes SSLSocket.startHandshake() to throw
- // when it sees the "bogus proxy connect response content"
- // instead of a ServerHello handshake message.
- }
+ connection.setHostnameVerifier(new RecordingHostnameVerifier());
+ assertContent("response", connection);
RecordedRequest connect = server.takeRequest();
- assertEquals("Connect line failure on proxy",
- "CONNECT android.com:443 HTTP/1.1", connect.getRequestLine());
+ assertEquals("CONNECT android.com:443 HTTP/1.1", connect.getRequestLine());
assertContains(connect.getHeaders(), "Host: android.com");
}
diff --git a/luni/src/test/java/libcore/java/security/cert/CertificateFactoryTest.java b/luni/src/test/java/libcore/java/security/cert/CertificateFactoryTest.java
index e2f21e8..30185d1 100644
--- a/luni/src/test/java/libcore/java/security/cert/CertificateFactoryTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/CertificateFactoryTest.java
@@ -17,10 +17,10 @@
package libcore.java.security.cert;
import com.android.org.bouncycastle.asn1.x509.BasicConstraints;
+import com.android.org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
import com.android.org.bouncycastle.asn1.x509.X509Extensions;
import com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
import com.android.org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
-import com.android.org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -571,7 +571,7 @@
}
certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,
- new SubjectKeyIdentifierStructure(keyPair.getPublic()));
+ SubjectKeyIdentifier.getInstance(keyPair.getPublic().getEncoded()));
certGen.addExtension(X509Extensions.BasicConstraints, true, basicConstraints);
X509Certificate cert = certGen.generate(caKey);
diff --git a/luni/src/test/java/libcore/java/util/LocaleTest.java b/luni/src/test/java/libcore/java/util/LocaleTest.java
index c72ecd7..15e01a1 100644
--- a/luni/src/test/java/libcore/java/util/LocaleTest.java
+++ b/luni/src/test/java/libcore/java/util/LocaleTest.java
@@ -20,6 +20,7 @@
import java.text.Collator;
import java.text.DateFormat;
import java.text.DateFormatSymbols;
+import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Calendar;
import java.util.IllformedLocaleException;
@@ -1146,4 +1147,22 @@
assertEquals("variant", locale.getVariant());
assertEquals(locale, Locale.forLanguageTag(locale.toLanguageTag()));
}
+
+ public void testArabicDigits() throws Exception {
+ // ar-DZ uses latn digits by default, but we can override that.
+ Locale ar_DZ = Locale.forLanguageTag("ar-DZ");
+ Locale ar_DZ_arab = Locale.forLanguageTag("ar-DZ-u-nu-arab");
+ Locale ar_DZ_latn = Locale.forLanguageTag("ar-DZ-u-nu-latn");
+ assertEquals('0', new DecimalFormatSymbols(ar_DZ).getZeroDigit());
+ assertEquals('\u0660', new DecimalFormatSymbols(ar_DZ_arab).getZeroDigit());
+ assertEquals('0', new DecimalFormatSymbols(ar_DZ_latn).getZeroDigit());
+
+ // ar-EG uses arab digits by default, but we can override that.
+ Locale ar_EG = Locale.forLanguageTag("ar-EG");
+ Locale ar_EG_arab = Locale.forLanguageTag("ar-EG-u-nu-arab");
+ Locale ar_EG_latn = Locale.forLanguageTag("ar-EG-u-nu-latn");
+ assertEquals('\u0660', new DecimalFormatSymbols(ar_EG).getZeroDigit());
+ assertEquals('\u0660', new DecimalFormatSymbols(ar_EG_arab).getZeroDigit());
+ assertEquals('0', new DecimalFormatSymbols(ar_EG_latn).getZeroDigit());
+ }
}
diff --git a/luni/src/test/java/libcore/java/util/TimeZoneTest.java b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
index 86a8b7f..c40c974 100644
--- a/luni/src/test/java/libcore/java/util/TimeZoneTest.java
+++ b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
@@ -74,52 +74,31 @@
}
public void testPreHistoricOffsets() throws Exception {
- // The "Asia/Saigon" time zone has just a few transitions, and hasn't changed in a
- // long time, which is convenient for testing:
- //
- // libcore.util.ZoneInfo[Asia/Saigon,mRawOffset=25200000,mUseDst=false]
- // 0 : time=-2005974400 Fri Jun 08 16:53:20 1906 GMT+00:00 = Fri Jun 08 23:59:40 1906 ICT isDst=0 offset= 380 gmtOffset=25580
- // 1 : time=-1855983920 Fri Mar 10 16:54:40 1911 GMT+00:00 = Fri Mar 10 23:54:40 1911 ICT isDst=0 offset= 0 gmtOffset=25200
- // 2 : time=-1819954800 Tue Apr 30 17:00:00 1912 GMT+00:00 = Wed May 01 01:00:00 1912 ICT isDst=0 offset= 3600 gmtOffset=28800
- // 3 : time=-1220428800 Thu Apr 30 16:00:00 1931 GMT+00:00 = Thu Apr 30 23:00:00 1931 ICT isDst=0 offset= 0 gmtOffset=25200
- TimeZone tz = TimeZone.getTimeZone("Asia/Saigon");
+ // "Africa/Bissau" has just a few transitions and hasn't changed in a long time.
+ // 1912-01-01 00:02:19-0100 ... 1912-01-01 00:02:20-0100
+ // 1974-12-31 23:59:59-0100 ... 1975-01-01 01:00:00+0000
+ TimeZone tz = TimeZone.getTimeZone("Africa/Bissau");
// Times before our first transition should assume we're still following that transition.
- // Note: the RI reports 25600 here because it has more transitions than we do.
- assertNonDaylightOffset(25580, -2005975000L, tz);
+ assertNonDaylightOffset(-3600, parseIsoTime("1911-01-01T00:00:00.0+0000"), tz);
- assertNonDaylightOffset(25580, -2005974400L, tz); // 0
- assertNonDaylightOffset(25580, -2005974000L, tz);
+ assertNonDaylightOffset(-3600, parseIsoTime("1912-01-01T12:00:00.0-0100"), tz);
- assertNonDaylightOffset(25200, -1855983920L, tz); // 1
- assertNonDaylightOffset(25200, -1855983900L, tz);
-
- assertNonDaylightOffset(28800, -1819954800L, tz); // 2
- assertNonDaylightOffset(28800, -1819954000L, tz);
-
- assertNonDaylightOffset(25200, -1220428800L, tz); // 3
-
- // Times after out last transition should assume we're still following that transition.
- assertNonDaylightOffset(25200, -1220428000L, tz);
-
- // There are plenty more examples. "Africa/Bissau" is one:
- //
- // libcore.util.ZoneInfo[Africa/Bissau,mRawOffset=0,mUseDst=false]
- // 0 : time=-1849388260 Fri May 26 01:02:20 1911 GMT+00:00 = Fri May 26 00:02:20 1911 GMT isDst=0 offset=-3600 gmtOffset=-3600
- // 1 : time= 157770000 Wed Jan 01 01:00:00 1975 GMT+00:00 = Wed Jan 01 01:00:00 1975 GMT isDst=0 offset= 0 gmtOffset=0
- tz = TimeZone.getTimeZone("Africa/Bissau");
- assertNonDaylightOffset(-3600, -1849388300L, tz);
- assertNonDaylightOffset(-3600, -1849388260L, tz); // 0
- assertNonDaylightOffset(-3600, -1849388200L, tz);
- assertNonDaylightOffset(0, 157770000L, tz); // 1
- assertNonDaylightOffset(0, 157780000L, tz);
+ // Times after our last transition should assume we're still following that transition.
+ assertNonDaylightOffset(0, parseIsoTime("1980-01-01T00:00:00.0+0000"), tz);
}
private static void assertNonDaylightOffset(int expectedOffsetSeconds, long epochSeconds, TimeZone tz) {
- assertEquals(expectedOffsetSeconds * 1000, tz.getOffset(epochSeconds * 1000));
+ assertEquals(expectedOffsetSeconds, tz.getOffset(epochSeconds * 1000) / 1000);
assertFalse(tz.inDaylightTime(new Date(epochSeconds * 1000)));
}
+ private static long parseIsoTime(String isoTime) throws Exception {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+ Date date = sdf.parse(isoTime);
+ return date.getTime() / 1000;
+ }
+
public void testZeroTransitionZones() throws Exception {
// Zones with no transitions historical or future seem ideal for testing.
String[] ids = new String[] { "Africa/Bujumbura", "Indian/Cocos", "Pacific/Wake", "UTC" };
diff --git a/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java b/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
index feecebe..f50367a 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
@@ -132,6 +132,17 @@
assertFalse(verifier.verifyHostName("a.b.c.d", "*.c.d"));
}
+ public void testWildcardsRejectedForSingleLabelPatterns() {
+ assertFalse(verifier.verifyHostName("d", "*"));
+ assertFalse(verifier.verifyHostName("d.", "*."));
+ assertFalse(verifier.verifyHostName("d", "d*"));
+ assertFalse(verifier.verifyHostName("d.", "d*."));
+ assertFalse(verifier.verifyHostName("d", "*d"));
+ assertFalse(verifier.verifyHostName("d.", "*d."));
+ assertFalse(verifier.verifyHostName("ddd", "d*d"));
+ assertFalse(verifier.verifyHostName("ddd.", "d*d."));
+ }
+
public void testVerifyHostName() {
assertTrue(verifier.verifyHostName("a.b.c.d", "a.b.c.d"));
assertTrue(verifier.verifyHostName("a.b.c.d", "*.b.c.d"));
@@ -145,6 +156,37 @@
assertFalse(verifier.verifyHostName("imap.google.com", "a*.google.com"));
assertFalse(verifier.verifyHostName("imap.google.com", "ix*.google.com"));
assertTrue(verifier.verifyHostName("imap.google.com", "iMap.Google.Com"));
+ assertTrue(verifier.verifyHostName("weird", "weird"));
+ assertFalse(verifier.verifyHostName("weird", "weird."));
+
+ // Wildcards rejected for domain names consisting of fewer than two labels (excluding root).
+ assertFalse(verifier.verifyHostName("weird", "weird*"));
+ assertFalse(verifier.verifyHostName("weird", "*weird"));
+ assertFalse(verifier.verifyHostName("weird", "weird*."));
+ assertFalse(verifier.verifyHostName("weird", "weird.*"));
+ }
+
+ public void testVerifyAbsoluteHostName() {
+ assertTrue(verifier.verifyHostName("a.b.c.d.", "a.b.c.d"));
+ assertTrue(verifier.verifyHostName("a.b.c.d.", "*.b.c.d"));
+ assertFalse(verifier.verifyHostName("a.b.c.d.", "*.*.c.d"));
+ assertTrue(verifier.verifyHostName("imap.google.com.", "imap.google.com"));
+ assertFalse(verifier.verifyHostName("imap2.google.com.", "imap.google.com"));
+ assertTrue(verifier.verifyHostName("imap.google.com.", "*.google.com"));
+ assertTrue(verifier.verifyHostName("imap2.google.com.", "*.google.com"));
+ assertFalse(verifier.verifyHostName("imap.google.com.", "*.googl.com"));
+ assertFalse(verifier.verifyHostName("imap2.google2.com.", "*.google3.com"));
+ assertFalse(verifier.verifyHostName("imap.google.com.", "a*.google.com"));
+ assertFalse(verifier.verifyHostName("imap.google.com.", "ix*.google.com"));
+ assertTrue(verifier.verifyHostName("imap.google.com.", "iMap.Google.Com"));
+ assertTrue(verifier.verifyHostName("weird.", "weird"));
+ assertTrue(verifier.verifyHostName("weird.", "weird."));
+
+ // Wildcards rejected for domain names consisting of fewer than two labels (excluding root).
+ assertFalse(verifier.verifyHostName("weird.", "*weird"));
+ assertFalse(verifier.verifyHostName("weird.", "weird*"));
+ assertFalse(verifier.verifyHostName("weird.", "weird*."));
+ assertFalse(verifier.verifyHostName("weird.", "weird.*"));
}
public void testSubjectOnlyCert() throws Exception {
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLContextTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLContextTest.java
index dccadbd..533849c 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLContextTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLContextTest.java
@@ -26,7 +26,6 @@
import java.security.UnrecoverableKeyException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import libcore.io.IoUtils;
@@ -82,14 +81,14 @@
}
public void test_SSLContext_defaultConfiguration() throws Exception {
- SSLDefaultConfigurationAsserts.assertSSLContext(SSLContext.getDefault());
+ SSLConfigurationAsserts.assertSSLContextDefaultConfiguration(SSLContext.getDefault());
for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
SSLContext sslContext = SSLContext.getInstance(protocol);
if (!protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
sslContext.init(null, null, null);
}
- SSLDefaultConfigurationAsserts.assertSSLContext(sslContext);
+ SSLConfigurationAsserts.assertSSLContextDefaultConfiguration(sslContext);
}
}
@@ -149,6 +148,27 @@
sslContext);
}
+ public void test_SSLContext_init_correctProtocolVersionsEnabled() throws Exception {
+ for (String tlsVersion : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+ // Don't test the "Default" instance.
+ if (StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT.equals(tlsVersion)) {
+ continue;
+ }
+
+ SSLContext context = SSLContext.getInstance(tlsVersion);
+ context.init(null, null, null);
+
+ StandardNames.assertSSLContextEnabledProtocols(tlsVersion, ((SSLSocket) (context.getSocketFactory()
+ .createSocket())).getEnabledProtocols());
+ StandardNames.assertSSLContextEnabledProtocols(tlsVersion, ((SSLServerSocket) (context
+ .getServerSocketFactory().createServerSocket())).getEnabledProtocols());
+ StandardNames.assertSSLContextEnabledProtocols(tlsVersion, context.getDefaultSSLParameters()
+ .getProtocols());
+ StandardNames.assertSSLContextEnabledProtocols(tlsVersion, context.createSSLEngine()
+ .getEnabledProtocols());
+ }
+ }
+
private static void assertEnabledCipherSuites(
List<String> expectedCipherSuites, SSLContext sslContext) throws Exception {
assertContentsInOrder(
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
index fb7e0c9..5239977 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java
@@ -65,7 +65,7 @@
}
public void test_SSLEngine_defaultConfiguration() throws Exception {
- SSLDefaultConfigurationAsserts.assertSSLEngine(
+ SSLConfigurationAsserts.assertSSLEngineDefaultConfiguration(
TestSSLContext.create().clientContext.createSSLEngine());
}
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLServerSocketFactoryTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLServerSocketFactoryTest.java
index ea9c3f0..cda1fb8 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLServerSocketFactoryTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLServerSocketFactoryTest.java
@@ -22,7 +22,7 @@
public class SSLServerSocketFactoryTest extends TestCase {
public void testDefaultConfiguration() throws Exception {
- SSLDefaultConfigurationAsserts.assertSSLServerSocketFactory(
+ SSLConfigurationAsserts.assertSSLServerSocketFactoryDefaultConfiguration(
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault());
}
}
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLServerSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLServerSocketTest.java
index 59c44c1..d2c0f48 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLServerSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLServerSocketTest.java
@@ -24,7 +24,7 @@
public class SSLServerSocketTest extends TestCase {
public void testDefaultConfiguration() throws Exception {
- SSLDefaultConfigurationAsserts.assertSSLServerSocket(
+ SSLConfigurationAsserts.assertSSLServerSocketDefaultConfiguration(
(SSLServerSocket) SSLServerSocketFactory.getDefault().createServerSocket());
}
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketFactoryTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketFactoryTest.java
index acf69c0..83b690b 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketFactoryTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketFactoryTest.java
@@ -210,7 +210,7 @@
}
public void test_SSLSocketFactory_defaultConfiguration() throws Exception {
- SSLDefaultConfigurationAsserts.assertSSLSocketFactory(
+ SSLConfigurationAsserts.assertSSLSocketFactoryDefaultConfiguration(
(SSLSocketFactory) SSLSocketFactory.getDefault());
}
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
index ff055b2..abf8c89 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -16,6 +16,8 @@
package libcore.javax.net.ssl;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
@@ -64,11 +66,14 @@
import libcore.io.Streams;
import libcore.java.security.StandardNames;
import libcore.java.security.TestKeyStore;
+import libcore.tlswire.handshake.HandshakeMessage;
+import libcore.tlswire.record.TlsProtocols;
+import libcore.tlswire.record.TlsRecord;
public class SSLSocketTest extends TestCase {
public void test_SSLSocket_defaultConfiguration() throws Exception {
- SSLDefaultConfigurationAsserts.assertSSLSocket(
+ SSLConfigurationAsserts.assertSSLSocketDefaultConfiguration(
(SSLSocket) SSLSocketFactory.getDefault().createSocket());
}
@@ -1549,12 +1554,18 @@
});
// Wait for the ClientHello to arrive
- byte[] clientHello = readFirstReceivedChunkFuture.get(10, TimeUnit.SECONDS);
+ byte[] firstReceivedChunk = readFirstReceivedChunkFuture.get(10, TimeUnit.SECONDS);
// Check for ClientHello length that may cause handshake to fail/time out with older
// F5/BIG-IP appliances.
- assertEquals("TLS record type: handshake", 22, clientHello[0]);
- int fragmentLength = ((clientHello[3] & 0xff) << 8) | (clientHello[4] & 0xff);
+ TlsRecord firstReceivedTlsRecord = TlsRecord.read(
+ new DataInputStream(new ByteArrayInputStream(firstReceivedChunk)));
+ assertEquals("TLS record type", TlsProtocols.HANDSHAKE, firstReceivedTlsRecord.type);
+ HandshakeMessage handshakeMessage = HandshakeMessage.read(
+ new DataInputStream(new ByteArrayInputStream(firstReceivedTlsRecord.fragment)));
+ assertEquals("HandshakeMessage type",
+ HandshakeMessage.TYPE_CLIENT_HELLO, handshakeMessage.type);
+ int fragmentLength = firstReceivedTlsRecord.fragment.length;
if ((fragmentLength >= 256) && (fragmentLength <= 511)) {
fail("Fragment containing ClientHello is of dangerous length: "
+ fragmentLength + " bytes");
diff --git a/luni/src/test/java/libcore/net/MimeUtilsTest.java b/luni/src/test/java/libcore/net/MimeUtilsTest.java
index 9bfb375..ff22632 100644
--- a/luni/src/test/java/libcore/net/MimeUtilsTest.java
+++ b/luni/src/test/java/libcore/net/MimeUtilsTest.java
@@ -27,6 +27,12 @@
assertEquals("flac", MimeUtils.guessExtensionFromMimeType("application/x-flac"));
}
+ // https://code.google.com/p/android/issues/detail?id=78909
+ public void test_78909() {
+ assertEquals("mka", MimeUtils.guessExtensionFromMimeType("audio/x-matroska"));
+ assertEquals("mkv", MimeUtils.guessExtensionFromMimeType("video/x-matroska"));
+ }
+
public void test_16978217() {
assertEquals("image/x-ms-bmp", MimeUtils.guessMimeTypeFromExtension("bmp"));
assertEquals("image/x-icon", MimeUtils.guessMimeTypeFromExtension("ico"));
diff --git a/luni/src/test/native/test_openssl_engine.cpp b/luni/src/test/native/test_openssl_engine.cpp
index 9a0f3b3..4fb1ee1 100644
--- a/luni/src/test/native/test_openssl_engine.cpp
+++ b/luni/src/test/native/test_openssl_engine.cpp
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#include "UniquePtr.h"
-
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
@@ -24,6 +22,7 @@
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
+#include <memory>
#define DYNAMIC_ENGINE
#define TEST_ENGINE_ID "javacoretests"
@@ -34,7 +33,7 @@
RSA_free(p);
}
};
-typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
+typedef std::unique_ptr<RSA, RSA_Delete> Unique_RSA;
static const char* HMAC_TAG = "-HMAC-";
static const size_t HMAC_TAG_LEN = strlen(HMAC_TAG);
diff --git a/run-libcore-tests b/run-libcore-tests
index 79c4d07..ef30877 100755
--- a/run-libcore-tests
+++ b/run-libcore-tests
@@ -23,5 +23,6 @@
--vm-arg -Xmx32M \
--classpath out/target/common/obj/JAVA_LIBRARIES/core-tests_intermediates/javalib.jar \
--classpath out/target/common/obj/JAVA_LIBRARIES/sqlite-jdbc_intermediates/classes.jar \
+ --classpath out/target/common/obj/JAVA_LIBRARIES/bouncycastle_intermediates/classes.jar \
$test_packages \
|| true
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index 528a651..5f5bafd 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -101,6 +101,9 @@
public static final Map<String,Set<String>> CIPHER_PADDINGS
= new HashMap<String,Set<String>>();
+ private static final Map<String, String[]> SSL_CONTEXT_PROTOCOLS_ENABLED
+ = new HashMap<String,String[]>();
+
private static void provide(String type, String algorithm) {
Set<String> algorithms = PROVIDER_ALGORITHMS.get(type);
if (algorithms == null) {
@@ -134,6 +137,18 @@
}
paddings.addAll(Arrays.asList(newPaddings));
}
+ private static void provideSslContextEnabledProtocols(String algorithm, TLSVersion minimum,
+ TLSVersion maximum) {
+ if (minimum.ordinal() > maximum.ordinal()) {
+ throw new RuntimeException("TLS version: minimum > maximum");
+ }
+ int versionsLength = maximum.ordinal() - minimum.ordinal() + 1;
+ String[] versionNames = new String[versionsLength];
+ for (int i = 0; i < versionsLength; i++) {
+ versionNames[i] = TLSVersion.values()[i + minimum.ordinal()].name;
+ }
+ SSL_CONTEXT_PROTOCOLS_ENABLED.put(algorithm, versionNames);
+ }
static {
provide("AlgorithmParameterGenerator", "DSA");
provide("AlgorithmParameterGenerator", "DiffieHellman");
@@ -533,6 +548,24 @@
}
}
+
+ if (IS_RI) {
+ provideSslContextEnabledProtocols("SSL", TLSVersion.SSLv3, TLSVersion.TLSv1);
+ provideSslContextEnabledProtocols("SSLv3", TLSVersion.SSLv3, TLSVersion.TLSv1);
+ provideSslContextEnabledProtocols("TLS", TLSVersion.SSLv3, TLSVersion.TLSv1);
+ provideSslContextEnabledProtocols("TLSv1", TLSVersion.SSLv3, TLSVersion.TLSv1);
+ provideSslContextEnabledProtocols("TLSv1.1", TLSVersion.SSLv3, TLSVersion.TLSv11);
+ provideSslContextEnabledProtocols("TLSv1.2", TLSVersion.SSLv3, TLSVersion.TLSv12);
+ provideSslContextEnabledProtocols("Default", TLSVersion.SSLv3, TLSVersion.TLSv1);
+ } else {
+ provideSslContextEnabledProtocols("SSL", TLSVersion.SSLv3, TLSVersion.TLSv12);
+ provideSslContextEnabledProtocols("SSLv3", TLSVersion.SSLv3, TLSVersion.TLSv12);
+ provideSslContextEnabledProtocols("TLS", TLSVersion.TLSv1, TLSVersion.TLSv12);
+ provideSslContextEnabledProtocols("TLSv1", TLSVersion.TLSv1, TLSVersion.TLSv12);
+ provideSslContextEnabledProtocols("TLSv1.1", TLSVersion.TLSv1, TLSVersion.TLSv12);
+ provideSslContextEnabledProtocols("TLSv1.2", TLSVersion.TLSv1, TLSVersion.TLSv12);
+ provideSslContextEnabledProtocols("Default", TLSVersion.TLSv1, TLSVersion.TLSv12);
+ }
}
public static final String SSL_CONTEXT_PROTOCOLS_DEFAULT = "Default";
@@ -571,13 +604,11 @@
"TLSv1.2"));
public static final Set<String> SSL_SOCKET_PROTOCOLS_CLIENT_DEFAULT =
new HashSet<String>(Arrays.asList(
- "SSLv3",
"TLSv1",
"TLSv1.1",
"TLSv1.2"));
public static final Set<String> SSL_SOCKET_PROTOCOLS_SERVER_DEFAULT =
new HashSet<String>(Arrays.asList(
- "SSLv3",
"TLSv1",
"TLSv1.1",
"TLSv1.2"));
@@ -590,9 +621,26 @@
* do to disable general use of SSLv2.
*/
SSL_SOCKET_PROTOCOLS.add("SSLv2Hello");
+
+ /* The RI still has SSLv3 as a default protocol. */
+ SSL_SOCKET_PROTOCOLS_CLIENT_DEFAULT.add("SSLv3");
+ SSL_SOCKET_PROTOCOLS_SERVER_DEFAULT.add("SSLv3");
}
}
+ private static enum TLSVersion {
+ SSLv3("SSLv3"),
+ TLSv1("TLSv1"),
+ TLSv11("TLSv1.1"),
+ TLSv12("TLSv1.2");
+
+ private final String name;
+
+ TLSVersion(String name) {
+ this.name = name;
+ }
+ };
+
/**
* Valid values for X509TrustManager.checkClientTrusted authType,
* either the algorithm of the public key or UNKNOWN.
@@ -663,14 +711,12 @@
addBoth( "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA");
addBoth( "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA");
addBoth( "TLS_DHE_RSA_WITH_AES_256_CBC_SHA");
- addBoth( "TLS_DHE_DSS_WITH_AES_256_CBC_SHA");
addBoth( "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA");
addBoth( "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
addBoth( "TLS_RSA_WITH_AES_128_CBC_SHA");
addBoth( "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA");
addBoth( "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA");
addBoth( "TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
- addBoth( "TLS_DHE_DSS_WITH_AES_128_CBC_SHA");
addBoth( "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA");
addBoth( "TLS_ECDHE_RSA_WITH_RC4_128_SHA");
addBoth( "SSL_RSA_WITH_RC4_128_SHA");
@@ -682,7 +728,6 @@
addBoth( "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA");
addBoth( "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA");
addBoth( "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA");
- addBoth( "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA");
addBoth( "SSL_RSA_WITH_RC4_128_MD5");
// TLSv1.2 cipher suites
@@ -695,10 +740,6 @@
addBoth( "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256");
addOpenSsl("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256");
addOpenSsl("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384");
- addBoth( "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256");
- addBoth( "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256");
- addOpenSsl("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256");
- addOpenSsl("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384");
addBoth( "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256");
addBoth( "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384");
addOpenSsl("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256");
@@ -753,13 +794,11 @@
addBoth( "SSL_RSA_WITH_NULL_MD5");
addBoth( "SSL_RSA_WITH_DES_CBC_SHA");
addBoth( "SSL_DHE_RSA_WITH_DES_CBC_SHA");
- addBoth( "SSL_DHE_DSS_WITH_DES_CBC_SHA");
addBoth( "SSL_DH_anon_WITH_DES_CBC_SHA");
addBoth( "SSL_RSA_EXPORT_WITH_RC4_40_MD5");
addBoth( "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5");
addBoth( "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA");
addBoth( "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA");
- addBoth( "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
addBoth( "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA");
// Android does not have Keberos support
@@ -774,6 +813,17 @@
addRi( "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA");
addRi( "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5");
+ // Android does not have DSS support
+ addRi( "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
+ addRi( "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA");
+ addRi( "SSL_DHE_DSS_WITH_DES_CBC_SHA");
+ addRi( "TLS_DHE_DSS_WITH_AES_128_CBC_SHA");
+ addRi( "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256");
+ addNeither("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256");
+ addRi( "TLS_DHE_DSS_WITH_AES_256_CBC_SHA");
+ addRi( "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256");
+ addNeither("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384");
+
// Dropped
addNeither("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA");
addNeither("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA");
@@ -864,8 +914,6 @@
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
- "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
- "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
"TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
"TLS_ECDHE_RSA_WITH_RC4_128_SHA",
"TLS_RSA_WITH_AES_128_GCM_SHA256",
@@ -943,7 +991,8 @@
* suites in a test for those that want to verify separately that
* all cipher suites were included.
*/
- public static Set<String> assertValidCipherSuites(Set<String> expected, String[] cipherSuites) {
+ private static Set<String> assertValidCipherSuites(
+ Set<String> expected, String[] cipherSuites) {
assertNotNull(cipherSuites);
assertTrue(cipherSuites.length != 0);
@@ -965,7 +1014,7 @@
* assertSupportedCipherSuites additionally verifies that all
* supported cipher suites where in the input array.
*/
- public static void assertSupportedCipherSuites(Set<String> expected, String[] cipherSuites) {
+ private static void assertSupportedCipherSuites(Set<String> expected, String[] cipherSuites) {
Set<String> remainingCipherSuites = assertValidCipherSuites(expected, cipherSuites);
assertEquals("Missing cipher suites", Collections.EMPTY_SET, remainingCipherSuites);
assertEquals(expected.size(), cipherSuites.length);
@@ -978,7 +1027,7 @@
* those that want to verify separately that all protocols were
* included.
*/
- public static Set<String> assertValidProtocols(Set<String> expected, String[] protocols) {
+ private static Set<String> assertValidProtocols(Set<String> expected, String[] protocols) {
assertNotNull(protocols);
assertTrue(protocols.length != 0);
@@ -999,21 +1048,13 @@
* assertSupportedProtocols additionally verifies that all
* supported protocols where in the input array.
*/
- public static void assertSupportedProtocols(Set<String> expected, String[] protocols) {
+ private static void assertSupportedProtocols(Set<String> expected, String[] protocols) {
Set<String> remainingProtocols = assertValidProtocols(expected, protocols);
assertEquals("Missing protocols", Collections.EMPTY_SET, remainingProtocols);
assertEquals(expected.size(), protocols.length);
}
/**
- * Asserts that the protocols array is non-null and that all of its contents are supported
- * protocols.
- */
- public static void assertValidProtocols(String[] protocols) {
- assertValidProtocols(SSL_SOCKET_PROTOCOLS, protocols);
- }
-
- /**
* Asserts that the provided list of protocols matches the supported list of protocols.
*/
public static void assertSupportedProtocols(String[] protocols) {
@@ -1021,33 +1062,6 @@
}
/**
- * Asserts that the protocols array contains all the protocols enabled by default for client use
- * and no other ones.
- */
- public static void assertDefaultProtocolsClient(String[] protocols) {
- assertValidProtocols(protocols);
- assertSupportedProtocols(SSL_SOCKET_PROTOCOLS_CLIENT_DEFAULT, protocols);
- }
-
- /**
- * Asserts that the protocols array contains all the protocols enabled by default for server use
- * and no other ones.
- */
- public static void assertDefaultProtocolsServer(String[] protocols) {
- assertValidProtocols(protocols);
- assertSupportedProtocols(SSL_SOCKET_PROTOCOLS_SERVER_DEFAULT, protocols);
- }
-
- /**
- * Asserts that the protocols array contains all the protocols enabled by default for
- * {@link javax.net.ssl.SSLEngine} and no other ones.
- */
- public static void assertSSLEngineDefaultProtocols(String[] protocols) {
- assertValidProtocols(protocols);
- assertSupportedProtocols(SSL_SOCKET_PROTOCOLS_CLIENT_DEFAULT, protocols);
- }
-
- /**
* Assert that the provided list of cipher suites contains only the supported cipher suites.
*/
public static void assertValidCipherSuites(String[] cipherSuites) {
@@ -1084,6 +1098,12 @@
}
}
+ public static void assertSSLContextEnabledProtocols(String version, String[] protocols) {
+ assertEquals("For protocol \"" + version + "\"",
+ Arrays.toString(SSL_CONTEXT_PROTOCOLS_ENABLED.get(version)),
+ Arrays.toString(protocols));
+ }
+
private static boolean isPermittedDefaultCipherSuite(String cipherSuite) {
assertNotNull(cipherSuite);
if (CIPHER_SUITE_SECURE_RENEGOTIATION.equals(cipherSuite)) {
diff --git a/support/src/test/java/libcore/javax/net/ssl/SSLConfigurationAsserts.java b/support/src/test/java/libcore/javax/net/ssl/SSLConfigurationAsserts.java
new file mode 100644
index 0000000..bdaad65
--- /dev/null
+++ b/support/src/test/java/libcore/javax/net/ssl/SSLConfigurationAsserts.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2013 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.javax.net.ssl;
+
+import junit.framework.Assert;
+import libcore.java.security.StandardNames;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+/**
+ * Assertions about the configuration of TLS/SSL primitives.
+ */
+public class SSLConfigurationAsserts extends Assert {
+
+ /** Hidden constructor to prevent instantiation. */
+ private SSLConfigurationAsserts() {}
+
+ /**
+ * Asserts that the provided {@link SSLContext} has the expected default configuration, and that
+ * {@link SSLSocketFactory}, {@link SSLServerSocketFactory}, {@link SSLSocket},
+ * {@link SSLServerSocket} and {@link SSLEngine} instances created from the context match the
+ * configuration.
+ */
+ public static void assertSSLContextDefaultConfiguration(SSLContext sslContext)
+ throws IOException {
+ SSLParameters defaultParameters = sslContext.getDefaultSSLParameters();
+ StandardNames.assertSSLContextEnabledProtocols(sslContext.getProtocol(),
+ defaultParameters.getProtocols());
+ StandardNames.assertDefaultCipherSuites(defaultParameters.getCipherSuites());
+ assertFalse(defaultParameters.getWantClientAuth());
+ assertFalse(defaultParameters.getNeedClientAuth());
+
+ SSLParameters supportedParameters = sslContext.getSupportedSSLParameters();
+ StandardNames.assertSupportedCipherSuites(supportedParameters.getCipherSuites());
+ StandardNames.assertSupportedProtocols(supportedParameters.getProtocols());
+ assertFalse(supportedParameters.getWantClientAuth());
+ assertFalse(supportedParameters.getNeedClientAuth());
+
+ assertContainsAll("Unsupported enabled cipher suites", supportedParameters.getCipherSuites(),
+ defaultParameters.getCipherSuites());
+ assertContainsAll("Unsupported enabled protocols", supportedParameters.getProtocols(),
+ defaultParameters.getProtocols());
+
+ assertSSLSocketFactoryConfigSameAsSSLContext(sslContext.getSocketFactory(), sslContext);
+ assertSSLServerSocketFactoryConfigSameAsSSLContext(sslContext.getServerSocketFactory(),
+ sslContext);
+
+ SSLEngine sslEngine = sslContext.createSSLEngine();
+ assertFalse(sslEngine.getUseClientMode());
+ assertSSLEngineConfigSameAsSSLContext(sslEngine, sslContext);
+ }
+
+ /**
+ * Asserts that the provided {@link SSLSocketFactory} has the expected default configuration and
+ * that {@link SSLSocket} instances created by the factory match the configuration.
+ */
+ public static void assertSSLSocketFactoryDefaultConfiguration(
+ SSLSocketFactory sslSocketFactory) throws Exception {
+ assertSSLSocketFactoryConfigSameAsSSLContext(sslSocketFactory,
+ SSLContext.getDefault());
+ }
+
+ /**
+ * Asserts that {@link SSLSocketFactory}'s configuration matches {@code SSLContext}'s
+ * configuration, and that {@link SSLSocket} instances obtained from the factory match this
+ * configuration as well.
+ */
+ private static void assertSSLSocketFactoryConfigSameAsSSLContext(
+ SSLSocketFactory sslSocketFactory, SSLContext sslContext) throws IOException {
+ assertCipherSuitesEqual(sslContext.getDefaultSSLParameters().getCipherSuites(),
+ sslSocketFactory.getDefaultCipherSuites());
+ assertCipherSuitesEqual(sslContext.getSupportedSSLParameters().getCipherSuites(),
+ sslSocketFactory.getSupportedCipherSuites());
+
+ try (SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket()) {
+ assertTrue(sslSocket.getUseClientMode());
+ assertTrue(sslSocket.getEnableSessionCreation());
+ assertSSLSocketConfigSameAsSSLContext(sslSocket, sslContext);
+ }
+ }
+
+ /**
+ * Asserts that the provided {@link SSLSocket} has the expected default configuration.
+ */
+ public static void assertSSLSocketDefaultConfiguration(SSLSocket sslSocket) throws Exception {
+ assertTrue(sslSocket.getUseClientMode());
+ assertTrue(sslSocket.getEnableSessionCreation());
+ assertSSLSocketConfigSameAsSSLContext(sslSocket, SSLContext.getDefault());
+ }
+
+ /**
+ * Asserts that {@link SSLSocket}'s configuration matches {@code SSLContext's} configuration.
+ */
+ private static void assertSSLSocketConfigSameAsSSLContext(SSLSocket sslSocket,
+ SSLContext sslContext) {
+ assertSSLParametersEqual(sslSocket.getSSLParameters(), sslContext.getDefaultSSLParameters());
+ assertCipherSuitesEqual(sslSocket.getEnabledCipherSuites(),
+ sslContext.getDefaultSSLParameters().getCipherSuites());
+ assertProtocolsEqual(sslSocket.getEnabledProtocols(),
+ sslContext.getDefaultSSLParameters().getProtocols());
+
+ assertCipherSuitesEqual(sslSocket.getSupportedCipherSuites(),
+ sslContext.getSupportedSSLParameters().getCipherSuites());
+ assertProtocolsEqual(sslSocket.getSupportedProtocols(),
+ sslContext.getSupportedSSLParameters().getProtocols());
+ }
+
+ /**
+ * Asserts that the provided {@link SSLServerSocketFactory} has the expected default
+ * configuration, and that {@link SSLServerSocket} instances created by the factory match the
+ * configuration.
+ */
+ public static void assertSSLServerSocketFactoryDefaultConfiguration(
+ SSLServerSocketFactory sslServerSocketFactory) throws Exception {
+ assertSSLServerSocketFactoryConfigSameAsSSLContext(sslServerSocketFactory,
+ SSLContext.getDefault());
+ }
+
+ /**
+ * Asserts that {@link SSLServerSocketFactory}'s configuration matches {@code SSLContext}'s
+ * configuration, and that {@link SSLServerSocket} instances obtained from the factory match this
+ * configuration as well.
+ */
+ private static void assertSSLServerSocketFactoryConfigSameAsSSLContext(
+ SSLServerSocketFactory sslServerSocketFactory, SSLContext sslContext) throws IOException {
+ assertCipherSuitesEqual(sslContext.getDefaultSSLParameters().getCipherSuites(),
+ sslServerSocketFactory.getDefaultCipherSuites());
+ assertCipherSuitesEqual(sslContext.getSupportedSSLParameters().getCipherSuites(),
+ sslServerSocketFactory.getSupportedCipherSuites());
+ try (SSLServerSocket sslServerSocket =
+ (SSLServerSocket) sslServerSocketFactory.createServerSocket()) {
+ assertFalse(sslServerSocket.getUseClientMode());
+ assertTrue(sslServerSocket.getEnableSessionCreation());
+ assertSSLServerSocketConfigSameAsSSLContext(sslServerSocket, sslContext);
+ }
+ }
+
+ /**
+ * Asserts that the provided {@link SSLServerSocket} has the expected default configuration.
+ */
+ public static void assertSSLServerSocketDefaultConfiguration(SSLServerSocket sslServerSocket)
+ throws Exception {
+ assertFalse(sslServerSocket.getUseClientMode());
+ assertTrue(sslServerSocket.getEnableSessionCreation());
+ assertSSLServerSocketConfigSameAsSSLContext(sslServerSocket, SSLContext.getDefault());
+ // TODO: Check SSLParameters when supported by SSLServerSocket API
+ }
+
+ /**
+ * Asserts that {@link SSLServerSocket}'s configuration matches {@code SSLContext's}
+ * configuration.
+ */
+ private static void assertSSLServerSocketConfigSameAsSSLContext(SSLServerSocket sslServerSocket,
+ SSLContext sslContext) {
+ assertCipherSuitesEqual(sslServerSocket.getEnabledCipherSuites(),
+ sslContext.getDefaultSSLParameters().getCipherSuites());
+ assertProtocolsEqual(sslServerSocket.getEnabledProtocols(),
+ sslContext.getDefaultSSLParameters().getProtocols());
+
+ assertCipherSuitesEqual(sslServerSocket.getSupportedCipherSuites(),
+ sslContext.getSupportedSSLParameters().getCipherSuites());
+ assertProtocolsEqual(sslServerSocket.getSupportedProtocols(),
+ sslContext.getSupportedSSLParameters().getProtocols());
+
+ assertEquals(sslServerSocket.getNeedClientAuth(),
+ sslContext.getDefaultSSLParameters().getNeedClientAuth());
+ assertEquals(sslServerSocket.getWantClientAuth(),
+ sslContext.getDefaultSSLParameters().getWantClientAuth());
+ }
+
+ /**
+ * Asserts that the provided {@link SSLEngine} has the expected default configuration.
+ */
+ public static void assertSSLEngineDefaultConfiguration(SSLEngine sslEngine) throws Exception {
+ assertFalse(sslEngine.getUseClientMode());
+ assertTrue(sslEngine.getEnableSessionCreation());
+ assertSSLEngineConfigSameAsSSLContext(sslEngine, SSLContext.getDefault());
+ }
+
+ /**
+ * Asserts that {@link SSLEngine}'s configuration matches {@code SSLContext's} configuration.
+ */
+ private static void assertSSLEngineConfigSameAsSSLContext(SSLEngine sslEngine,
+ SSLContext sslContext) {
+ assertSSLParametersEqual(sslEngine.getSSLParameters(), sslContext.getDefaultSSLParameters());
+ assertCipherSuitesEqual(sslEngine.getEnabledCipherSuites(),
+ sslContext.getDefaultSSLParameters().getCipherSuites());
+ assertProtocolsEqual(sslEngine.getEnabledProtocols(),
+ sslContext.getDefaultSSLParameters().getProtocols());
+
+ assertCipherSuitesEqual(sslEngine.getSupportedCipherSuites(),
+ sslContext.getSupportedSSLParameters().getCipherSuites());
+ assertProtocolsEqual(sslEngine.getSupportedProtocols(),
+ sslContext.getSupportedSSLParameters().getProtocols());
+ }
+
+ private static void assertSSLParametersEqual(SSLParameters expected, SSLParameters actual) {
+ assertCipherSuitesEqual(expected.getCipherSuites(), actual.getCipherSuites());
+ assertProtocolsEqual(expected.getProtocols(), actual.getProtocols());
+ assertEquals(expected.getNeedClientAuth(), actual.getNeedClientAuth());
+ assertEquals(expected.getWantClientAuth(), actual.getWantClientAuth());
+ }
+
+ private static void assertCipherSuitesEqual(String[] expected, String[] actual) {
+ assertEquals(Arrays.asList(expected), Arrays.asList(actual));
+ }
+
+ private static void assertProtocolsEqual(String[] expected, String[] actual) {
+ // IMPLEMENTATION NOTE: The order of protocols versions does not matter. Similarly, it only
+ // matters whether a protocol version is present or absent in the array. These arrays are
+ // supposed to represent sets of protocol versions. Thus, we treat them as such.
+ assertEquals(new HashSet<String>(Arrays.asList(expected)),
+ new HashSet<String>(Arrays.asList(actual)));
+ }
+
+ /**
+ * Asserts that the {@code container} contains all the {@code elements}.
+ */
+ private static void assertContainsAll(String message, String[] container, String[] elements) {
+ Set<String> elementsNotInContainer = new HashSet<String>(Arrays.asList(elements));
+ elementsNotInContainer.removeAll(Arrays.asList(container));
+ assertEquals(message, Collections.EMPTY_SET, elementsNotInContainer);
+ }
+}
diff --git a/support/src/test/java/libcore/javax/net/ssl/SSLDefaultConfigurationAsserts.java b/support/src/test/java/libcore/javax/net/ssl/SSLDefaultConfigurationAsserts.java
deleted file mode 100644
index d54f5e5..0000000
--- a/support/src/test/java/libcore/javax/net/ssl/SSLDefaultConfigurationAsserts.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2013 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.javax.net.ssl;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLParameters;
-import javax.net.ssl.SSLServerSocket;
-import javax.net.ssl.SSLServerSocketFactory;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import junit.framework.Assert;
-import libcore.java.security.StandardNames;
-
-/**
- * Assertions about the default configuration of TLS/SSL primitives.
- */
-public abstract class SSLDefaultConfigurationAsserts extends Assert {
-
- /** Hidden constructor to prevent instantiation. */
- private SSLDefaultConfigurationAsserts() {}
-
- /**
- * Asserts that the provided {@link SSLContext} has the expected default configuration.
- */
- public static void assertSSLContext(SSLContext sslContext) throws IOException {
- assertDefaultSSLParametersClient(sslContext.getDefaultSSLParameters());
- assertSupportedSSLParametersClient(sslContext.getSupportedSSLParameters());
- assertSSLSocketFactory(sslContext.getSocketFactory());
- assertSSLServerSocketFactory(sslContext.getServerSocketFactory());
- assertSSLEngine(sslContext.createSSLEngine());
- assertSSLEngine(sslContext.createSSLEngine(null, -1));
- }
-
- /**
- * Asserts that the provided {@link SSLSocketFactory} has the expected default configuration.
- */
- public static void assertSSLSocketFactory(SSLSocketFactory sslSocketFactory) throws IOException {
- StandardNames.assertDefaultCipherSuites(sslSocketFactory.getDefaultCipherSuites());
- StandardNames.assertSupportedCipherSuites(sslSocketFactory.getSupportedCipherSuites());
- assertContainsAll("Unsupported default cipher suites",
- sslSocketFactory.getSupportedCipherSuites(),
- sslSocketFactory.getDefaultCipherSuites());
-
- assertSSLSocket((SSLSocket) sslSocketFactory.createSocket());
- }
-
- /**
- * Asserts that the provided {@link SSLServerSocketFactory} has the expected default
- * configuration.
- */
- public static void assertSSLServerSocketFactory(SSLServerSocketFactory sslServerSocketFactory)
- throws IOException {
- StandardNames.assertDefaultCipherSuites(sslServerSocketFactory.getDefaultCipherSuites());
- StandardNames.assertSupportedCipherSuites(sslServerSocketFactory.getSupportedCipherSuites());
- assertContainsAll("Unsupported default cipher suites",
- sslServerSocketFactory.getSupportedCipherSuites(),
- sslServerSocketFactory.getDefaultCipherSuites());
-
- assertSSLServerSocket((SSLServerSocket) sslServerSocketFactory.createServerSocket());
- }
-
- /**
- * Asserts that the provided {@link SSLSocket} has the expected default configuration.
- */
- public static void assertSSLSocket(SSLSocket sslSocket) {
- assertSSLParametersClient(sslSocket.getSSLParameters());
-
- StandardNames.assertDefaultCipherSuites(sslSocket.getEnabledCipherSuites());
- StandardNames.assertSupportedCipherSuites(sslSocket.getSupportedCipherSuites());
- assertContainsAll("Unsupported enabled cipher suites",
- sslSocket.getSupportedCipherSuites(),
- sslSocket.getEnabledCipherSuites());
-
- StandardNames.assertDefaultProtocolsClient(sslSocket.getEnabledProtocols());
- StandardNames.assertSupportedProtocols(sslSocket.getSupportedProtocols());
- assertContainsAll("Unsupported enabled protocols",
- sslSocket.getSupportedProtocols(),
- sslSocket.getEnabledProtocols());
-
- assertTrue(sslSocket.getUseClientMode());
- assertTrue(sslSocket.getEnableSessionCreation());
- assertFalse(sslSocket.getNeedClientAuth());
- assertFalse(sslSocket.getWantClientAuth());
- }
-
- /**
- * Asserts that the provided {@link SSLServerSocket} has the expected default configuration.
- */
- public static void assertSSLServerSocket(SSLServerSocket sslServerSocket) {
- // TODO: Check SSLParameters when supported by SSLServerSocket API
-
- StandardNames.assertDefaultCipherSuites(sslServerSocket.getEnabledCipherSuites());
- StandardNames.assertSupportedCipherSuites(sslServerSocket.getSupportedCipherSuites());
- assertContainsAll("Unsupported enabled cipher suites",
- sslServerSocket.getSupportedCipherSuites(),
- sslServerSocket.getEnabledCipherSuites());
-
- StandardNames.assertDefaultProtocolsServer(sslServerSocket.getEnabledProtocols());
- StandardNames.assertSupportedProtocols(sslServerSocket.getSupportedProtocols());
- assertContainsAll("Unsupported enabled protocols",
- sslServerSocket.getSupportedProtocols(),
- sslServerSocket.getEnabledProtocols());
-
- assertTrue(sslServerSocket.getEnableSessionCreation());
- assertFalse(sslServerSocket.getNeedClientAuth());
- assertFalse(sslServerSocket.getWantClientAuth());
- }
-
- /**
- * Asserts that the provided {@link SSLEngine} has the expected default configuration.
- */
- public static void assertSSLEngine(SSLEngine sslEngine) {
- assertFalse(sslEngine.getUseClientMode());
- assertSSLEngineSSLParameters(sslEngine.getSSLParameters());
-
- StandardNames.assertDefaultCipherSuites(sslEngine.getEnabledCipherSuites());
- StandardNames.assertSupportedCipherSuites(sslEngine.getSupportedCipherSuites());
- assertContainsAll("Unsupported enabled cipher suites",
- sslEngine.getSupportedCipherSuites(),
- sslEngine.getEnabledCipherSuites());
-
- StandardNames.assertSSLEngineDefaultProtocols(sslEngine.getEnabledProtocols());
- StandardNames.assertSupportedProtocols(sslEngine.getSupportedProtocols());
- assertContainsAll("Unsupported enabled protocols",
- sslEngine.getSupportedProtocols(),
- sslEngine.getEnabledProtocols());
-
- assertTrue(sslEngine.getEnableSessionCreation());
- assertFalse(sslEngine.getNeedClientAuth());
- assertFalse(sslEngine.getWantClientAuth());
- }
-
- /**
- * Asserts that the provided {@link SSLParameters} describe the expected default configuration
- * for client-side mode of operation.
- */
- public static void assertSSLParametersClient(SSLParameters sslParameters) {
- assertDefaultSSLParametersClient(sslParameters);
- }
-
- /**
- * Asserts that the provided default {@link SSLParameters} are as expected for client-side mode of
- * operation.
- */
- private static void assertDefaultSSLParametersClient(SSLParameters sslParameters) {
- StandardNames.assertDefaultCipherSuites(sslParameters.getCipherSuites());
- StandardNames.assertDefaultProtocolsClient(sslParameters.getProtocols());
- assertFalse(sslParameters.getWantClientAuth());
- assertFalse(sslParameters.getNeedClientAuth());
- }
-
- /**
- * Asserts that the provided supported {@link SSLParameters} are as expected for client-side mode
- * of operation.
- */
- private static void assertSupportedSSLParametersClient(SSLParameters sslParameters) {
- StandardNames.assertSupportedCipherSuites(sslParameters.getCipherSuites());
- StandardNames.assertSupportedProtocols(sslParameters.getProtocols());
- assertFalse(sslParameters.getWantClientAuth());
- assertFalse(sslParameters.getNeedClientAuth());
- }
-
- /**
- * Asserts that the provided {@link SSLParameters} has the expected default configuration for
- * {@link SSLEngine}.
- */
- public static void assertSSLEngineSSLParameters(SSLParameters sslParameters) {
- StandardNames.assertDefaultCipherSuites(sslParameters.getCipherSuites());
- StandardNames.assertSSLEngineDefaultProtocols(sslParameters.getProtocols());
- assertFalse(sslParameters.getWantClientAuth());
- assertFalse(sslParameters.getNeedClientAuth());
- }
-
- /**
- * Asserts that the {@code container} contains all the {@code elements}.
- */
- private static void assertContainsAll(String message, String[] container, String[] elements) {
- Set<String> elementsNotInContainer = new HashSet<String>(Arrays.asList(elements));
- elementsNotInContainer.removeAll(Arrays.asList(container));
- assertEquals(message, Collections.EMPTY_SET, elementsNotInContainer);
- }
-}
diff --git a/support/src/test/java/libcore/tlswire/handshake/CipherSuite.java b/support/src/test/java/libcore/tlswire/handshake/CipherSuite.java
new file mode 100644
index 0000000..959379d
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/handshake/CipherSuite.java
@@ -0,0 +1,473 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.handshake;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * {@code CipherSuite} enum from TLS 1.2 RFC 5246.
+ */
+public class CipherSuite {
+ // The list of cipher suites below is based on IANA registry
+ // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
+ private static final CipherSuite[] CIPHER_SUITES = new CipherSuite[] {
+ new CipherSuite(0x0000, "TLS_NULL_WITH_NULL_NULL"),
+ new CipherSuite(0x0001, "TLS_RSA_WITH_NULL_MD5"),
+ new CipherSuite(0x0002, "TLS_RSA_WITH_NULL_SHA"),
+ new CipherSuite(0x0003, "TLS_RSA_EXPORT_WITH_RC4_40_MD5"),
+ new CipherSuite(0x0004, "TLS_RSA_WITH_RC4_128_MD5"),
+ new CipherSuite(0x0005, "TLS_RSA_WITH_RC4_128_SHA"),
+ new CipherSuite(0x0006, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"),
+ new CipherSuite(0x0007, "TLS_RSA_WITH_IDEA_CBC_SHA"),
+ new CipherSuite(0x0008, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"),
+ new CipherSuite(0x0009, "TLS_RSA_WITH_DES_CBC_SHA"),
+ new CipherSuite(0x000a, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0x000b, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"),
+ new CipherSuite(0x000c, "TLS_DH_DSS_WITH_DES_CBC_SHA"),
+ new CipherSuite(0x000d, "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0x000e, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"),
+ new CipherSuite(0x000f, "TLS_DH_RSA_WITH_DES_CBC_SHA"),
+ new CipherSuite(0x0010, "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0x0011, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"),
+ new CipherSuite(0x0012, "TLS_DHE_DSS_WITH_DES_CBC_SHA"),
+ new CipherSuite(0x0013, "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0x0014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"),
+ new CipherSuite(0x0015, "TLS_DHE_RSA_WITH_DES_CBC_SHA"),
+ new CipherSuite(0x0016, "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0x0017, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"),
+ new CipherSuite(0x0018, "TLS_DH_anon_WITH_RC4_128_MD5"),
+ new CipherSuite(0x0019, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"),
+ new CipherSuite(0x001a, "TLS_DH_anon_WITH_DES_CBC_SHA"),
+ new CipherSuite(0x001b, "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0x001e, "TLS_KRB5_WITH_DES_CBC_SHA"),
+ new CipherSuite(0x001f, "TLS_KRB5_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0x0020, "TLS_KRB5_WITH_RC4_128_SHA"),
+ new CipherSuite(0x0021, "TLS_KRB5_WITH_IDEA_CBC_SHA"),
+ new CipherSuite(0x0022, "TLS_KRB5_WITH_DES_CBC_MD5"),
+ new CipherSuite(0x0023, "TLS_KRB5_WITH_3DES_EDE_CBC_MD5"),
+ new CipherSuite(0x0024, "TLS_KRB5_WITH_RC4_128_MD5"),
+ new CipherSuite(0x0025, "TLS_KRB5_WITH_IDEA_CBC_MD5"),
+ new CipherSuite(0x0026, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"),
+ new CipherSuite(0x0027, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA"),
+ new CipherSuite(0x0028, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA"),
+ new CipherSuite(0x0029, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"),
+ new CipherSuite(0x002a, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5"),
+ new CipherSuite(0x002b, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5"),
+ new CipherSuite(0x002c, "TLS_PSK_WITH_NULL_SHA"),
+ new CipherSuite(0x002d, "TLS_DHE_PSK_WITH_NULL_SHA"),
+ new CipherSuite(0x002e, "TLS_RSA_PSK_WITH_NULL_SHA"),
+ new CipherSuite(0x002f, "TLS_RSA_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0x0030, "TLS_DH_DSS_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0x0031, "TLS_DH_RSA_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0x0032, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0x0033, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0x0034, "TLS_DH_anon_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0x0035, "TLS_RSA_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0x0036, "TLS_DH_DSS_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0x0037, "TLS_DH_RSA_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0x0038, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0x0039, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0x003a, "TLS_DH_anon_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0x003b, "TLS_RSA_WITH_NULL_SHA256"),
+ new CipherSuite(0x003c, "TLS_RSA_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0x003d, "TLS_RSA_WITH_AES_256_CBC_SHA256"),
+ new CipherSuite(0x003e, "TLS_DH_DSS_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0x003f, "TLS_DH_RSA_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0x0040, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0x0041, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"),
+ new CipherSuite(0x0042, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA"),
+ new CipherSuite(0x0043, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA"),
+ new CipherSuite(0x0044, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"),
+ new CipherSuite(0x0045, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"),
+ new CipherSuite(0x0046, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA"),
+ new CipherSuite(0x0060, "TLS_RSA_EXPORT1024_WITH_RC4_56_MD5"),
+ new CipherSuite(0x0061, "TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5"),
+ new CipherSuite(0x0062, "TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA"),
+ new CipherSuite(0x0063, "TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA"),
+ new CipherSuite(0x0064, "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA"),
+ new CipherSuite(0x0065, "TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA"),
+ new CipherSuite(0x0066, "TLS_DHE_DSS_WITH_RC4_128_SHA"),
+ new CipherSuite(0x0067, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0x0068, "TLS_DH_DSS_WITH_AES_256_CBC_SHA256"),
+ new CipherSuite(0x0069, "TLS_DH_RSA_WITH_AES_256_CBC_SHA256"),
+ new CipherSuite(0x006a, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"),
+ new CipherSuite(0x006b, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"),
+ new CipherSuite(0x006c, "TLS_DH_anon_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0x006d, "TLS_DH_anon_WITH_AES_256_CBC_SHA256"),
+ new CipherSuite(0x0084, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"),
+ new CipherSuite(0x0085, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA"),
+ new CipherSuite(0x0086, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA"),
+ new CipherSuite(0x0087, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA"),
+ new CipherSuite(0x0088, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"),
+ new CipherSuite(0x0089, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA"),
+ new CipherSuite(0x008a, "TLS_PSK_WITH_RC4_128_SHA"),
+ new CipherSuite(0x008b, "TLS_PSK_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0x008c, "TLS_PSK_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0x008d, "TLS_PSK_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0x008e, "TLS_DHE_PSK_WITH_RC4_128_SHA"),
+ new CipherSuite(0x008f, "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0x0090, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0x0091, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0x0092, "TLS_RSA_PSK_WITH_RC4_128_SHA"),
+ new CipherSuite(0x0093, "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0x0094, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0x0095, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0x0096, "TLS_RSA_WITH_SEED_CBC_SHA"),
+ new CipherSuite(0x0097, "TLS_DH_DSS_WITH_SEED_CBC_SHA"),
+ new CipherSuite(0x0098, "TLS_DH_RSA_WITH_SEED_CBC_SHA"),
+ new CipherSuite(0x0099, "TLS_DHE_DSS_WITH_SEED_CBC_SHA"),
+ new CipherSuite(0x009a, "TLS_DHE_RSA_WITH_SEED_CBC_SHA"),
+ new CipherSuite(0x009b, "TLS_DH_anon_WITH_SEED_CBC_SHA"),
+ new CipherSuite(0x009c, "TLS_RSA_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0x009d, "TLS_RSA_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0x009e, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0x009f, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0x00a0, "TLS_DH_RSA_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0x00a1, "TLS_DH_RSA_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0x00a2, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0x00a3, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0x00a4, "TLS_DH_DSS_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0x00a5, "TLS_DH_DSS_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0x00a6, "TLS_DH_anon_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0x00a7, "TLS_DH_anon_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0x00a8, "TLS_PSK_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0x00a9, "TLS_PSK_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0x00aa, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0x00ab, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0x00ac, "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0x00ad, "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0x00ae, "TLS_PSK_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0x00af, "TLS_PSK_WITH_AES_256_CBC_SHA384"),
+ new CipherSuite(0x00b0, "TLS_PSK_WITH_NULL_SHA256"),
+ new CipherSuite(0x00b1, "TLS_PSK_WITH_NULL_SHA384"),
+ new CipherSuite(0x00b2, "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0x00b3, "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384"),
+ new CipherSuite(0x00b4, "TLS_DHE_PSK_WITH_NULL_SHA256"),
+ new CipherSuite(0x00b5, "TLS_DHE_PSK_WITH_NULL_SHA384"),
+ new CipherSuite(0x00b6, "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0x00b7, "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384"),
+ new CipherSuite(0x00b8, "TLS_RSA_PSK_WITH_NULL_SHA256"),
+ new CipherSuite(0x00b9, "TLS_RSA_PSK_WITH_NULL_SHA384"),
+ new CipherSuite(0x00ba, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0x00bb, "TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0x00bc, "TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0x00bd, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0x00be, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0x00bf, "TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0x00c0, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256"),
+ new CipherSuite(0x00c1, "TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256"),
+ new CipherSuite(0x00c2, "TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256"),
+ new CipherSuite(0x00c3, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256"),
+ new CipherSuite(0x00c4, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256"),
+ new CipherSuite(0x00c5, "TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256"),
+ new CipherSuite(0x00ff, "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"),
+ new CipherSuite(0x5600, "TLS_FALLBACK_SCSV"),
+ new CipherSuite(0xc001, "TLS_ECDH_ECDSA_WITH_NULL_SHA"),
+ new CipherSuite(0xc002, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"),
+ new CipherSuite(0xc003, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0xc004, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0xc005, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0xc006, "TLS_ECDHE_ECDSA_WITH_NULL_SHA"),
+ new CipherSuite(0xc007, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"),
+ new CipherSuite(0xc008, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0xc009, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0xc00a, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0xc00b, "TLS_ECDH_RSA_WITH_NULL_SHA"),
+ new CipherSuite(0xc00c, "TLS_ECDH_RSA_WITH_RC4_128_SHA"),
+ new CipherSuite(0xc00d, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0xc00e, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0xc00f, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0xc010, "TLS_ECDHE_RSA_WITH_NULL_SHA"),
+ new CipherSuite(0xc011, "TLS_ECDHE_RSA_WITH_RC4_128_SHA"),
+ new CipherSuite(0xc012, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0xc013, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0xc014, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0xc015, "TLS_ECDH_anon_WITH_NULL_SHA"),
+ new CipherSuite(0xc016, "TLS_ECDH_anon_WITH_RC4_128_SHA"),
+ new CipherSuite(0xc017, "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0xc018, "TLS_ECDH_anon_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0xc019, "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0xc01a, "TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0xc01b, "TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0xc01c, "TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0xc01d, "TLS_SRP_SHA_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0xc01e, "TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0xc01f, "TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0xc020, "TLS_SRP_SHA_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0xc021, "TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0xc022, "TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0xc023, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0xc024, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"),
+ new CipherSuite(0xc025, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0xc026, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384"),
+ new CipherSuite(0xc027, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0xc028, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"),
+ new CipherSuite(0xc029, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0xc02a, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384"),
+ new CipherSuite(0xc02b, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0xc02c, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0xc02d, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0xc02e, "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0xc02f, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0xc030, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0xc031, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"),
+ new CipherSuite(0xc032, "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384"),
+ new CipherSuite(0xc033, "TLS_ECDHE_PSK_WITH_RC4_128_SHA"),
+ new CipherSuite(0xc034, "TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA"),
+ new CipherSuite(0xc035, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"),
+ new CipherSuite(0xc036, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA"),
+ new CipherSuite(0xc037, "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256"),
+ new CipherSuite(0xc038, "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384"),
+ new CipherSuite(0xc039, "TLS_ECDHE_PSK_WITH_NULL_SHA"),
+ new CipherSuite(0xc03a, "TLS_ECDHE_PSK_WITH_NULL_SHA256"),
+ new CipherSuite(0xc03b, "TLS_ECDHE_PSK_WITH_NULL_SHA384"),
+ new CipherSuite(0xc03c, "TLS_RSA_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc03d, "TLS_RSA_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc03e, "TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc03f, "TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc040, "TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc041, "TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc042, "TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc043, "TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc044, "TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc045, "TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc046, "TLS_DH_anon_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc047, "TLS_DH_anon_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc048, "TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc049, "TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc04a, "TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc04b, "TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc04c, "TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc04d, "TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc04e, "TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc04f, "TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc050, "TLS_RSA_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc051, "TLS_RSA_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc052, "TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc053, "TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc054, "TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc055, "TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc056, "TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc057, "TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc058, "TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc059, "TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc05a, "TLS_DH_anon_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc05b, "TLS_DH_anon_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc05c, "TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc05d, "TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc05e, "TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc05f, "TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc060, "TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc061, "TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc062, "TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc063, "TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc064, "TLS_PSK_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc065, "TLS_PSK_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc066, "TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc067, "TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc068, "TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc069, "TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc06a, "TLS_PSK_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc06b, "TLS_PSK_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc06c, "TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc06d, "TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc06e, "TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256"),
+ new CipherSuite(0xc06f, "TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384"),
+ new CipherSuite(0xc070, "TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256"),
+ new CipherSuite(0xc071, "TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384"),
+ new CipherSuite(0xc072, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0xc073, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"),
+ new CipherSuite(0xc074, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0xc075, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384"),
+ new CipherSuite(0xc076, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0xc077, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384"),
+ new CipherSuite(0xc078, "TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0xc079, "TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384"),
+ new CipherSuite(0xc07a, "TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc07b, "TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc07c, "TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc07d, "TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc07e, "TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc07f, "TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc080, "TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc081, "TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc082, "TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc083, "TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc084, "TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc085, "TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc086, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc087, "TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc088, "TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc089, "TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc08a, "TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc08b, "TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc08c, "TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc08d, "TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc08e, "TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc08f, "TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc090, "TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc091, "TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc092, "TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256"),
+ new CipherSuite(0xc093, "TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384"),
+ new CipherSuite(0xc094, "TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0xc095, "TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384"),
+ new CipherSuite(0xc096, "TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0xc097, "TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"),
+ new CipherSuite(0xc098, "TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0xc099, "TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384"),
+ new CipherSuite(0xc09a, "TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256"),
+ new CipherSuite(0xc09b, "TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384"),
+ new CipherSuite(0xc09c, "TLS_RSA_WITH_AES_128_CCM"),
+ new CipherSuite(0xc09d, "TLS_RSA_WITH_AES_256_CCM"),
+ new CipherSuite(0xc09e, "TLS_DHE_RSA_WITH_AES_128_CCM"),
+ new CipherSuite(0xc09f, "TLS_DHE_RSA_WITH_AES_256_CCM"),
+ new CipherSuite(0xc0a0, "TLS_RSA_WITH_AES_128_CCM_8"),
+ new CipherSuite(0xc0a1, "TLS_RSA_WITH_AES_256_CCM_8"),
+ new CipherSuite(0xc0a2, "TLS_DHE_RSA_WITH_AES_128_CCM_8"),
+ new CipherSuite(0xc0a3, "TLS_DHE_RSA_WITH_AES_256_CCM_8"),
+ new CipherSuite(0xc0a4, "TLS_PSK_WITH_AES_128_CCM"),
+ new CipherSuite(0xc0a5, "TLS_PSK_WITH_AES_256_CCM"),
+ new CipherSuite(0xc0a6, "TLS_DHE_PSK_WITH_AES_128_CCM"),
+ new CipherSuite(0xc0a7, "TLS_DHE_PSK_WITH_AES_256_CCM"),
+ new CipherSuite(0xc0a8, "TLS_PSK_WITH_AES_128_CCM_8"),
+ new CipherSuite(0xc0a9, "TLS_PSK_WITH_AES_256_CCM_8"),
+ new CipherSuite(0xc0aa, "TLS_PSK_DHE_WITH_AES_128_CCM_8"),
+ new CipherSuite(0xc0ab, "TLS_PSK_DHE_WITH_AES_256_CCM_8"),
+ new CipherSuite(0xc0ac, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM"),
+ new CipherSuite(0xc0ad, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM"),
+ new CipherSuite(0xc0ae, "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8"),
+ new CipherSuite(0xc0af, "TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8"),
+ new CipherSuite(0xcc13, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305"),
+ new CipherSuite(0xcc14, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305"),
+ new CipherSuite(0xcc15, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305"),
+ };
+
+ private static final Map<Integer, CipherSuite> CODE_TO_CIPHER_SUITE;
+ private static final Map<String, CipherSuite> NAME_TO_CIPHER_SUITE;
+
+
+ static {
+ Map<Integer, CipherSuite> byCode = new HashMap<Integer, CipherSuite>();
+ Map<String, CipherSuite> byName = new HashMap<String, CipherSuite>();
+ for (CipherSuite cipherSuite : CIPHER_SUITES) {
+ if (byCode.put(cipherSuite.code, cipherSuite) != null) {
+ throw new RuntimeException(
+ "Cipher suite multiply defined: " + Integer.toHexString(cipherSuite.code));
+ }
+ if (byName.put(cipherSuite.name, cipherSuite) != null) {
+ throw new RuntimeException(
+ "Cipher suite multiply defined: " + cipherSuite.name);
+ }
+ }
+
+ // Add alternative names used in Android's platform-default TLS/SSL stack.
+ addAltName(byName,
+ "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
+ addAltName(byName,
+ "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA");
+ addAltName(byName, "TLS_DHE_DSS_WITH_DES_CBC_SHA", "SSL_DHE_DSS_WITH_DES_CBC_SHA");
+ addAltName(byName,
+ "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA");
+ addAltName(byName,
+ "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA");
+ addAltName(byName, "TLS_DHE_RSA_WITH_DES_CBC_SHA", "SSL_DHE_RSA_WITH_DES_CBC_SHA");
+ addAltName(byName,
+ "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA", "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA");
+ addAltName(byName,
+ "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5", "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5");
+ addAltName(byName,
+ "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA", "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA");
+ addAltName(byName, "TLS_DH_anon_WITH_DES_CBC_SHA", "SSL_DH_anon_WITH_DES_CBC_SHA");
+ addAltName(byName, "TLS_DH_anon_WITH_RC4_128_MD5", "SSL_DH_anon_WITH_RC4_128_MD5");
+ addAltName(byName,
+ "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA");
+ addAltName(byName, "TLS_RSA_EXPORT_WITH_RC4_40_MD5", "SSL_RSA_EXPORT_WITH_RC4_40_MD5");
+ addAltName(byName, "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA");
+ addAltName(byName, "TLS_RSA_WITH_DES_CBC_SHA", "SSL_RSA_WITH_DES_CBC_SHA");
+ addAltName(byName, "TLS_RSA_WITH_NULL_MD5", "SSL_RSA_WITH_NULL_MD5");
+ addAltName(byName, "TLS_RSA_WITH_NULL_SHA", "SSL_RSA_WITH_NULL_SHA");
+ addAltName(byName, "TLS_RSA_WITH_RC4_128_MD5", "SSL_RSA_WITH_RC4_128_MD5");
+ addAltName(byName, "TLS_RSA_WITH_RC4_128_SHA", "SSL_RSA_WITH_RC4_128_SHA");
+
+ CODE_TO_CIPHER_SUITE = byCode;
+ NAME_TO_CIPHER_SUITE = byName;
+ }
+
+ private static void addAltName(Map<String, CipherSuite> byName, String name, String altName) {
+ CipherSuite cipherSuite = byName.get(name);
+ if (cipherSuite == null) {
+ throw new IllegalArgumentException("Cipher suite not found: " + name);
+ }
+ byName.put(altName, cipherSuite);
+ }
+
+ public final int code;
+ public final String name;
+
+ private CipherSuite(int code, String name) {
+ this.code = code;
+ this.name = name;
+ }
+
+ public static CipherSuite valueOf(String name) {
+ CipherSuite result = NAME_TO_CIPHER_SUITE.get(name);
+ if (result != null) {
+ return result;
+ }
+ throw new IllegalArgumentException("Unknown cipher suite: " + name);
+ }
+
+ public static CipherSuite valueOf(int code) {
+ CipherSuite result = CODE_TO_CIPHER_SUITE.get(code);
+ if (result != null) {
+ return result;
+ }
+ return new CipherSuite(code, Integer.toHexString(code));
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + code;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ CipherSuite other = (CipherSuite) obj;
+ if (code != other.code) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/support/src/test/java/libcore/tlswire/handshake/ClientHello.java b/support/src/test/java/libcore/tlswire/handshake/ClientHello.java
new file mode 100644
index 0000000..8d25cd5
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/handshake/ClientHello.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.handshake;
+
+import libcore.tlswire.util.TlsProtocolVersion;
+import libcore.tlswire.util.HexEncoding;
+import libcore.tlswire.util.IoUtils;
+import java.io.ByteArrayInputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link ClientHello} {@link HandshakeMessage} from TLS 1.2 RFC 5246.
+ */
+public class ClientHello extends HandshakeMessage {
+ public TlsProtocolVersion clientVersion;
+ public byte[] random;
+ public byte[] sessionId;
+ public List<CipherSuite> cipherSuites;
+ public List<CompressionMethod> compressionMethods;
+
+ /** Extensions or {@code null} for no extensions. */
+ public List<HelloExtension> extensions;
+
+ @Override
+ protected void parseBody(DataInput in) throws IOException {
+ clientVersion = TlsProtocolVersion.read(in);
+ random = new byte[32];
+ in.readFully(random);
+ sessionId = IoUtils.readTlsVariableLengthByteVector(in, 32);
+ int[] cipherSuiteCodes = IoUtils.readTlsVariableLengthUnsignedShortVector(in, 0xfffe);
+ cipherSuites = new ArrayList<CipherSuite>(cipherSuiteCodes.length);
+ for (int i = 0; i < cipherSuiteCodes.length; i++) {
+ cipherSuites.add(CipherSuite.valueOf(cipherSuiteCodes[i]));
+ }
+ byte[] compressionMethodCodes = IoUtils.readTlsVariableLengthByteVector(in, 0xff);
+ compressionMethods = new ArrayList<CompressionMethod>(compressionMethodCodes.length);
+ for (int i = 0; i < compressionMethodCodes.length; i++) {
+ int code = compressionMethodCodes[i] & 0xff;
+ compressionMethods.add(CompressionMethod.valueOf(code));
+ }
+
+ int extensionsSectionSize;
+ try {
+ extensionsSectionSize = in.readUnsignedShort();
+ } catch (EOFException e) {
+ // No extensions present
+ extensionsSectionSize = 0;
+ }
+
+ if (extensionsSectionSize > 0) {
+ extensions = new ArrayList<HelloExtension>();
+ byte[] extensionsBytes = new byte[extensionsSectionSize];
+ in.readFully(extensionsBytes);
+ ByteArrayInputStream extensionsIn = new ByteArrayInputStream(extensionsBytes);
+ DataInput extensionsDataIn = new DataInputStream(extensionsIn);
+ while (extensionsIn.available() > 0) {
+ try {
+ extensions.add(HelloExtension.read(extensionsDataIn));
+ } catch (IOException e) {
+ throw new IOException(
+ "Failed to read HelloExtension #" + (extensions.size() + 1));
+ }
+ }
+ }
+ }
+
+ public HelloExtension findExtensionByType(int extensionType) {
+ if (extensions == null) {
+ return null;
+ }
+ for (HelloExtension extension : extensions) {
+ if (extension.type == extensionType) {
+ return extension;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return "ClientHello{client version: " + clientVersion
+ + ", random: " + HexEncoding.encode(random)
+ + ", sessionId: " + HexEncoding.encode(sessionId)
+ + ", cipher suites: " + cipherSuites
+ + ", compression methods: " + compressionMethods
+ + ((extensions != null) ? (", extensions: " + String.valueOf(extensions)) : "")
+ + "}";
+ }
+}
diff --git a/support/src/test/java/libcore/tlswire/handshake/CompressionMethod.java b/support/src/test/java/libcore/tlswire/handshake/CompressionMethod.java
new file mode 100644
index 0000000..0f4f619
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/handshake/CompressionMethod.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.handshake;
+
+/**
+ * {@code CompressionMethod} enum from TLS 1.2 RFC 5246.
+ */
+public class CompressionMethod {
+
+ public static final CompressionMethod NULL = new CompressionMethod(0, "null");
+ public static final CompressionMethod DEFLATE = new CompressionMethod(1, "deflate");
+
+ public final int type;
+ public final String name;
+
+ private CompressionMethod(int type, String name) {
+ this.type = type;
+ this.name = name;
+ }
+
+ public static CompressionMethod valueOf(int type) {
+ switch (type) {
+ case 0:
+ return NULL;
+ case 1:
+ return DEFLATE;
+ default:
+ return new CompressionMethod(type, String.valueOf(type));
+ }
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + type;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ CompressionMethod other = (CompressionMethod) obj;
+ if (type != other.type) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/support/src/test/java/libcore/tlswire/handshake/HandshakeMessage.java b/support/src/test/java/libcore/tlswire/handshake/HandshakeMessage.java
new file mode 100644
index 0000000..a855b46
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/handshake/HandshakeMessage.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.handshake;
+
+import libcore.tlswire.util.IoUtils;
+import java.io.ByteArrayInputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.IOException;
+
+/**
+ * Handshake Protocol message from TLS 1.2 RFC 5246.
+ */
+public class HandshakeMessage {
+ public static final int TYPE_CLIENT_HELLO = 1;
+
+ public int type;
+ public byte[] body;
+
+ /**
+ * Parses the provided TLS record as a handshake message.
+ */
+ public static HandshakeMessage read(DataInput in) throws IOException {
+ int type = in.readUnsignedByte();
+ HandshakeMessage result;
+ switch (type) {
+ case TYPE_CLIENT_HELLO:
+ result = new ClientHello();
+ break;
+ default:
+ result = new HandshakeMessage();
+ break;
+ }
+ result.type = type;
+ int bodyLength = IoUtils.readUnsignedInt24(in);
+ result.body = new byte[bodyLength];
+ in.readFully(result.body);
+ result.parseBody(new DataInputStream(new ByteArrayInputStream(result.body)));
+ return result;
+ }
+
+ /**
+ * Parses the provided body. The default implementation does nothing.
+ *
+ * @throws IOException if an I/O error occurs.
+ */
+ protected void parseBody(@SuppressWarnings("unused") DataInput in) throws IOException {}
+}
diff --git a/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java b/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java
new file mode 100644
index 0000000..e3361b9
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.handshake;
+
+import libcore.tlswire.util.HexEncoding;
+import libcore.tlswire.util.IoUtils;
+import java.io.DataInput;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * {@code HelloExtension} struct from TLS 1.2 RFC 5246.
+ */
+public class HelloExtension {
+
+ public static final int TYPE_SERVER_NAME = 0;
+ public static final int TYPE_PADDING = 21;
+ public static final int TYPE_SESSION_TICKET = 35;
+
+ private static final Map<Integer, String> TYPE_TO_NAME = new HashMap<Integer, String>();
+ static {
+ TYPE_TO_NAME.put(TYPE_SERVER_NAME, "server_name");
+ TYPE_TO_NAME.put(1, "max_fragment_length");
+ TYPE_TO_NAME.put(2, "client_certificate_url");
+ TYPE_TO_NAME.put(3, "trusted_ca_keys");
+ TYPE_TO_NAME.put(4, "truncated_hmac");
+ TYPE_TO_NAME.put(5, "status_request");
+ TYPE_TO_NAME.put(6, "user_mapping");
+ TYPE_TO_NAME.put(7, "client_authz");
+ TYPE_TO_NAME.put(8, "server_authz");
+ TYPE_TO_NAME.put(9, "cert_type");
+ TYPE_TO_NAME.put(10, "elliptic_curves");
+ TYPE_TO_NAME.put(11, "ec_point_formats");
+ TYPE_TO_NAME.put(12, "srp");
+ TYPE_TO_NAME.put(13, "signature_algorithms");
+ TYPE_TO_NAME.put(14, "use_srtp");
+ TYPE_TO_NAME.put(15, "heartbeat");
+ TYPE_TO_NAME.put(16, "application_layer_protocol_negotiation");
+ TYPE_TO_NAME.put(17, "status_request_v2");
+ TYPE_TO_NAME.put(18, "signed_certificate_timestamp");
+ TYPE_TO_NAME.put(19, "client_certificate_type");
+ TYPE_TO_NAME.put(20, "server_certificate_type");
+ TYPE_TO_NAME.put(TYPE_PADDING, "padding");
+ TYPE_TO_NAME.put(TYPE_SESSION_TICKET, "SessionTicket");
+ TYPE_TO_NAME.put(13172, "next_protocol_negotiation");
+ TYPE_TO_NAME.put(30031, "Channel ID (old)");
+ TYPE_TO_NAME.put(30032, "Channel ID (new)");
+ TYPE_TO_NAME.put(65281, "renegotiation_info");
+ }
+
+ public int type;
+ public String name;
+ public byte[] data;
+
+ public static HelloExtension read(DataInput in) throws IOException {
+ int type = in.readUnsignedShort();
+ HelloExtension result;
+ switch (type) {
+ case TYPE_SERVER_NAME:
+ result = new ServerNameHelloExtension();
+ break;
+ default:
+ result = new HelloExtension();
+ break;
+ }
+ result.type = type;
+ result.name = TYPE_TO_NAME.get(result.type);
+ if (result.name == null) {
+ result.name = String.valueOf(result.type);
+ }
+ result.data = IoUtils.readTlsVariableLengthByteVector(in, 0xffff);
+ result.parseData();
+ return result;
+ }
+
+ /**
+ * @throws IOException
+ */
+ protected void parseData() throws IOException {}
+
+ @Override
+ public String toString() {
+ return "HelloExtension{type: " + name + ", data: " + HexEncoding.encode(data) + "}";
+ }
+}
diff --git a/support/src/test/java/libcore/tlswire/handshake/ServerNameHelloExtension.java b/support/src/test/java/libcore/tlswire/handshake/ServerNameHelloExtension.java
new file mode 100644
index 0000000..afc9cfe
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/handshake/ServerNameHelloExtension.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.handshake;
+
+import libcore.tlswire.util.IoUtils;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@code server_name} (SNI) {@link HelloExtension} from TLS 1.2 RFC 5246.
+ */
+public class ServerNameHelloExtension extends HelloExtension {
+ private static final int TYPE_HOST_NAME = 0;
+
+ private List<String> hostnames;
+
+ @Override
+ protected void parseData() throws IOException {
+ byte[] serverNameListBytes = IoUtils.readTlsVariableLengthByteVector(
+ new DataInputStream(new ByteArrayInputStream(data)), 0xffff);
+ ByteArrayInputStream serverNameListIn = new ByteArrayInputStream(serverNameListBytes);
+ DataInputStream in = new DataInputStream(serverNameListIn);
+ hostnames = new ArrayList<String>();
+ while (serverNameListIn.available() > 0) {
+ int type = in.readUnsignedByte();
+ if (type != TYPE_HOST_NAME) {
+ throw new IOException("Unsupported ServerName type: " + type);
+ }
+ byte[] hostnameBytes = IoUtils.readTlsVariableLengthByteVector(in, 0xffff);
+ String hostname = new String(hostnameBytes, "US-ASCII");
+ hostnames.add(hostname);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "HelloExtension{type: server_name, hostnames: " + hostnames + "}";
+ }
+}
diff --git a/support/src/test/java/libcore/tlswire/record/TlsProtocols.java b/support/src/test/java/libcore/tlswire/record/TlsProtocols.java
new file mode 100644
index 0000000..0ce0d35
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/record/TlsProtocols.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.record;
+
+/**
+ * Protocols that can run over the TLS Record Protocol from TLS 1.2 RFC 5246.
+ */
+public class TlsProtocols {
+ public static final int CHANGE_CIPHER_SPEC = 20;
+ public static final int ALERT = 21;
+ public static final int HANDSHAKE = 22;
+ public static final int APPLICATION_DATA = 23;
+ public static final int HEARTBEAT = 24;
+
+ private TlsProtocols() {}
+}
diff --git a/support/src/test/java/libcore/tlswire/record/TlsRecord.java b/support/src/test/java/libcore/tlswire/record/TlsRecord.java
new file mode 100644
index 0000000..1b60407
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/record/TlsRecord.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.record;
+
+import libcore.tlswire.util.TlsProtocolVersion;
+import java.io.DataInput;
+import java.io.IOException;
+
+/**
+ * TLS Record Protocol record from TLS 1.2 RFC 5246.
+ */
+public class TlsRecord {
+ public int type;
+ public TlsProtocolVersion version;
+ public byte[] fragment;
+
+ public static TlsRecord read(DataInput in) throws IOException {
+ TlsRecord result = new TlsRecord();
+ result.type = in.readUnsignedByte();
+ result.version = TlsProtocolVersion.read(in);
+ int fragmentLength = in.readUnsignedShort();
+ result.fragment = new byte[fragmentLength];
+ in.readFully(result.fragment);
+ return result;
+ }
+}
diff --git a/support/src/test/java/libcore/tlswire/util/HexEncoding.java b/support/src/test/java/libcore/tlswire/util/HexEncoding.java
new file mode 100644
index 0000000..2061fcc
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/util/HexEncoding.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.util;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Hexadecimal encoding where each byte is represented by two hexadecimal digits.
+ */
+public class HexEncoding {
+
+ /** Hidden constructor to prevent instantiation. */
+ private HexEncoding() {}
+
+ private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
+
+ /**
+ * Encodes the provided data as a hexadecimal string.
+ */
+ public static String encode(byte[] data) {
+ return encode(data, 0, data.length);
+ }
+
+ /**
+ * Encodes the provided data as a hexadecimal string.
+ */
+ public static String encode(byte[] data, int offset, int len) {
+ StringBuilder result = new StringBuilder(len * 2);
+ for (int i = 0; i < len; i++) {
+ byte b = data[offset + i];
+ result.append(HEX_DIGITS[(b >>> 4) & 0x0f]);
+ result.append(HEX_DIGITS[b & 0x0f]);
+ }
+ return result.toString();
+ }
+
+ /**
+ * Encodes the provided data as a hexadecimal string.
+ */
+ public static String encode(ByteBuffer buf) {
+ return encode(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining());
+ }
+
+ /**
+ * Decodes the provided hexadecimal string into an array of bytes.
+ */
+ public static byte[] decode(String encoded) {
+ // IMPLEMENTATION NOTE: Special care is taken to permit odd number of hexadecimal digits.
+ int resultLengthBytes = (encoded.length() + 1) / 2;
+ byte[] result = new byte[resultLengthBytes];
+ int resultOffset = 0;
+ int encodedCharOffset = 0;
+ if ((encoded.length() % 2) != 0) {
+ // Odd number of digits -- the first digit is the lower 4 bits of the first result byte.
+ result[resultOffset++] =
+ (byte) getHexadecimalDigitValue(encoded.charAt(encodedCharOffset));
+ encodedCharOffset++;
+ }
+ for (int len = encoded.length(); encodedCharOffset < len; encodedCharOffset += 2) {
+ result[resultOffset++] = (byte) (
+ (getHexadecimalDigitValue(encoded.charAt(encodedCharOffset)) << 4)
+ | getHexadecimalDigitValue(encoded.charAt(encodedCharOffset + 1)));
+ }
+ return result;
+ }
+
+ private static int getHexadecimalDigitValue(char c) {
+ if ((c >= 'a') && (c <= 'f')) {
+ return (c - 'a') + 0x0a;
+ } else if ((c >= 'A') && (c <= 'F')) {
+ return (c - 'A') + 0x0a;
+ } else if ((c >= '0') && (c <= '9')) {
+ return c - '0';
+ } else {
+ throw new IllegalArgumentException("Invalid hexadecimal digit at position : '" + c
+ + "' (0x" + Integer.toHexString(c) + ")");
+ }
+ }
+}
diff --git a/support/src/test/java/libcore/tlswire/util/IoUtils.java b/support/src/test/java/libcore/tlswire/util/IoUtils.java
new file mode 100644
index 0000000..1e2d8f2
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/util/IoUtils.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.util;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+public class IoUtils {
+
+ public static int readUnsignedInt24(DataInput in) throws IOException {
+ return (in.readUnsignedByte() << 16) | in.readUnsignedShort();
+ }
+
+ public static byte[] readTlsVariableLengthByteVector(DataInput in, int maxSizeBytes)
+ throws IOException {
+ int sizeBytes = readTlsVariableLengthVectorSizeBytes(in, maxSizeBytes);
+ byte[] result = new byte[sizeBytes];
+ in.readFully(result);
+ return result;
+ }
+
+ public static int[] readTlsVariableLengthUnsignedShortVector(DataInput in, int maxSizeBytes)
+ throws IOException {
+ int sizeBytes = readTlsVariableLengthVectorSizeBytes(in, maxSizeBytes);
+ int elementCount = sizeBytes / 2;
+ int[] result = new int[elementCount];
+ for (int i = 0; i < elementCount; i++) {
+ result[i] = in.readUnsignedShort();
+ }
+ return result;
+ }
+
+ private static int readTlsVariableLengthVectorSizeBytes(DataInput in, int maxSizeBytes)
+ throws IOException {
+ if (maxSizeBytes < 0x100) {
+ return in.readUnsignedByte();
+ } else if (maxSizeBytes < 0x10000) {
+ return in.readUnsignedShort();
+ } else if (maxSizeBytes < 0x1000000) {
+ return readUnsignedInt24(in);
+ } else {
+ return in.readInt();
+ }
+ }
+}
diff --git a/support/src/test/java/libcore/tlswire/util/TlsProtocolVersion.java b/support/src/test/java/libcore/tlswire/util/TlsProtocolVersion.java
new file mode 100644
index 0000000..f58faf2
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/util/TlsProtocolVersion.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.util;
+
+import java.io.DataInput;
+import java.io.IOException;
+
+/**
+ * {@code ProtovolVersion} struct from TLS 1.2 RFC 5246.
+ */
+public class TlsProtocolVersion {
+ public static final TlsProtocolVersion SSLV3 = new TlsProtocolVersion(3, 0, "SSLv3");
+ public static final TlsProtocolVersion TLSv1_0 = new TlsProtocolVersion(3, 1, "TLSv1.0");
+ public static final TlsProtocolVersion TLSv1_1 = new TlsProtocolVersion(3, 2, "TLSv1.1");
+ public static final TlsProtocolVersion TLSv1_2 = new TlsProtocolVersion(3, 3, "TLSv1.2");
+
+ public final int major;
+ public final int minor;
+ public final String name;
+
+ private TlsProtocolVersion(int major, int minor, String name) {
+ this.major = major;
+ this.minor = minor;
+ this.name = name;
+ }
+
+ public static TlsProtocolVersion valueOf(int major, int minor) {
+ if (major == 3) {
+ switch (minor) {
+ case 0:
+ return SSLV3;
+ case 1:
+ return TLSv1_0;
+ case 2:
+ return TLSv1_1;
+ case 3:
+ return TLSv1_2;
+ }
+ }
+ return new TlsProtocolVersion(major, minor, major + "." + minor);
+ }
+
+ public static TlsProtocolVersion read(DataInput in) throws IOException {
+ int major = in.readUnsignedByte();
+ int minor = in.readUnsignedByte();
+ return TlsProtocolVersion.valueOf(major, minor);
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + major;
+ result = prime * result + minor;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ TlsProtocolVersion other = (TlsProtocolVersion) obj;
+ if (major != other.major) {
+ return false;
+ }
+ if (minor != other.minor) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/support/src/test/java/tests/net/StuckServer.java b/support/src/test/java/tests/net/StuckServer.java
index f7a3118..d6b038b 100644
--- a/support/src/test/java/tests/net/StuckServer.java
+++ b/support/src/test/java/tests/net/StuckServer.java
@@ -21,6 +21,7 @@
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
+import java.net.UnknownHostException;
import java.util.ArrayList;
/**
@@ -29,6 +30,19 @@
public final class StuckServer {
private static final boolean DEBUG = false;
+ // RFC 5737 implies this network -- "test net 1" -- will be unreachable.
+ // (There are two other networks to try if we have trouble with this one.)
+ // We've had trouble with 10.* in the past (because test labs running CTS often use
+ // net 10!) but hopefully this network will be better.
+ public static final InetAddress UNREACHABLE_ADDRESS;
+ static {
+ try {
+ UNREACHABLE_ADDRESS = InetAddress.getByAddress(new byte[] { (byte) 192, 0, 2, 0 });
+ } catch (UnknownHostException ex) {
+ throw new AssertionError(ex);
+ }
+ }
+
private ServerSocket serverSocket;
private InetSocketAddress address;
private ArrayList<Socket> clients = new ArrayList<Socket>();
@@ -57,12 +71,7 @@
}
} else {
// In general, though, you don't want to rely on listen(2) backlog. http://b/6971145.
- // RFC 5737 implies this network will be unreachable. (There are two other networks
- // to try if we have trouble with this one.)
- // We've had trouble with 10.* in the past (because test labs running CTS often use
- // net 10!) but hopefully this network will be better.
- InetAddress testNet1 = InetAddress.getByAddress(new byte[] { (byte) 192, 0, 2, 0 });
- this.address = new InetSocketAddress(testNet1, 80);
+ this.address = new InetSocketAddress(UNREACHABLE_ADDRESS, 80);
}
}
diff --git a/support/src/test/java/tests/support/Support_Configuration.java b/support/src/test/java/tests/support/Support_Configuration.java
index 9cb617d..0658d54 100644
--- a/support/src/test/java/tests/support/Support_Configuration.java
+++ b/support/src/test/java/tests/support/Support_Configuration.java
@@ -75,11 +75,6 @@
public static String IPv6GlobalAddressJcl4 = "2001:4860:8004::67"; // ipv6.google.com
- // ip address that resolves to a host that is not present on the local
- // network
- // this allows us to check the timeouts for connect
- public static String ResolvedNotExistingHost = "9.26.194.72";
-
// BEGIN android-changed
/**
* An address that resolves to more than one IP address so that the
@@ -279,11 +274,6 @@
URLConnectionDate = Long.parseLong(value);
}
- value = props.get("ResolvedNotExistingHost");
- if (value != null) {
- ResolvedNotExistingHost = value;
- }
-
value = props.get("InetAlias1");
if (value != null) {
InetAlias1 = value;