Merge "Improve patches to sun.security on top of upstream OpenJDK8u121-b13."
diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java
index 6dd1ba6..bbf0d99 100644
--- a/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/dalvik/src/main/java/dalvik/system/DexFile.java
@@ -526,4 +526,13 @@
*/
public native static String getNonProfileGuidedCompilerFilter(String filter);
+ /**
+ * Returns the version of the compiler filter that is suitable for safe mode.
+ * If the input is not a valid filter, or the filter is already suitable for
+ * safe mode, this returns the input.
+ *
+ * @hide
+ */
+ public native static String getSafeModeCompilerFilter(String filter);
+
}
diff --git a/expectations/brokentests.txt b/expectations/brokentests.txt
index cd24094..59546b5 100644
--- a/expectations/brokentests.txt
+++ b/expectations/brokentests.txt
@@ -1,145 +1,6 @@
/*
- * This file contains expectations for tests that we'd like to eventually fix, but aren't urgent.
+ * TODO: Remove this file entirely.
*/
[
-{
- description: "libcore.java.io.OldFileTest#test_deleteOnExit fails on IRM05 mysid-user",
- name: "libcore.java.io.OldFileTest#test_deleteOnExit",
- bug: 5834665
-},
-{
- description: "We're retiring the security manager. Unfortunately, tests all over the place
- need to check that they're secure, so they all fail when we refuse to install
- a security manager. This suppresses all of these failures.",
- result: EXEC_FAILED,
- failure: "disable securityManager",
- pattern: ".*java.lang.SecurityException\\s+at java.lang.System.setSecurityManager.*",
- bug: 2585285
-},
-{
- description: "ignore compilation errors due to different available APIs",
- result: COMPILE_FAILED,
- failure: "ignore compilation errors",
- pattern: ".*\\.java:\\d+: cannot find symbol.*"
-},
-{
- description: "the average length of possible UTF-8 sequences is 2 bytes.",
- result: EXEC_FAILED,
- name: "org.apache.harmony.tests.java.nio.charset.UTFCharsetEncoderTest#testSpecificDefaultValue",
- substring: "junit.framework.AssertionFailedError: expected:<1.1> but was:<2.0>"
-},
-{
- description: "Some tests (ExcludedProxyTest) connect to a public webserver to check that the HTTP client works",
- result: EXEC_FAILED,
- failure: "connect to the Internet",
- pattern: ".*java.net.UnknownHostException:.*jcltest.apache.org.*"
-},
-{
- description: "Some tests (ExcludedProxyTest) connect to a public webserver to check that the HTTP client works",
- result: EXEC_FAILED,
- names: [
- "com.android.org.apache.harmony.luni.tests.java.net.ExcludedProxyTest"
- ]
-},
-{
- description: "Some tests depend on ICU data, which has changed. Others make assumptions about floating point rounding",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_DateTimeConversion",
- "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_GeneralConversionOther",
- "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_LineSeparator",
- "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_Percent"
- ]
-},
-{
- description: "(Needs investigation) Some tests make assertions that don't make sense, others use broken port allocation logic.",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.java.net.InetAddressTest#test_isReachableLjava_net_NetworkInterfaceII_loopbackInterface"
- ]
-},
-{
- description: "Potentially flakey because they rely on a specific local TCP port being free.",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.java.nio.channels.ServerSocketChannelTest#test_bind_explicitPort"
- ]
-},
-{
- description: "The ResourceBundle code under test is probably not used much on Android and needs a lot of attention.",
- modes: [device],
- bug: 13747957,
- names: [
- "org.apache.harmony.tests.java.util.ControlTest#test_needsReload_LStringLLocaleLStringLClassLoaderResourceBundleJ"
- ]
-},
-{
- description: "Fails in CTS, passes in CoreTestRunner.",
- result: EXEC_FAILED,
- modes: [device],
- names: [
- "org.apache.harmony.tests.java.net.URLConnection#test_getContentEncoding",
- "libcore.java.text.OldNumberFormatTest#test_parseLjava_lang_String",
- "libcore.java.nio.channels.OldSocketChannelTest#test_writeLjava_nio_ByteBuffer_Nonblocking_HugeData",
- "org.apache.harmony.tests.java.lang.ProcessManagerTest#testSleep",
- "libcore.java.security.cert.OldPKIXParametersTest#testPKIXParametersKeyStore04"
- ]
-},
-{
- description: "Suffers from DH slowness, disabling for now.",
- result: EXEC_FAILED,
- names: [
- "libcore.java.security.OldDHTest#testDHGen",
- "libcore.java.security.OldKeyPairGeneratorTestDH#testKeyPairGenerator",
- "libcore.javax.crypto.spec.KeyPairGeneratorTestDH#testKeyPairGenerator",
- "libcore.javax.crypto.spec.AlgorithmParametersTestDH#testAlgorithmParameters",
- "libcore.javax.crypto.spec.AlgorithmParameterGeneratorTestDH#testAlgorithmParameterGenerator"
- ]
-},
-{
- description: "Destroys MD5 provider, hurts succeeding tests",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.api.javax.security.cert.X509CertificateTest#testVerifyPublicKey",
- "org.apache.harmony.tests.api.javax.security.cert.X509CertificateTest#testVerifyPublicKeyString"
- ]
-},
-{
- description: "Support_TestWebServer requires isolation.",
- result: EXEC_FAILED,
- names: [
- "libcore.java.net.OldURLClassLoaderTest#test_findResourceLjava_lang_String"
- ]
-},
-{
- description: "Causes OutOfMemoryError to test finalization",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.java.lang.ref.SoftReferenceTest#test_get_SoftReference",
- "org.apache.harmony.crypto.tests.javax.crypto#ExemptionMechanismTest#test_finalize"
- ]
-},
-{
- description: "Causes open dex file error",
- modes: [device],
- names: [
- "org.apache.harmony.tests.java.lang.reflect.GenericSignatureFormatErrorTest#test_signatureFormatError"
- ]
-},
-{
- description: "Requires functional Support_Jetty",
- bug: 28535961,
- result: EXEC_FAILED,
- names: [
- "com.android.org.apache.harmony.luni.tests.java.net.URLClassLoaderTest"
- ]
-},
-{
- description: "Unable to execute Support_AvailTest",
- result: EXEC_FAILED,
- bug: 28535603,
- names: [
- "com.android.org.apache.harmony.luni.tests.internal.process.SystemProcessTest#test_interrupt"
- ]
-}
+
]
diff --git a/expectations/icebox.txt b/expectations/icebox.txt
index db9e3ad..59546b5 100644
--- a/expectations/icebox.txt
+++ b/expectations/icebox.txt
@@ -1,149 +1,6 @@
/*
- * This file contains expectations for tests that we'd like to eventually fix, but aren't urgent.
+ * TODO: Remove this file entirely.
*/
[
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DomTest#testEntityDeclarations",
- substring: "This implementation does not parse entity declarations"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DomTest#testGetWholeTextWithEntityReference",
- substring: "This implementation doesn't resolve entity references in getWholeText"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- name: "libcore.xml.DomTest#testExpandingEntityReferencesOff",
- bug: 3268630,
- substring: "This implementation doesn't include children in entity references"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- name: "libcore.xml.DomTest#testExpandingEntityReferencesOn",
- bug: 3268630,
- substring: "This implementation doesn't expand entity references"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DomTest#testIsElementContentWhitespaceWithDeclaration",
- substring: "This implementation does not recognize element content whitespace"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DomTest#testNotations",
- substring: "This implementation does not parse notations"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- names: [
- "tests.org.w3c.dom.HCNotationsRemoveNamedItemNS#testRemoveNamedItemNS",
- "tests.org.w3c.dom.HCNotationsSetNamedItemNS#testNotationsSetNamedItemNS"
- ]
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DeclarationTest#testGetXmlEncoding",
- substring: "This implementation doesn't parse the encoding from the XML declaration"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DeclarationTest#testGetXmlStandalone",
- substring: "This implementation doesn't parse standalone from the XML declaration"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DeclarationTest#testGetXmlVersion",
- substring: "This implementation doesn't parse the version from the XML declaration"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.NormalizeTest#testSchemaTypeDtd",
- substring: "This implementation's setParameter() supports an unexpected value: schema-type=http://www.w3.org/TR/REC-xml"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "org.apache.harmony.tests.javax.xml.parsers.DocumentBuilderTest#testSetEntityResolver",
- substring: "java.lang.ClassCastException: org.apache.harmony.xml.dom.EntityReferenceImpl"
-},
-{
- description: "many tests attempt to fork a Java executable, but fork the wrong one",
- result: "EXEC_FAILED",
- failure: "should fork a dalvikvm, not a JVM",
- substring: "/system/bin.*IOException"
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- name: "libcore.xml.DomTest#testAttributeNamedIdIsNotAnIdByDefault",
- substring: "This implementation incorrectly interprets the \"id\" attribute as an identifier by default"
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- name: "libcore.xml.DomTest#testDocumentAddChild",
- substring: "Document nodes shouldn't accept child nodes"
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- name: "libcore.xml.DomTest#testElementTraversalFeature",
- substring: "This implementation is expected to support ElementTraversal v. 1.0 but does not."
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- name: "libcore.xml.DomTest#testLoadSaveFeature",
- substring: "This implementation is expected to support LS v. 3.0 but does not."
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- name: "libcore.xml.SaxTest#testYesPrefixesYesNamespaces",
- substring: "The 'namespace-prefix' feature is not supported while the 'namespaces' feature is enabled."
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- name: "org.apache.harmony.tests.javax.xml.parsers.SAXParserFactoryTest#test_newInstance",
- substring: "Expected FactoryConfigurationError was not thrown"
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.javax.xml.parsers.DocumentBuilderFactoryTest#test_isSetXIncludeAware",
- "org.apache.harmony.tests.javax.xml.parsers.DocumentBuilderTest#testIsXIncludeAware",
- "org.apache.harmony.tests.javax.xml.parsers.SAXParserFactoryTest#test_setIsXIncludeAware",
- "org.apache.harmony.tests.javax.xml.parsers.SAXParserTest#testIsXIncludeAware"
- ],
- substring: "java.lang.UnsupportedOperationException: This parser does not support specification \"Unknown\" version \"0.0\""
-},
-{
- description: "a low-impact bug, also present in Crockford's implementation of org.json",
- result: EXEC_FAILED,
- name: "org.json.ParsingTest#test64BitHexValues",
- substring: "Large hex longs shouldn't be yield ints or strings expected:<-1> but was:<0xFFFFFFFFFFFFFFFF>"
-},
-{
- description: "this test needs to be fixed. We supply optional qnames, but this test doesn't expect them",
- result: EXEC_FAILED,
- name: "org.apache.harmony.tests.javax.xml.parsers.SAXParserTest#test_parseLjava_io_InputStreamLorg_xml_sax_helpers_DefaultHandlerLjava_lang_String"
-},
-{
- description: "BouncyCastle allows unrecognized algorithms, but RI does not, not clear if this is a bug",
- result: EXEC_FAILED,
- name: "org.apache.harmony.crypto.tests.javax.crypto.KeyAgreementTest#test_generateSecretLjava_lang_String",
- substring: "junit.framework.AssertionFailedError: NoSuchAlgorithmException expected"
-}
+
]
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index 58a4337..2d60453 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -1,8 +1,49 @@
/*
- * This file contains expectations for tests that were annotated with @KnownFailure at the time
+ * This file contains test expectations for libcore.
+ * TODO: Rename this file to account for the fact that it has both tags and known failures
*/
[
{
+ description: "large tests",
+ result: SUCCESS,
+ names: [
+ /* libcore tests that take over 15 minutes on device because of DHParametersHelper.generateSafePrimes */
+ "org.apache.harmony.crypto.tests.javax.crypto.func.KeyAgreementFunctionalTest",
+ "org.apache.harmony.crypto.tests.javax.crypto.interfaces.DHPrivateKeyTest",
+ "org.apache.harmony.crypto.tests.javax.crypto.interfaces.DHPublicKeyTest",
+ /* non-AOSP tests http://b/8027066 */
+ "java.util.EnumSet.EnumSetBash",
+ "java.io.PipedInputStream.CloseAndAvailableRC",
+ "java.io.PrintStream.OversynchronizedTest",
+ "java.io.PrintWriter.OversynchronizedTest",
+ "java.lang.String.Split",
+ "java.lang.ref.SoftReference.Pin",
+ "java.math.BigInteger.BigIntegerTest",
+ "java.net.MulticastSocket.Test",
+ "java.net.Socket.InheritTimeout",
+ "java.net.Socket.reset.Test",
+ "java.net.URLConnection.TimeoutTest",
+ "java.nio.channels.DatagramChannel.ConnectedSend",
+ "java.nio.channels.FileChannel.ExpandingMap",
+ "java.nio.channels.FileChannel.Transfers",
+ "java.nio.channels.SocketChannel.Open",
+ "java.text.Bidi.Bug6665028",
+ "java.util.Collections.FindSubList",
+ "java.util.Locale.Bug4518797",
+ "java.util.ResourceBundle.Control.StressTest",
+ "java.util.WeakHashMap.GCDuringIteration",
+ "java.util.concurrent.FutureTask.Throw",
+ "java.util.concurrent.locks.ReentrantReadWriteLock.MapLoops",
+ "java.util.zip.LargeZip",
+ "java.util.zip.ZipFile.LargeZipFile",
+ "java.util.zip.ZipFile.ManyEntries",
+ "libcore.java.lang.SystemTest_testArrayCopyConcurrentModification",
+ "sun.nio.cs.FindOneCharEncoderBugs",
+ "sun.nio.cs.SurrogateGB18030Test"
+ ],
+ "tags": [ "large" ]
+},
+{
description: "can't compile a pattern with negative look-behind and quantifiers with upper bounds",
result: EXEC_FAILED,
name: "org.apache.harmony.regex.tests.java.util.regex.PatternTest#test_bug_40103",
@@ -1537,5 +1578,289 @@
names: [
"libcore.java.net.SocketTimeoutTest#testSocketWriteNeverTimeouts"
]
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DomTest#testEntityDeclarations",
+ substring: "This implementation does not parse entity declarations"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DomTest#testGetWholeTextWithEntityReference",
+ substring: "This implementation doesn't resolve entity references in getWholeText"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ name: "libcore.xml.DomTest#testExpandingEntityReferencesOff",
+ bug: 3268630,
+ substring: "This implementation doesn't include children in entity references"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ name: "libcore.xml.DomTest#testExpandingEntityReferencesOn",
+ bug: 3268630,
+ substring: "This implementation doesn't expand entity references"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DomTest#testIsElementContentWhitespaceWithDeclaration",
+ substring: "This implementation does not recognize element content whitespace"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DomTest#testNotations",
+ substring: "This implementation does not parse notations"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ names: [
+ "tests.org.w3c.dom.HCNotationsRemoveNamedItemNS#testRemoveNamedItemNS",
+ "tests.org.w3c.dom.HCNotationsSetNamedItemNS#testNotationsSetNamedItemNS"
+ ]
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DeclarationTest#testGetXmlEncoding",
+ substring: "This implementation doesn't parse the encoding from the XML declaration"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DeclarationTest#testGetXmlStandalone",
+ substring: "This implementation doesn't parse standalone from the XML declaration"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DeclarationTest#testGetXmlVersion",
+ substring: "This implementation doesn't parse the version from the XML declaration"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.NormalizeTest#testSchemaTypeDtd",
+ substring: "This implementation's setParameter() supports an unexpected value: schema-type=http://www.w3.org/TR/REC-xml"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "org.apache.harmony.tests.javax.xml.parsers.DocumentBuilderTest#testSetEntityResolver",
+ substring: "java.lang.ClassCastException: org.apache.harmony.xml.dom.EntityReferenceImpl"
+},
+{
+ description: "many tests attempt to fork a Java executable, but fork the wrong one",
+ result: "EXEC_FAILED",
+ failure: "should fork a dalvikvm, not a JVM",
+ substring: "/system/bin.*IOException"
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ name: "libcore.xml.DomTest#testAttributeNamedIdIsNotAnIdByDefault",
+ substring: "This implementation incorrectly interprets the \"id\" attribute as an identifier by default"
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ name: "libcore.xml.DomTest#testDocumentAddChild",
+ substring: "Document nodes shouldn't accept child nodes"
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ name: "libcore.xml.DomTest#testElementTraversalFeature",
+ substring: "This implementation is expected to support ElementTraversal v. 1.0 but does not."
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ name: "libcore.xml.DomTest#testLoadSaveFeature",
+ substring: "This implementation is expected to support LS v. 3.0 but does not."
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ name: "libcore.xml.SaxTest#testYesPrefixesYesNamespaces",
+ substring: "The 'namespace-prefix' feature is not supported while the 'namespaces' feature is enabled."
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ name: "org.apache.harmony.tests.javax.xml.parsers.SAXParserFactoryTest#test_newInstance",
+ substring: "Expected FactoryConfigurationError was not thrown"
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ names: [
+ "org.apache.harmony.tests.javax.xml.parsers.DocumentBuilderFactoryTest#test_isSetXIncludeAware",
+ "org.apache.harmony.tests.javax.xml.parsers.DocumentBuilderTest#testIsXIncludeAware",
+ "org.apache.harmony.tests.javax.xml.parsers.SAXParserFactoryTest#test_setIsXIncludeAware",
+ "org.apache.harmony.tests.javax.xml.parsers.SAXParserTest#testIsXIncludeAware"
+ ],
+ substring: "java.lang.UnsupportedOperationException: This parser does not support specification \"Unknown\" version \"0.0\""
+},
+{
+ description: "a low-impact bug, also present in Crockford's implementation of org.json",
+ result: EXEC_FAILED,
+ name: "org.json.ParsingTest#test64BitHexValues",
+ substring: "Large hex longs shouldn't be yield ints or strings expected:<-1> but was:<0xFFFFFFFFFFFFFFFF>"
+},
+{
+ description: "this test needs to be fixed. We supply optional qnames, but this test doesn't expect them",
+ result: EXEC_FAILED,
+ name: "org.apache.harmony.tests.javax.xml.parsers.SAXParserTest#test_parseLjava_io_InputStreamLorg_xml_sax_helpers_DefaultHandlerLjava_lang_String"
+},
+{
+ description: "BouncyCastle allows unrecognized algorithms, but RI does not, not clear if this is a bug",
+ result: EXEC_FAILED,
+ name: "org.apache.harmony.crypto.tests.javax.crypto.KeyAgreementTest#test_generateSecretLjava_lang_String",
+ substring: "junit.framework.AssertionFailedError: NoSuchAlgorithmException expected"
+},
+{
+ description: "libcore.java.io.OldFileTest#test_deleteOnExit fails on IRM05 mysid-user",
+ name: "libcore.java.io.OldFileTest#test_deleteOnExit",
+ bug: 5834665
+},
+{
+ description: "We're retiring the security manager. Unfortunately, tests all over the place
+ need to check that they're secure, so they all fail when we refuse to install
+ a security manager. This suppresses all of these failures.",
+ result: EXEC_FAILED,
+ failure: "disable securityManager",
+ pattern: ".*java.lang.SecurityException\\s+at java.lang.System.setSecurityManager.*",
+ bug: 2585285
+},
+{
+ description: "ignore compilation errors due to different available APIs",
+ result: COMPILE_FAILED,
+ failure: "ignore compilation errors",
+ pattern: ".*\\.java:\\d+: cannot find symbol.*"
+},
+{
+ description: "the average length of possible UTF-8 sequences is 2 bytes.",
+ result: EXEC_FAILED,
+ name: "org.apache.harmony.tests.java.nio.charset.UTFCharsetEncoderTest#testSpecificDefaultValue",
+ substring: "junit.framework.AssertionFailedError: expected:<1.1> but was:<2.0>"
+},
+{
+ description: "Some tests (ExcludedProxyTest) connect to a public webserver to check that the HTTP client works",
+ result: EXEC_FAILED,
+ failure: "connect to the Internet",
+ pattern: ".*java.net.UnknownHostException:.*jcltest.apache.org.*"
+},
+{
+ description: "Some tests (ExcludedProxyTest) connect to a public webserver to check that the HTTP client works",
+ result: EXEC_FAILED,
+ names: [
+ "com.android.org.apache.harmony.luni.tests.java.net.ExcludedProxyTest"
+ ]
+},
+{
+ description: "Some tests depend on ICU data, which has changed. Others make assumptions about floating point rounding",
+ result: EXEC_FAILED,
+ names: [
+ "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_DateTimeConversion",
+ "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_GeneralConversionOther",
+ "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_LineSeparator",
+ "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_Percent"
+ ]
+},
+{
+ description: "(Needs investigation) Some tests make assertions that don't make sense, others use broken port allocation logic.",
+ result: EXEC_FAILED,
+ names: [
+ "org.apache.harmony.tests.java.net.InetAddressTest#test_isReachableLjava_net_NetworkInterfaceII_loopbackInterface"
+ ]
+},
+{
+ description: "Potentially flakey because they rely on a specific local TCP port being free.",
+ result: EXEC_FAILED,
+ names: [
+ "org.apache.harmony.tests.java.nio.channels.ServerSocketChannelTest#test_bind_explicitPort"
+ ]
+},
+{
+ description: "The ResourceBundle code under test is probably not used much on Android and needs a lot of attention.",
+ modes: [device],
+ bug: 13747957,
+ names: [
+ "org.apache.harmony.tests.java.util.ControlTest#test_needsReload_LStringLLocaleLStringLClassLoaderResourceBundleJ"
+ ]
+},
+{
+ description: "Fails in CTS, passes in CoreTestRunner.",
+ result: EXEC_FAILED,
+ modes: [device],
+ names: [
+ "org.apache.harmony.tests.java.net.URLConnection#test_getContentEncoding",
+ "libcore.java.text.OldNumberFormatTest#test_parseLjava_lang_String",
+ "libcore.java.nio.channels.OldSocketChannelTest#test_writeLjava_nio_ByteBuffer_Nonblocking_HugeData",
+ "org.apache.harmony.tests.java.lang.ProcessManagerTest#testSleep",
+ "libcore.java.security.cert.OldPKIXParametersTest#testPKIXParametersKeyStore04"
+ ]
+},
+{
+ description: "Suffers from DH slowness, disabling for now.",
+ result: EXEC_FAILED,
+ names: [
+ "libcore.java.security.OldDHTest#testDHGen",
+ "libcore.java.security.OldKeyPairGeneratorTestDH#testKeyPairGenerator",
+ "libcore.javax.crypto.spec.KeyPairGeneratorTestDH#testKeyPairGenerator",
+ "libcore.javax.crypto.spec.AlgorithmParametersTestDH#testAlgorithmParameters",
+ "libcore.javax.crypto.spec.AlgorithmParameterGeneratorTestDH#testAlgorithmParameterGenerator"
+ ]
+},
+{
+ description: "Destroys MD5 provider, hurts succeeding tests",
+ result: EXEC_FAILED,
+ names: [
+ "org.apache.harmony.tests.api.javax.security.cert.X509CertificateTest#testVerifyPublicKey",
+ "org.apache.harmony.tests.api.javax.security.cert.X509CertificateTest#testVerifyPublicKeyString"
+ ]
+},
+{
+ description: "Support_TestWebServer requires isolation.",
+ result: EXEC_FAILED,
+ names: [
+ "libcore.java.net.OldURLClassLoaderTest#test_findResourceLjava_lang_String"
+ ]
+},
+{
+ description: "Causes OutOfMemoryError to test finalization",
+ result: EXEC_FAILED,
+ names: [
+ "org.apache.harmony.tests.java.lang.ref.SoftReferenceTest#test_get_SoftReference",
+ "org.apache.harmony.crypto.tests.javax.crypto#ExemptionMechanismTest#test_finalize"
+ ]
+},
+{
+ description: "Causes open dex file error",
+ modes: [device],
+ names: [
+ "org.apache.harmony.tests.java.lang.reflect.GenericSignatureFormatErrorTest#test_signatureFormatError"
+ ]
+},
+{
+ description: "Requires functional Support_Jetty",
+ bug: 28535961,
+ result: EXEC_FAILED,
+ names: [
+ "com.android.org.apache.harmony.luni.tests.java.net.URLClassLoaderTest"
+ ]
+},
+{
+ description: "Unable to execute Support_AvailTest",
+ result: EXEC_FAILED,
+ bug: 28535603,
+ names: [
+ "com.android.org.apache.harmony.luni.tests.internal.process.SystemProcessTest#test_interrupt"
+ ]
}
]
diff --git a/expectations/taggedtests.txt b/expectations/taggedtests.txt
index cc2a4d6..d13cdd4 100644
--- a/expectations/taggedtests.txt
+++ b/expectations/taggedtests.txt
@@ -1,46 +1,5 @@
/*
- * This file contains expectations for tests that require support from the test runner to complete
- * successfully.
+ * TODO: Remove this file entirely.
*/
[
-{
- description: "large tests",
- result: SUCCESS,
- names: [
- /* libcore tests that take over 15 minutes on device because of DHParametersHelper.generateSafePrimes */
- "org.apache.harmony.crypto.tests.javax.crypto.func.KeyAgreementFunctionalTest",
- "org.apache.harmony.crypto.tests.javax.crypto.interfaces.DHPrivateKeyTest",
- "org.apache.harmony.crypto.tests.javax.crypto.interfaces.DHPublicKeyTest",
- /* non-AOSP tests http://b/8027066 */
- "java.util.EnumSet.EnumSetBash",
- "java.io.PipedInputStream.CloseAndAvailableRC",
- "java.io.PrintStream.OversynchronizedTest",
- "java.io.PrintWriter.OversynchronizedTest",
- "java.lang.String.Split",
- "java.lang.ref.SoftReference.Pin",
- "java.math.BigInteger.BigIntegerTest",
- "java.net.MulticastSocket.Test",
- "java.net.Socket.InheritTimeout",
- "java.net.Socket.reset.Test",
- "java.net.URLConnection.TimeoutTest",
- "java.nio.channels.DatagramChannel.ConnectedSend",
- "java.nio.channels.FileChannel.ExpandingMap",
- "java.nio.channels.FileChannel.Transfers",
- "java.nio.channels.SocketChannel.Open",
- "java.text.Bidi.Bug6665028",
- "java.util.Collections.FindSubList",
- "java.util.Locale.Bug4518797",
- "java.util.ResourceBundle.Control.StressTest",
- "java.util.WeakHashMap.GCDuringIteration",
- "java.util.concurrent.FutureTask.Throw",
- "java.util.concurrent.locks.ReentrantReadWriteLock.MapLoops",
- "java.util.zip.LargeZip",
- "java.util.zip.ZipFile.LargeZipFile",
- "java.util.zip.ZipFile.ManyEntries",
- "libcore.java.lang.SystemTest_testArrayCopyConcurrentModification",
- "sun.nio.cs.FindOneCharEncoderBugs",
- "sun.nio.cs.SurrogateGB18030Test"
- ],
- "tags": [ "large" ]
-}
]
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/README.txt b/luni/src/test/java/libcore/java/lang/reflect/parameter/README.txt
index 6d5a6c2..90a40df 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/parameter/README.txt
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/README.txt
@@ -8,7 +8,7 @@
Regenerate the .dex files with:
make smali
-smali libcore/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetdataTestClasses*.smali \
+smali assemble libcore/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetdataTestClasses*.smali \
-o libcore/luni/src/test/resources/libcore/java/lang/reflect/parameter/parameter_metadata_test_classes.dex
For reference, the valid smali code should be (roughly) the equivalent of the
diff --git a/luni/src/test/java/libcore/sun/util/logging/PlatformLoggerTest.java b/luni/src/test/java/libcore/sun/util/logging/PlatformLoggerTest.java
new file mode 100644
index 0000000..d48d92a
--- /dev/null
+++ b/luni/src/test/java/libcore/sun/util/logging/PlatformLoggerTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 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.sun.util.logging;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.logging.Level;
+
+import sun.util.logging.PlatformLogger;
+
+public class PlatformLoggerTest extends TestCase {
+
+ /**
+ * Checks that the values of the private static final int constants in
+ * {@link PlatformLogger} code match the corresponding
+ * {@link Level#intValue()}. This constraint is mentioned in a comment
+ * in PlatformLogger.java.
+ */
+ public void testLogLevelConstants() throws Exception {
+ assertLogLevel("SEVERE", Level.SEVERE);
+ assertLogLevel("WARNING", Level.WARNING);
+ assertLogLevel("INFO", Level.INFO);
+ assertLogLevel("CONFIG", Level.CONFIG);
+ assertLogLevel("FINE", Level.FINE);
+ assertLogLevel("FINER", Level.FINER);
+ assertLogLevel("FINEST", Level.FINEST);
+ assertLogLevel("ALL", Level.ALL);
+ assertLogLevel("OFF", Level.OFF);
+ }
+
+ private void assertLogLevel(String levelName, Level javaUtilLoggingLevel) throws Exception {
+ Field field = PlatformLogger.class.getDeclaredField(levelName);
+ field.setAccessible(true);
+ int platformLoggerValue = field.getInt(PlatformLogger.class);
+ int javaUtilLoggingValue = javaUtilLoggingLevel.intValue();
+ assertEquals(levelName, javaUtilLoggingValue, platformLoggerValue);
+
+ // Check that the field is a constant (static and final); we don't care about
+ // other modifiers (public/private).
+ int requiredModifiers = Modifier.STATIC | Modifier.FINAL;
+ assertEquals(requiredModifiers, field.getModifiers() & requiredModifiers);
+ }
+
+}
diff --git a/ojluni/src/main/java/java/awt/font/TextAttribute.java b/ojluni/src/main/java/java/awt/font/TextAttribute.java
index 04a921d..7dff4ad 100644
--- a/ojluni/src/main/java/java/awt/font/TextAttribute.java
+++ b/ojluni/src/main/java/java/awt/font/TextAttribute.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -45,6 +45,8 @@
import java.util.Map;
import java.util.HashMap;
+// Android-removed: List of classes for use with attribute keys; Android doesn't have those.
+// Android-removed: "Summary of attributes" section. Android doesn't have the referenced classes.
/**
* The <code>TextAttribute</code> class defines attribute keys and
* attribute values used for text rendering.
@@ -62,7 +64,7 @@
* <LI>a description of the effect.
* </UL>
* <p>
- * <H4>Values</H4>
+ * <H3>Values</H3>
* <UL>
* <LI>The values of attributes must always be immutable.
* <LI>Where value limitations are given, any value outside of that
@@ -90,178 +92,12 @@
*
* </UL>
*
- * @see java.text.AttributedCharacterIterator
*/
-
-// Android-removed: Removed Summary of Attributes.
-/* <h4>Summary of attributes</h4>
- * <p>
- * <font size="-1">
- * <table align="center" border="0" cellspacing="0" cellpadding="2" width="%95"
- * summary="Key, value type, principal constants, and default value
- * behavior of all TextAttributes">
- * <tr bgcolor="#ccccff">
- * <th valign="TOP" align="CENTER">Key</th>
- * <th valign="TOP" align="CENTER">Value Type</th>
- * <th valign="TOP" align="CENTER">Principal Constants</th>
- * <th valign="TOP" align="CENTER">Default Value</th>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #FAMILY}</td>
- * <td valign="TOP">String</td>
- * <td valign="TOP">See Font {@link java.awt.Font#DIALOG DIALOG},
-{@link java.awt.Font#DIALOG_INPUT DIALOG_INPUT},<br> {@link java.awt.Font#SERIF SERIF},
-{@link java.awt.Font#SANS_SERIF SANS_SERIF}, and {@link java.awt.Font#MONOSPACED MONOSPACED}.
-</td>
- * <td valign="TOP">"Default" (use platform default)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #WEIGHT}</td>
- * <td valign="TOP">Number</td>
- * <td valign="TOP">WEIGHT_REGULAR, WEIGHT_BOLD</td>
- * <td valign="TOP">WEIGHT_REGULAR</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #WIDTH}</td>
- * <td valign="TOP">Number</td>
- * <td valign="TOP">WIDTH_CONDENSED, WIDTH_REGULAR,<br>WIDTH_EXTENDED</td>
- * <td valign="TOP">WIDTH_REGULAR</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #POSTURE}</td>
- * <td valign="TOP">Number</td>
- * <td valign="TOP">POSTURE_REGULAR, POSTURE_OBLIQUE</td>
- * <td valign="TOP">POSTURE_REGULAR</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #SIZE}</td>
- * <td valign="TOP">Number</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">12.0</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #TRANSFORM}</td>
- * <td valign="TOP">{@link TransformAttribute}</td>
- * <td valign="TOP">See TransformAttribute {@link TransformAttribute#IDENTITY IDENTITY}</td>
- * <td valign="TOP">TransformAttribute.IDENTITY</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #SUPERSCRIPT}</td>
- * <td valign="TOP">Integer</td>
- * <td valign="TOP">SUPERSCRIPT_SUPER, SUPERSCRIPT_SUB</td>
- * <td valign="TOP">0 (use the standard glyphs and metrics)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #FONT}</td>
- * <td valign="TOP">{@link java.awt.Font}</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">null (do not override font resolution)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #CHAR_REPLACEMENT}</td>
- * <td valign="TOP">{@link GraphicAttribute}</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">null (draw text using font glyphs)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #FOREGROUND}</td>
- * <td valign="TOP">{@link java.awt.Paint}</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">null (use current graphics paint)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #BACKGROUND}</td>
- * <td valign="TOP">{@link java.awt.Paint}</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">null (do not render background)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #UNDERLINE}</td>
- * <td valign="TOP">Integer</td>
- * <td valign="TOP">UNDERLINE_ON</td>
- * <td valign="TOP">-1 (do not render underline)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #STRIKETHROUGH}</td>
- * <td valign="TOP">Boolean</td>
- * <td valign="TOP">STRIKETHROUGH_ON</td>
- * <td valign="TOP">false (do not render strikethrough)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #RUN_DIRECTION}</td>
- * <td valign="TOP">Boolean</td>
- * <td valign="TOP">RUN_DIRECTION_LTR<br>RUN_DIRECTION_RTL</td>
- * <td valign="TOP">null (use {@link java.text.Bidi} standard default)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #BIDI_EMBEDDING}</td>
- * <td valign="TOP">Integer</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">0 (use base line direction)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #JUSTIFICATION}</td>
- * <td valign="TOP">Number</td>
- * <td valign="TOP">JUSTIFICATION_FULL</td>
- * <td valign="TOP">JUSTIFICATION_FULL</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #INPUT_METHOD_HIGHLIGHT}</td>
- * <td valign="TOP">{@link java.awt.im.InputMethodHighlight},<br>{@link java.text.Annotation}</td>
- * <td valign="TOP">(see class)</td>
- * <td valign="TOP">null (do not apply input highlighting)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #INPUT_METHOD_UNDERLINE}</td>
- * <td valign="TOP">Integer</td>
- * <td valign="TOP">UNDERLINE_LOW_ONE_PIXEL,<br>UNDERLINE_LOW_TWO_PIXEL</td>
- * <td valign="TOP">-1 (do not render underline)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #SWAP_COLORS}</td>
- * <td valign="TOP">Boolean</td>
- * <td valign="TOP">SWAP_COLORS_ON</td>
- * <td valign="TOP">false (do not swap colors)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #NUMERIC_SHAPING}</td>
- * <td valign="TOP">{@link java.awt.font.NumericShaper}</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">null (do not shape digits)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #KERNING}</td>
- * <td valign="TOP">Integer</td>
- * <td valign="TOP">KERNING_ON</td>
- * <td valign="TOP">0 (do not request kerning)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #LIGATURES}</td>
- * <td valign="TOP">Integer</td>
- * <td valign="TOP">LIGATURES_ON</td>
- * <td valign="TOP">0 (do not form optional ligatures)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #TRACKING}</td>
- * <td valign="TOP">Number</td>
- * <td valign="TOP">TRACKING_LOOSE, TRACKING_TIGHT</td>
- * <td valign="TOP">0 (do not add tracking)</td>
- * </tr>
- * </table>
- * </font>
- *
- * @see java.awt.Font
- * @see java.awt.font.TextLayout
- */
-// Android-removed
-//
-// {@link java.awt.Font Font},
-// {@link java.awt.font.TextLayout TextLayout},
-// {@link java.text.AttributedCharacterIterator AttributedCharacterIterator},
public final class TextAttribute extends Attribute {
// table of all instances in this class, used by readResolve
- private static final Map instanceMap = new HashMap(29);
+ private static final Map<String, TextAttribute>
+ instanceMap = new HashMap<String, TextAttribute>(29);
/**
* Constructs a <code>TextAttribute</code> with the specified name.
@@ -284,7 +120,7 @@
"subclass didn't correctly implement readResolve");
}
- TextAttribute instance = (TextAttribute) instanceMap.get(getName());
+ TextAttribute instance = instanceMap.get(getName());
if (instance != null) {
return instance;
} else {
@@ -302,6 +138,7 @@
// For use with Font.
//
+ // Android-removed: Don't link to java.awt.Font class, it doesn't exist on Android.
/**
* Attribute key for the font name. Values are instances of
* <b><code>String</code></b>. The default value is
@@ -324,13 +161,6 @@
* The "Bold" in the name is part of the face name, not a separate
* request that the font's weight be bold.</p>
*/
- // Android-removed links to font names.
- //
- // {@link java.awt.Font#DIALOG DIALOG},
- // {@link java.awt.Font#DIALOG_INPUT DIALOG_INPUT},
- // {@link java.awt.Font#SANS_SERIF SANS_SERIF},
- // {@link java.awt.Font#SERIF SERIF}, and
- // {@link java.awt.Font#MONOSPACED MONOSPACED}.
public static final TextAttribute FAMILY =
new TextAttribute("family");
@@ -490,6 +320,7 @@
public static final Float WIDTH_EXTENDED =
Float.valueOf(1.5f);
+ // Android-removed: Don't link to java.awt.Font class, it doesn't exist on Android.
/**
* Attribute key for the posture of a font. Values are instances
* of <b><code>Number</code></b>. The default value is
@@ -510,8 +341,6 @@
* <code>Font.getItalicAngle</code>.
*
*/
- // Android-removed.
- // @see java.awt.Font#getItalicAngle()
public static final TextAttribute POSTURE =
new TextAttribute("posture");
@@ -548,6 +377,8 @@
public static final TextAttribute SIZE =
new TextAttribute("size");
+ // Android-removed: References to classes that don't exist on Android.
+ // These classes were AffineTransform, Font, and TransformAttribute.
/**
* Attribute key for the transform of a font. Values are
* instances of <b><code>TransformAttribute</code></b>. The
@@ -566,23 +397,6 @@
* with a rotated TRANSFORM and an unrotated TRANSFORM will measure as
* having the same ascent, descent, and advance.</p>
*/
- // Android-removed
- //
- // <p>This corresponds to the transform passed to
- // <code>Font.deriveFont(AffineTransform)</code>. Since that
- // transform is mutable and <code>TextAttribute</code> values must
- // not be, the <code>TransformAttribute</code> wrapper class is
- // used.
- //
- // <p>The <code>TransformAttribute</code> class defines the
- // constant {@link TransformAttribute#IDENTITY IDENTITY}.
- // @see TransformAttribute
- // @see java.awt.geom.AffineTransform
- //
- // <p>In styled text, the baselines for each such run are aligned
- // one after the other to potentially create a non-linear baseline
- // for the entire run of text. For more information, see {@link
- // TextLayout#getLayoutPath}.</p>
public static final TextAttribute TRANSFORM =
new TextAttribute("transform");
@@ -621,6 +435,7 @@
public static final Integer SUPERSCRIPT_SUB =
Integer.valueOf(-1);
+ // Android-removed: Don't link to java.awt.Font class, it doesn't exist on Android.
/**
* Attribute key used to provide the font to use to render text.
*
@@ -673,17 +488,6 @@
* <code>Font</code> but can be overridden by other values in the
* <code>Map</code>.
*/
- // Android-removed
- // Values are instances of {@link java.awt.Font}.
- //
- // <p><em>Note:</em><code>Font's</code> <code>Map</code>-based
- // constructor and <code>deriveFont</code> methods do not process
- // the <code>FONT</code> attribute, as these are used to create
- // new <code>Font</code> objects. Instead, {@link
- // java.awt.Font#getFont(Map) Font.getFont(Map)} should be used to
- // handle the <code>FONT</code> attribute.
- //
- // @see java.awt.Font
public static final TextAttribute FONT =
new TextAttribute("font");
@@ -900,6 +704,7 @@
// For use by input method.
//
+ // Android-removed: References to java.awt.im.InputMethodHighlight (doesn't exist on Android).
/**
* Attribute key for input method highlight styles.
*
@@ -909,24 +714,6 @@
*
* @see java.text.Annotation
*/
- // Android-removed
- //
- // <p>Values are instances of {@link
- // java.awt.im.InputMethodHighlight} or {@link
- // java.text.Annotation}.
- //
- // <p>If adjacent runs of text with the same
- // <code>InputMethodHighlight</code> need to be rendered
- // separately, the <code>InputMethodHighlights</code> should be
- // wrapped in <code>Annotation</code> instances.
- //
- // <p>Input method highlights are used while text is being
- // composed by an input method. Text editing components should
- // retain them even if they generally only deal with unstyled
- // text, and make them available to the drawing routines.
- //
- // @see java.awt.Font
- // @see java.awt.im.InputMethodHighlight
public static final TextAttribute INPUT_METHOD_HIGHLIGHT =
new TextAttribute("input method highlight");
diff --git a/ojluni/src/main/java/java/io/RandomAccessFile.java b/ojluni/src/main/java/java/io/RandomAccessFile.java
index 34eb7ab..f4830c1 100755
--- a/ojluni/src/main/java/java/io/RandomAccessFile.java
+++ b/ojluni/src/main/java/java/io/RandomAccessFile.java
@@ -65,10 +65,12 @@
public class RandomAccessFile implements DataOutput, DataInput, Closeable {
+ // BEGIN Android-added: CloseGuard and some helper fields for Android changes in this file.
private final CloseGuard guard = CloseGuard.get();
private final byte[] scratch = new byte[8];
private boolean syncMetadata = false;
private int mode;
+ // END Android-added: CloseGuard and some helper fields for Android changes in this file.
private FileDescriptor fd;
private FileChannel channel = null;
@@ -82,11 +84,14 @@
private Object closeLock = new Object();
private volatile boolean closed = false;
+
+ // BEGIN Android-added: IoTracker.
/**
* A single tracker to track both read and write. The tracker resets when the operation
* performed is different from the operation last performed.
*/
private final IoTracker ioTracker = new IoTracker();
+ // END Android-added: IoTracker.
/**
* Creates a random access file stream to read from, and optionally
@@ -216,43 +221,57 @@
throws FileNotFoundException
{
String name = (file != null ? file.getPath() : null);
- this.mode = -1;
+ int imode = -1;
if (mode.equals("r")) {
- this.mode = O_RDONLY;
+ imode = O_RDONLY;
} else if (mode.startsWith("rw")) {
// Android-changed: Added. O_CREAT
- this.mode = O_RDWR | O_CREAT;
+ // imode = O_RDWR;
+ imode = O_RDWR | O_CREAT;
rw = true;
if (mode.length() > 2) {
if (mode.equals("rws")) {
+ // Android-changed: Don't use O_SYNC for "rws". Is this correct?
+ // imode |= O_SYNC;
syncMetadata = true;
} else if (mode.equals("rwd")) {
- // Android-changed: Should this be O_DSYNC and the above O_SYNC ?
- this.mode |= O_SYNC;
+ // Android-changed: Use O_SYNC rather than O_DSYNC for "rwd". Is this correct?
+ // imode |= O_DSYNC;
+ imode |= O_SYNC;
} else {
- this.mode = -1;
+ imode = -1;
}
}
}
-
- if (this.mode < 0) {
+ if (imode < 0) {
throw new IllegalArgumentException("Illegal mode \"" + mode
+ "\" must be one of "
+ "\"r\", \"rw\", \"rws\","
+ " or \"rwd\"");
}
-
+ // Android-removed: do not use legacy security code
+ /*
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkRead(name);
+ if (rw) {
+ security.checkWrite(name);
+ }
+ }
+ */
if (name == null) {
+ // Android-changed: different exception message in ctor when file == null.
+ // throw new NullPointerException();
throw new NullPointerException("file == null");
}
-
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
this.path = name;
+ this.mode = imode;
- // Android-changed: Use IoBridge.open() instead of open.
- fd = IoBridge.open(file.getPath(), this.mode);
+ // BEGIN Android-changed: Use IoBridge.open() instead of open.
+ fd = IoBridge.open(name, imode);
if (syncMetadata) {
try {
fd.sync();
@@ -261,6 +280,7 @@
}
}
guard.open("close");
+ // END Android-changed: Use IoBridge.open() instead of open.
}
/**
@@ -321,6 +341,8 @@
* end-of-file has been reached.
*/
public int read() throws IOException {
+ // Android-changed: Implement on top of low-level API, not directly natively.
+ // return read0();
return (read(scratch, 0, 1) != -1) ? scratch[0] & 0xff : -1;
}
@@ -332,6 +354,7 @@
* @exception IOException If an I/O error has occurred.
*/
private int readBytes(byte b[], int off, int len) throws IOException {
+ // Android-changed: Implement on top of low-level API, not directly natively.
ioTracker.trackIo(len, IoTracker.Mode.READ);
return IoBridge.read(fd, b, off, len);
}
@@ -474,6 +497,8 @@
* @exception IOException if an I/O error occurs.
*/
public void write(int b) throws IOException {
+ // Android-changed: Implement on top of low-level API, not directly natively.
+ // write0(b);
scratch[0] = (byte) (b & 0xff);
write(scratch, 0, 1);
}
@@ -481,11 +506,13 @@
/**
* Writes a sub array as a sequence of bytes.
* @param b the data to be written
+
* @param off the start offset in the data
* @param len the number of bytes that are written
* @exception IOException If an I/O error has occurred.
*/
private void writeBytes(byte b[], int off, int len) throws IOException {
+ // Android-changed: Implement on top of low-level API, not directly natively.
ioTracker.trackIo(len, IoTracker.Mode.WRITE);
IoBridge.write(fd, b, off, len);
// if we are in "rws" mode, attempt to sync file+metadata
@@ -528,6 +555,7 @@
* @exception IOException if an I/O error occurs.
*/
public long getFilePointer() throws IOException {
+ // Android-changed: Implement on top of low-level API, not directly natively.
try {
return Libcore.os.lseek(fd, 0L, SEEK_CUR);
} catch (ErrnoException errnoException) {
@@ -543,21 +571,26 @@
* change only by writing after the offset has been set beyond the end
* of the file.
*
- * @param offset the offset position, measured in bytes from the
+ * @param pos the offset position, measured in bytes from the
* beginning of the file, at which to set the file
* pointer.
* @exception IOException if {@code pos} is less than
* {@code 0} or if an I/O error occurs.
*/
- public void seek(long offset) throws IOException {
- if (offset < 0) {
- throw new IOException("offset < 0: " + offset);
- }
- try {
- Libcore.os.lseek(fd, offset, SEEK_SET);
- ioTracker.reset();
- } catch (ErrnoException errnoException) {
- throw errnoException.rethrowAsIOException();
+ public void seek(long pos) throws IOException {
+ if (pos < 0) {
+ // Android-changed: different exception message for seek(-1).
+ // throw new IOException("Negative seek offset");
+ throw new IOException("offset < 0: " + pos);
+ } else {
+ // Android-changed: Implement on top of low-level API, not directly natively.
+ // seek0(pos);
+ try {
+ Libcore.os.lseek(fd, pos, SEEK_SET);
+ ioTracker.reset();
+ } catch (ErrnoException errnoException) {
+ throw errnoException.rethrowAsIOException();
+ }
}
}
@@ -568,6 +601,7 @@
* @exception IOException if an I/O error occurs.
*/
public long length() throws IOException {
+ // Android-changed: Implement on top of low-level API, not directly natively.
try {
return Libcore.os.fstat(fd).st_size;
} catch (ErrnoException errnoException) {
@@ -595,6 +629,7 @@
* @since 1.2
*/
public void setLength(long newLength) throws IOException {
+ // BEGIN Android-changed: Implement on top of low-level API, not directly natively.
if (newLength < 0) {
throw new IllegalArgumentException("newLength < 0");
}
@@ -612,6 +647,7 @@
if (syncMetadata) {
fd.sync();
}
+ // END Android-changed: Implement on top of low-level API, not directly natively.
}
@@ -638,10 +674,12 @@
closed = true;
}
+ // BEGIN Android-changed: Implement on top of low-level API, not directly natively.
if (channel != null && channel.isOpen()) {
channel.close();
}
IoBridge.closeAndSignalBlockedThreads(fd);
+ // END Android-changed: Implement on top of low-level API, not directly natively.
}
//
@@ -1166,6 +1204,7 @@
DataOutputStream.writeUTF(str, this);
}
+ // Android-added: use finalize() to detect if not close()d.
@Override protected void finalize() throws Throwable {
try {
if (guard != null) {
diff --git a/ojluni/src/main/java/java/time/zone/IcuZoneRulesProvider.java b/ojluni/src/main/java/java/time/zone/IcuZoneRulesProvider.java
index 0e45290..91d3a4c 100644
--- a/ojluni/src/main/java/java/time/zone/IcuZoneRulesProvider.java
+++ b/ojluni/src/main/java/java/time/zone/IcuZoneRulesProvider.java
@@ -1,18 +1,24 @@
/*
* Copyright (C) 2016 The Android Open Source Project
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. The Android Open Source
+ * Project designates this particular file as subject to the "Classpath"
+ * exception as provided by The Android Open Source Project in the LICENSE
+ * file that accompanied this code.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
*
- * 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.
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+
package java.time.zone;
import android.icu.impl.OlsonTimeZone;
diff --git a/ojluni/src/main/java/java/util/Calendar.java b/ojluni/src/main/java/java/util/Calendar.java
index 2009123..b846211 100644
--- a/ojluni/src/main/java/java/util/Calendar.java
+++ b/ojluni/src/main/java/java/util/Calendar.java
@@ -1773,11 +1773,11 @@
public void setTimeInMillis(long millis) {
// If we don't need to recalculate the calendar field values,
// do nothing.
-// BEGIN Android-changed: Removed ZoneInfo support
+// BEGIN Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
// if (time == millis && isTimeSet && areFieldsSet && areAllFieldsSet
// && (zone instanceof ZoneInfo) && !((ZoneInfo)zone).isDirty()) {
if (time == millis && isTimeSet && areFieldsSet && areAllFieldsSet) {
-// END Android-changed: Removed ZoneInfo support
+// END Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
return;
}
@@ -3508,7 +3508,7 @@
catch (IllegalArgumentException e) {}
}
- // Android-changed: Removed ZoneInfo support/workaround.
+ // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
// Write out the 1.1 FCS object.
stream.defaultWriteObject();
}
@@ -3560,7 +3560,7 @@
serialVersionOnStream = currentSerialVersion;
- // Android-changed: removed ZoneInfo support.
+ // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
// If the deserialized object has a SimpleTimeZone, try to
// replace it with a ZoneInfo equivalent (as of 1.4) in order
diff --git a/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java b/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java
index fef7eed..c569981 100644
--- a/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java
+++ b/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java
@@ -1574,10 +1574,14 @@
zoneOffsets = new int[2];
}
if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) {
- // Android-changed: remove ZoneInfo support.
- zoneOffset = tz.getOffset(time);
- zoneOffsets[0] = tz.getRawOffset();
- zoneOffsets[1] = zoneOffset - zoneOffsets[0];
+ // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+ // if (tz instanceof ZoneInfo) {
+ // zoneOffset = ((ZoneInfo)tz).getOffsets(time, zoneOffsets);
+ // } else {
+ zoneOffset = tz.getOffset(time);
+ zoneOffsets[0] = tz.getRawOffset();
+ zoneOffsets[1] = zoneOffset - zoneOffsets[0];
+ // }
}
if (tzMask != 0) {
if (isFieldSet(tzMask, ZONE_OFFSET)) {
@@ -1911,8 +1915,12 @@
}
int tzMask = fieldMask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK);
if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) {
- // Android-changed: remove ZoneInfo support
- zone.getOffsets(millis - zone.getRawOffset(), zoneOffsets);
+ // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+ // if (zone instanceof ZoneInfo) {
+ // ((ZoneInfo)zone).getOffsetsByWall(millis, zoneOffsets);
+ // } else {
+ zone.getOffsets(millis - zone.getRawOffset(), zoneOffsets);
+ // }
}
if (tzMask != 0) {
if (isFieldSet(tzMask, ZONE_OFFSET)) {
diff --git a/ojluni/src/main/java/javax/crypto/CryptoAllPermission.java b/ojluni/src/main/java/javax/crypto/CryptoAllPermission.java
index 24268b8..be2cde4 100644
--- a/ojluni/src/main/java/javax/crypto/CryptoAllPermission.java
+++ b/ojluni/src/main/java/javax/crypto/CryptoAllPermission.java
@@ -25,6 +25,7 @@
package javax.crypto;
+// Android-changed: We don't implement this permission system on Android.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/crypto/CryptoPermission.java b/ojluni/src/main/java/javax/crypto/CryptoPermission.java
index ec09287..41b315f 100644
--- a/ojluni/src/main/java/javax/crypto/CryptoPermission.java
+++ b/ojluni/src/main/java/javax/crypto/CryptoPermission.java
@@ -28,6 +28,7 @@
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
+// Android-changed: We don't implement this permission system on Android.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/crypto/CryptoPermissions.java b/ojluni/src/main/java/javax/crypto/CryptoPermissions.java
index 0e62b18..245492f 100644
--- a/ojluni/src/main/java/javax/crypto/CryptoPermissions.java
+++ b/ojluni/src/main/java/javax/crypto/CryptoPermissions.java
@@ -31,6 +31,7 @@
import java.io.InputStream;
import java.io.IOException;
+// Android-changed: We don't implement this permission system on Android.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/crypto/CryptoPolicyParser.java b/ojluni/src/main/java/javax/crypto/CryptoPolicyParser.java
index a5a3818..bf1aebe 100644
--- a/ojluni/src/main/java/javax/crypto/CryptoPolicyParser.java
+++ b/ojluni/src/main/java/javax/crypto/CryptoPolicyParser.java
@@ -29,6 +29,7 @@
import java.security.GeneralSecurityException;
+// Android-changed: We don't implement this permission system on Android.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/crypto/JceSecurityManager.java b/ojluni/src/main/java/javax/crypto/JceSecurityManager.java
index 38d9f19..b29939e 100644
--- a/ojluni/src/main/java/javax/crypto/JceSecurityManager.java
+++ b/ojluni/src/main/java/javax/crypto/JceSecurityManager.java
@@ -25,6 +25,7 @@
package javax.crypto;
+// Android-changed: We don't implement this permission system on Android.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLEngine.java b/ojluni/src/main/java/javax/net/ssl/SSLEngine.java
index 26dc64c..aa15ccc 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLEngine.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLEngine.java
@@ -404,600 +404,600 @@
*
* <h4>Cipher suites</h4>
* <table>
- * <thead>
- * <tr>
- * <th>Cipher suite</th>
- * <th>Supported (API Levels)</th>
- * <th>Enabled by default (API Levels)</th>
- * </tr>
- * </thead>
- * <tbody>
- * <tr class="deprecated">
- * <td>SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DHE_DSS_WITH_DES_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DHE_RSA_WITH_DES_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DH_anon_EXPORT_WITH_RC4_40_MD5</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DH_anon_WITH_3DES_EDE_CBC_SHA</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DH_anon_WITH_DES_CBC_SHA</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DH_anon_WITH_RC4_128_MD5</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_EXPORT_WITH_RC4_40_MD5</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr>
- * <td>SSL_RSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>9+</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_WITH_DES_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_WITH_NULL_MD5</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_WITH_NULL_SHA</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_WITH_RC4_128_MD5</td>
- * <td>9–TBD</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_WITH_RC4_128_SHA</td>
- * <td>9–TBD</td>
- * <td>9–23</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>1–8</td>
- * <td>1–8</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA</td>
- * <td>1–8</td>
- * <td>1–8</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_AES_128_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–22</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_AES_128_CBC_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_AES_128_GCM_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_AES_256_CBC_SHA</td>
- * <td>9–22</td>
- * <td>20–22</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_AES_256_CBC_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_AES_256_GCM_SHA384</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_DES_CBC_SHA</td>
- * <td>1–8</td>
- * <td>1–8</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>1–8</td>
- * <td>1–8</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>1–8</td>
- * <td>1–8</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_AES_128_CBC_SHA</td>
- * <td>9–TBD</td>
- * <td>9–TBD</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_AES_128_CBC_SHA256</td>
- * <td>20–TBD</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_AES_128_GCM_SHA256</td>
- * <td>20–TBD</td>
- * <td>20–TBD</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_AES_256_CBC_SHA</td>
- * <td>9–TBD</td>
- * <td>20–TBD</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_AES_256_CBC_SHA256</td>
- * <td>20–TBD</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_AES_256_GCM_SHA384</td>
- * <td>20–TBD</td>
- * <td>20–TBD</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_DES_CBC_SHA</td>
- * <td>1–8</td>
- * <td>1–8</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>1–8</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA</td>
- * <td>1–8</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_DSS_WITH_DES_CBC_SHA</td>
- * <td>1–8</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>1–8</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>1–8</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_RSA_WITH_DES_CBC_SHA</td>
- * <td>1–8</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>1–8</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_3DES_EDE_CBC_SHA</td>
- * <td>1–8</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_AES_128_CBC_SHA</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_AES_128_CBC_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_AES_128_GCM_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_AES_256_CBC_SHA</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_AES_256_CBC_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_AES_256_GCM_SHA384</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_DES_CBC_SHA</td>
- * <td>1–8</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256</td>
- * <td>20+</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384</td>
- * <td>20+</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</td>
- * <td>24+</td>
- * <td>24+</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDHE_ECDSA_WITH_NULL_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDHE_ECDSA_WITH_RC4_128_SHA</td>
- * <td>20–TBD</td>
- * <td>20–23</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA</td>
- * <td>21+</td>
- * <td>21+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA</td>
- * <td>21+</td>
- * <td>21+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256</td>
- * <td>24+</td>
- * <td>24+</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256</td>
- * <td>20+</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384</td>
- * <td>20+</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</td>
- * <td>24+</td>
- * <td>24+</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDHE_RSA_WITH_NULL_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDHE_RSA_WITH_RC4_128_SHA</td>
- * <td>20–TBD</td>
- * <td>20–23</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_NULL_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_RC4_128_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_AES_128_CBC_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_AES_256_CBC_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_NULL_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_RC4_128_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_anon_WITH_AES_128_CBC_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_anon_WITH_AES_256_CBC_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_anon_WITH_NULL_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_anon_WITH_RC4_128_SHA</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_EMPTY_RENEGOTIATION_INFO_SCSV</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_FALLBACK_SCSV</td>
- * <td>21+</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_NULL_WITH_NULL_NULL</td>
- * <td>1–8</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_PSK_WITH_3DES_EDE_CBC_SHA</td>
- * <td>21–22</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_PSK_WITH_AES_128_CBC_SHA</td>
- * <td>21+</td>
- * <td>21+</td>
- * </tr>
- * <tr>
- * <td>TLS_PSK_WITH_AES_256_CBC_SHA</td>
- * <td>21+</td>
- * <td>21+</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_PSK_WITH_RC4_128_SHA</td>
- * <td>21–TBD</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>1–8</td>
- * <td>1–8</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_RSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>1–8</td>
- * <td>1–8</td>
- * </tr>
- * <tr>
- * <td>TLS_RSA_WITH_AES_128_CBC_SHA</td>
- * <td>9+</td>
- * <td>9+</td>
- * </tr>
- * <tr>
- * <td>TLS_RSA_WITH_AES_128_CBC_SHA256</td>
- * <td>20+</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_RSA_WITH_AES_128_GCM_SHA256</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_RSA_WITH_AES_256_CBC_SHA</td>
- * <td>9+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_RSA_WITH_AES_256_CBC_SHA256</td>
- * <td>20+</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_RSA_WITH_AES_256_GCM_SHA384</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_RSA_WITH_DES_CBC_SHA</td>
- * <td>1–8</td>
- * <td>1–8</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_RSA_WITH_NULL_MD5</td>
- * <td>1–8</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_RSA_WITH_NULL_SHA</td>
- * <td>1–8</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_RSA_WITH_NULL_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * </tbody>
+ * <thead>
+ * <tr>
+ * <th>Cipher suite</th>
+ * <th>Supported (API Levels)</th>
+ * <th>Enabled by default (API Levels)</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr class="deprecated">
+ * <td>SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DHE_DSS_WITH_DES_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DHE_RSA_WITH_DES_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DH_anon_EXPORT_WITH_RC4_40_MD5</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DH_anon_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DH_anon_WITH_DES_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DH_anon_WITH_RC4_128_MD5</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_EXPORT_WITH_RC4_40_MD5</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr>
+ * <td>SSL_RSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>9+</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_WITH_DES_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_WITH_NULL_MD5</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_WITH_NULL_SHA</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_WITH_RC4_128_MD5</td>
+ * <td>9-25</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_WITH_RC4_128_SHA</td>
+ * <td>9-25</td>
+ * <td>9-23</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_AES_128_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-22</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_AES_128_CBC_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_AES_128_GCM_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_AES_256_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>20-22</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_AES_256_CBC_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_AES_256_GCM_SHA384</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_DES_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_AES_128_CBC_SHA</td>
+ * <td>9-25</td>
+ * <td>9-25</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_AES_128_CBC_SHA256</td>
+ * <td>20-25</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_AES_128_GCM_SHA256</td>
+ * <td>20-25</td>
+ * <td>20-25</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_AES_256_CBC_SHA</td>
+ * <td>9-25</td>
+ * <td>20-25</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_AES_256_CBC_SHA256</td>
+ * <td>20-25</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_AES_256_GCM_SHA384</td>
+ * <td>20-25</td>
+ * <td>20-25</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_DES_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_DSS_WITH_DES_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_RSA_WITH_DES_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_AES_128_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_AES_128_CBC_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_AES_128_GCM_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_AES_256_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_AES_256_CBC_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_AES_256_GCM_SHA384</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_DES_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256</td>
+ * <td>20+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384</td>
+ * <td>20+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</td>
+ * <td>24+</td>
+ * <td>24+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDHE_ECDSA_WITH_NULL_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDHE_ECDSA_WITH_RC4_128_SHA</td>
+ * <td>20-25</td>
+ * <td>20-23</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA</td>
+ * <td>21+</td>
+ * <td>21+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA</td>
+ * <td>21+</td>
+ * <td>21+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256</td>
+ * <td>24+</td>
+ * <td>24+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256</td>
+ * <td>20+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384</td>
+ * <td>20+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</td>
+ * <td>24+</td>
+ * <td>24+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDHE_RSA_WITH_NULL_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDHE_RSA_WITH_RC4_128_SHA</td>
+ * <td>20-25</td>
+ * <td>20-23</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_NULL_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_RC4_128_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_AES_128_CBC_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_AES_256_CBC_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_NULL_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_RC4_128_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_anon_WITH_AES_128_CBC_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_anon_WITH_AES_256_CBC_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_anon_WITH_NULL_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_anon_WITH_RC4_128_SHA</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_EMPTY_RENEGOTIATION_INFO_SCSV</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_FALLBACK_SCSV</td>
+ * <td>21+</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_NULL_WITH_NULL_NULL</td>
+ * <td>1-8</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_PSK_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>21-22</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_PSK_WITH_AES_128_CBC_SHA</td>
+ * <td>21+</td>
+ * <td>21+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_PSK_WITH_AES_256_CBC_SHA</td>
+ * <td>21+</td>
+ * <td>21+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_PSK_WITH_RC4_128_SHA</td>
+ * <td>21-25</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_RSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_RSA_WITH_AES_128_CBC_SHA</td>
+ * <td>9+</td>
+ * <td>9+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_RSA_WITH_AES_128_CBC_SHA256</td>
+ * <td>20+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_RSA_WITH_AES_128_GCM_SHA256</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_RSA_WITH_AES_256_CBC_SHA</td>
+ * <td>9+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_RSA_WITH_AES_256_CBC_SHA256</td>
+ * <td>20+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_RSA_WITH_AES_256_GCM_SHA384</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_RSA_WITH_DES_CBC_SHA</td>
+ * <td>1-8</td>
+ * <td>1-8</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_RSA_WITH_NULL_MD5</td>
+ * <td>1-8</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_RSA_WITH_NULL_SHA</td>
+ * <td>1-8</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_RSA_WITH_NULL_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * </tbody>
* </table>
*
* <p><em>NOTE</em>: PSK cipher suites are enabled by default only if the {@code SSLContext} through
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLSocket.java b/ojluni/src/main/java/javax/net/ssl/SSLSocket.java
index f2037b4..875ae34 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLSocket.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLSocket.java
@@ -218,495 +218,495 @@
* below. Prior to API Level 9, non-standard (OpenSSL) names had been used (see
* the table following this table).
* <table>
- * <thead>
- * <tr>
- * <th>Cipher suite</th>
- * <th>Supported (API Levels)</th>
- * <th>Enabled by default (API Levels)</th>
- * </tr>
- * </thead>
- * <tbody>
- * <tr class="deprecated">
- * <td>SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DHE_DSS_WITH_DES_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DHE_RSA_WITH_DES_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DH_anon_EXPORT_WITH_RC4_40_MD5</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DH_anon_WITH_3DES_EDE_CBC_SHA</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DH_anon_WITH_DES_CBC_SHA</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_DH_anon_WITH_RC4_128_MD5</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_EXPORT_WITH_RC4_40_MD5</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr>
- * <td>SSL_RSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>9+</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_WITH_DES_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_WITH_NULL_MD5</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_WITH_NULL_SHA</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_WITH_RC4_128_MD5</td>
- * <td>9–TBD</td>
- * <td>9–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>SSL_RSA_WITH_RC4_128_SHA</td>
- * <td>9–TBD</td>
- * <td>9–23</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_AES_128_CBC_SHA</td>
- * <td>9–22</td>
- * <td>9–22</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_AES_128_CBC_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_AES_128_GCM_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_AES_256_CBC_SHA</td>
- * <td>9–22</td>
- * <td>11–22</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_AES_256_CBC_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_DSS_WITH_AES_256_GCM_SHA384</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_AES_128_CBC_SHA</td>
- * <td>9–TBD</td>
- * <td>9–TBD</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_AES_128_CBC_SHA256</td>
- * <td>20–TBD</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_AES_128_GCM_SHA256</td>
- * <td>20–TBD</td>
- * <td>20–TBD</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_AES_256_CBC_SHA</td>
- * <td>9–TBD</td>
- * <td>11–TBD</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_AES_256_CBC_SHA256</td>
- * <td>20–TBD</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DHE_RSA_WITH_AES_256_GCM_SHA384</td>
- * <td>20–TBD</td>
- * <td>20–TBD</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_AES_128_CBC_SHA</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_AES_128_CBC_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_AES_128_GCM_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_AES_256_CBC_SHA</td>
- * <td>9–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_AES_256_CBC_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_DH_anon_WITH_AES_256_GCM_SHA384</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>11–22</td>
- * <td>11–19</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA</td>
- * <td>11+</td>
- * <td>11+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256</td>
- * <td>20+</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA</td>
- * <td>11+</td>
- * <td>11+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384</td>
- * <td>20+</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</td>
- * <td>24+</td>
- * <td>24+</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDHE_ECDSA_WITH_NULL_SHA</td>
- * <td>11–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDHE_ECDSA_WITH_RC4_128_SHA</td>
- * <td>11–TBD</td>
- * <td>11–23</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA</td>
- * <td>21+</td>
- * <td>21+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA</td>
- * <td>21+</td>
- * <td>21+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256</td>
- * <td>24+</td>
- * <td>24+</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>11–22</td>
- * <td>11–19</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA</td>
- * <td>11+</td>
- * <td>11+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256</td>
- * <td>20+</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA</td>
- * <td>11+</td>
- * <td>11+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384</td>
- * <td>20+</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDHE_RSA_WITH_NULL_SHA</td>
- * <td>11–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDHE_RSA_WITH_RC4_128_SHA</td>
- * <td>11–TBD</td>
- * <td>11–23</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>11–22</td>
- * <td>11–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA</td>
- * <td>11–22</td>
- * <td>11–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA</td>
- * <td>11–22</td>
- * <td>11–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_NULL_SHA</td>
- * <td>11–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_ECDSA_WITH_RC4_128_SHA</td>
- * <td>11–22</td>
- * <td>11–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA</td>
- * <td>11–22</td>
- * <td>11–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_AES_128_CBC_SHA</td>
- * <td>11–22</td>
- * <td>11–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_AES_256_CBC_SHA</td>
- * <td>11–22</td>
- * <td>11–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_NULL_SHA</td>
- * <td>11–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_RSA_WITH_RC4_128_SHA</td>
- * <td>11–22</td>
- * <td>11–19</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA</td>
- * <td>11–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_anon_WITH_AES_128_CBC_SHA</td>
- * <td>11–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_anon_WITH_AES_256_CBC_SHA</td>
- * <td>11–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_anon_WITH_NULL_SHA</td>
- * <td>11–22</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_ECDH_anon_WITH_RC4_128_SHA</td>
- * <td>11–22</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_EMPTY_RENEGOTIATION_INFO_SCSV</td>
- * <td>11+</td>
- * <td>11+</td>
- * </tr>
- * <tr>
- * <td>TLS_FALLBACK_SCSV</td>
- * <td>21+</td>
- * <td></td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_PSK_WITH_3DES_EDE_CBC_SHA</td>
- * <td>21–22</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_PSK_WITH_AES_128_CBC_SHA</td>
- * <td>21+</td>
- * <td>21+</td>
- * </tr>
- * <tr>
- * <td>TLS_PSK_WITH_AES_256_CBC_SHA</td>
- * <td>21+</td>
- * <td>21+</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_PSK_WITH_RC4_128_SHA</td>
- * <td>21–TBD</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_RSA_WITH_AES_128_CBC_SHA</td>
- * <td>9+</td>
- * <td>9+</td>
- * </tr>
- * <tr>
- * <td>TLS_RSA_WITH_AES_128_CBC_SHA256</td>
- * <td>20+</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_RSA_WITH_AES_128_GCM_SHA256</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_RSA_WITH_AES_256_CBC_SHA</td>
- * <td>9+</td>
- * <td>11+</td>
- * </tr>
- * <tr>
- * <td>TLS_RSA_WITH_AES_256_CBC_SHA256</td>
- * <td>20+</td>
- * <td></td>
- * </tr>
- * <tr>
- * <td>TLS_RSA_WITH_AES_256_GCM_SHA384</td>
- * <td>20+</td>
- * <td>20+</td>
- * </tr>
- * <tr>
- * <td>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</td>
- * <td>24+</td>
- * <td>24+</td>
- * </tr>
- * <tr class="deprecated">
- * <td>TLS_RSA_WITH_NULL_SHA256</td>
- * <td>20–22</td>
- * <td></td>
- * </tr>
- * </tbody>
+ * <thead>
+ * <tr>
+ * <th>Cipher suite</th>
+ * <th>Supported (API Levels)</th>
+ * <th>Enabled by default (API Levels)</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr class="deprecated">
+ * <td>SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DHE_DSS_WITH_DES_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DHE_RSA_WITH_DES_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DH_anon_EXPORT_WITH_RC4_40_MD5</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DH_anon_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DH_anon_WITH_DES_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_DH_anon_WITH_RC4_128_MD5</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_EXPORT_WITH_DES40_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_EXPORT_WITH_RC4_40_MD5</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr>
+ * <td>SSL_RSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>9+</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_WITH_DES_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_WITH_NULL_MD5</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_WITH_NULL_SHA</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_WITH_RC4_128_MD5</td>
+ * <td>9-25</td>
+ * <td>9-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>SSL_RSA_WITH_RC4_128_SHA</td>
+ * <td>9-25</td>
+ * <td>9-23</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_AES_128_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>9-22</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_AES_128_CBC_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_AES_128_GCM_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_AES_256_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td>11-22</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_AES_256_CBC_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_DSS_WITH_AES_256_GCM_SHA384</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_AES_128_CBC_SHA</td>
+ * <td>9-25</td>
+ * <td>9-25</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_AES_128_CBC_SHA256</td>
+ * <td>20-25</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_AES_128_GCM_SHA256</td>
+ * <td>20-25</td>
+ * <td>20-25</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_AES_256_CBC_SHA</td>
+ * <td>9-25</td>
+ * <td>11-25</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_AES_256_CBC_SHA256</td>
+ * <td>20-25</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DHE_RSA_WITH_AES_256_GCM_SHA384</td>
+ * <td>20-25</td>
+ * <td>20-25</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_AES_128_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_AES_128_CBC_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_AES_128_GCM_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_AES_256_CBC_SHA</td>
+ * <td>9-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_AES_256_CBC_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_DH_anon_WITH_AES_256_GCM_SHA384</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>11-22</td>
+ * <td>11-19</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA</td>
+ * <td>11+</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256</td>
+ * <td>20+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA</td>
+ * <td>11+</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384</td>
+ * <td>20+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</td>
+ * <td>24+</td>
+ * <td>24+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDHE_ECDSA_WITH_NULL_SHA</td>
+ * <td>11-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDHE_ECDSA_WITH_RC4_128_SHA</td>
+ * <td>11-25</td>
+ * <td>11-23</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA</td>
+ * <td>21+</td>
+ * <td>21+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA</td>
+ * <td>21+</td>
+ * <td>21+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256</td>
+ * <td>24+</td>
+ * <td>24+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>11-22</td>
+ * <td>11-19</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA</td>
+ * <td>11+</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256</td>
+ * <td>20+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA</td>
+ * <td>11+</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384</td>
+ * <td>20+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256</td>
+ * <td>24+</td>
+ * <td>24+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDHE_RSA_WITH_NULL_SHA</td>
+ * <td>11-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDHE_RSA_WITH_RC4_128_SHA</td>
+ * <td>11-25</td>
+ * <td>11-23</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>11-22</td>
+ * <td>11-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA</td>
+ * <td>11-22</td>
+ * <td>11-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA</td>
+ * <td>11-22</td>
+ * <td>11-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_NULL_SHA</td>
+ * <td>11-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_ECDSA_WITH_RC4_128_SHA</td>
+ * <td>11-22</td>
+ * <td>11-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>11-22</td>
+ * <td>11-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_AES_128_CBC_SHA</td>
+ * <td>11-22</td>
+ * <td>11-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_AES_256_CBC_SHA</td>
+ * <td>11-22</td>
+ * <td>11-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_NULL_SHA</td>
+ * <td>11-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_RSA_WITH_RC4_128_SHA</td>
+ * <td>11-22</td>
+ * <td>11-19</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>11-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_anon_WITH_AES_128_CBC_SHA</td>
+ * <td>11-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_anon_WITH_AES_256_CBC_SHA</td>
+ * <td>11-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_anon_WITH_NULL_SHA</td>
+ * <td>11-22</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_ECDH_anon_WITH_RC4_128_SHA</td>
+ * <td>11-22</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_EMPTY_RENEGOTIATION_INFO_SCSV</td>
+ * <td>11+</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_FALLBACK_SCSV</td>
+ * <td>21+</td>
+ * <td></td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_PSK_WITH_3DES_EDE_CBC_SHA</td>
+ * <td>21-22</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_PSK_WITH_AES_128_CBC_SHA</td>
+ * <td>21+</td>
+ * <td>21+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_PSK_WITH_AES_256_CBC_SHA</td>
+ * <td>21+</td>
+ * <td>21+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_PSK_WITH_RC4_128_SHA</td>
+ * <td>21-25</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_RSA_WITH_AES_128_CBC_SHA</td>
+ * <td>9+</td>
+ * <td>9+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_RSA_WITH_AES_128_CBC_SHA256</td>
+ * <td>20+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_RSA_WITH_AES_128_GCM_SHA256</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_RSA_WITH_AES_256_CBC_SHA</td>
+ * <td>9+</td>
+ * <td>11+</td>
+ * </tr>
+ * <tr>
+ * <td>TLS_RSA_WITH_AES_256_CBC_SHA256</td>
+ * <td>20+</td>
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>TLS_RSA_WITH_AES_256_GCM_SHA384</td>
+ * <td>20+</td>
+ * <td>20+</td>
+ * </tr>
+ * <tr class="deprecated">
+ * <td>TLS_RSA_WITH_NULL_SHA256</td>
+ * <td>20-22</td>
+ * <td></td>
+ * </tr>
+ * </tbody>
* </table>
*
* <p><em>NOTE</em>: PSK cipher suites are enabled by default only if the {@code SSLContext} through
diff --git a/ojluni/src/main/java/javax/security/auth/AuthPermission.java b/ojluni/src/main/java/javax/security/auth/AuthPermission.java
index 651e9a3..00eef9e 100644
--- a/ojluni/src/main/java/javax/security/auth/AuthPermission.java
+++ b/ojluni/src/main/java/javax/security/auth/AuthPermission.java
@@ -25,6 +25,7 @@
package javax.security.auth;
+// Android-changed: We don't implement this permission system on Android.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/security/auth/PrivateCredentialPermission.java b/ojluni/src/main/java/javax/security/auth/PrivateCredentialPermission.java
index ca52a1b2..9f5eea9 100644
--- a/ojluni/src/main/java/javax/security/auth/PrivateCredentialPermission.java
+++ b/ojluni/src/main/java/javax/security/auth/PrivateCredentialPermission.java
@@ -29,6 +29,7 @@
import java.security.Permission;
import java.security.Principal;
+// Android-changed: We don't implement this permission system on Android.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/security/auth/SubjectDomainCombiner.java b/ojluni/src/main/java/javax/security/auth/SubjectDomainCombiner.java
index 8e07d4b..4ad9a37 100644
--- a/ojluni/src/main/java/javax/security/auth/SubjectDomainCombiner.java
+++ b/ojluni/src/main/java/javax/security/auth/SubjectDomainCombiner.java
@@ -27,6 +27,7 @@
import java.security.ProtectionDomain;
+// Android-changed: We don't implement this permission system on Android.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/sun/misc/Hashing.java b/ojluni/src/main/java/sun/misc/Hashing.java
deleted file mode 100644
index 2b3b144..0000000
--- a/ojluni/src/main/java/sun/misc/Hashing.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.misc;
-
-import java.util.concurrent.ThreadLocalRandom;
-
-/**
- * Hashing utilities.
- *
- * Little endian implementations of Murmur3 hashing.
- */
-public class Hashing {
-
- /**
- * Static utility methods only.
- */
- private Hashing() {
- throw new Error("No instances");
- }
-
- // Spread bits to regularize both segment and index locations,
- // using variant of single-word Wang/Jenkins hash.
- //
- // Based on commit 1424a2a1a9fc53dc8b859a77c02c924.
- public static int singleWordWangJenkinsHash(Object k) {
- int h = k.hashCode();
-
- h += (h << 15) ^ 0xffffcd7d;
- h ^= (h >>> 10);
- h += (h << 3);
- h ^= (h >>> 6);
- h += (h << 2) + (h << 14);
- return h ^ (h >>> 16);
- }
-}
diff --git a/ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java b/ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java
index 96e2e3d..ead18de 100644
--- a/ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java
+++ b/ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java
@@ -123,9 +123,15 @@
TimeZone zi = date.getZone();
if (zi != null) {
int[] offsets = new int[2];
- zoneOffset = zi.getOffset(millis);
- offsets[0] = zi.getRawOffset();
- offsets[1] = zoneOffset - offsets[0];
+ // BEGIN Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+ // if (zi instanceof ZoneInfo) {
+ // zoneOffset = ((ZoneInfo)zi).getOffsets(millis, offsets);
+ // } else {
+ zoneOffset = zi.getOffset(millis);
+ offsets[0] = zi.getRawOffset();
+ offsets[1] = zoneOffset - offsets[0];
+ // }
+ // END Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
// We need to calculate the given millis and time zone
// offset separately for java.util.GregorianCalendar
@@ -185,14 +191,25 @@
// 2) 5:00pm during DST is still interpreted as 5:00pm ST
// 3) 1:30am during ending-DST transition is interpreted
// as 1:30am ST (after transition)
- zoneOffset = zi.getOffset(ms - zi.getRawOffset());
+ // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+ // if (zi instanceof ZoneInfo) {
+ // ((ZoneInfo)zi).getOffsetsByStandard(ms, offsets);
+ // zoneOffset = offsets[0];
+ // } else {
+ zoneOffset = zi.getOffset(ms - zi.getRawOffset());
+ // }
} else {
// 1) 2:30am during starting-DST transition is
// intrepreted as 3:30am DT
// 2) 5:00pm during DST is intrepreted as 5:00pm DT
// 3) 1:30am during ending-DST transition is interpreted
// as 1:30am DT/0:30am ST (before transition)
- zoneOffset = zi.getOffset(ms - zi.getRawOffset());
+ // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+ // if (zi instanceof ZoneInfo) {
+ // zoneOffset = ((ZoneInfo)zi).getOffsetsByWall(ms, offsets);
+ // } else {
+ zoneOffset = zi.getOffset(ms - zi.getRawOffset());
+ // }
}
}
ms -= zoneOffset;
diff --git a/ojluni/src/main/java/sun/util/calendar/BaseCalendar.java b/ojluni/src/main/java/sun/util/calendar/BaseCalendar.java
index 908bec8..a7e763a 100644
--- a/ojluni/src/main/java/sun/util/calendar/BaseCalendar.java
+++ b/ojluni/src/main/java/sun/util/calendar/BaseCalendar.java
@@ -25,7 +25,6 @@
package sun.util.calendar;
-import java.util.Locale;
import java.util.TimeZone;
/**
diff --git a/ojluni/src/main/java/sun/util/calendar/CalendarDate.java b/ojluni/src/main/java/sun/util/calendar/CalendarDate.java
index 205415e..b8e736c 100644
--- a/ojluni/src/main/java/sun/util/calendar/CalendarDate.java
+++ b/ojluni/src/main/java/sun/util/calendar/CalendarDate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -435,7 +435,7 @@
return super.clone();
} catch (CloneNotSupportedException e) {
// this shouldn't happen
- throw new InternalError();
+ throw new InternalError(e);
}
}
diff --git a/ojluni/src/main/java/sun/util/calendar/CalendarSystem.java b/ojluni/src/main/java/sun/util/calendar/CalendarSystem.java
index 17ad0e8..3b9cbf7 100644
--- a/ojluni/src/main/java/sun/util/calendar/CalendarSystem.java
+++ b/ojluni/src/main/java/sun/util/calendar/CalendarSystem.java
@@ -75,25 +75,53 @@
/////////////////////// Calendar Factory Methods /////////////////////////
+ // BEGIN Android-changed: avoid reflection for loading calendar classes.
+ // // Map of calendar names and calendar class names
+ // private static ConcurrentMap<String, String> names;
// Map of calendar names and calendar classes;
private static final Map<String, Class<?>> names;
- // Android-changed: Don't use reflection for Class.forName every time.
+ // Map of calendar names and CalendarSystem instances
+ private static final ConcurrentMap<String, CalendarSystem> calendars =
+ new ConcurrentHashMap<>();
static {
names = new HashMap<>();
names.put("gregorian", Gregorian.class);
names.put("japanese", LocalGregorianCalendar.class);
names.put("julian", JulianCalendar.class);
- // names.put("hebrew", "HebrewCalendar");
- // names.put("iso8601", "ISOCalendar");
- // names.put("taiwanese", "LocalGregorianCalendar");
- // names.put("thaibuddhist", "LocalGregorianCalendar");
+ // END Android-changed: avoid reflection for loading calendar classes.
+ /*
+ "hebrew", "HebrewCalendar",
+ "iso8601", "ISOCalendar",
+ "taiwanese", "LocalGregorianCalendar",
+ "thaibuddhist", "LocalGregorianCalendar",
+ */
}
- // Map of calendar names and CalendarSystem instances
- private static final ConcurrentMap<String, CalendarSystem> calendars =
- new ConcurrentHashMap<>();
+ // BEGIN Android-removed: avoid reflection for loading calendar classes.
+ /*
+ private static void initNames() {
+ ConcurrentMap<String,String> nameMap = new ConcurrentHashMap<>();
+
+ // Associate a calendar name with its class name and the
+ // calendar class name with its date class name.
+ StringBuilder clName = new StringBuilder();
+ for (int i = 0; i < namePairs.length; i += 2) {
+ clName.setLength(0);
+ String cl = clName.append(PACKAGE_NAME).append(namePairs[i+1]).toString();
+ nameMap.put(namePairs[i], cl);
+ }
+ synchronized (CalendarSystem.class) {
+ if (!initialized) {
+ names = nameMap;
+ calendars = new ConcurrentHashMap<>();
+ initialized = true;
+ }
+ }
+ }
+ */
+ // END Android-removed: avoid reflection for loading calendar classes.
private final static Gregorian GREGORIAN_INSTANCE = new Gregorian();
@@ -141,13 +169,12 @@
try {
cal = (CalendarSystem) calendarClass.newInstance();
} catch (Exception e) {
- throw new RuntimeException("internal error", e);
+ throw new InternalError(e);
}
}
if (cal == null) {
return null;
}
-
CalendarSystem cs = calendars.putIfAbsent(calendarName, cal);
return (cs == null) ? cal : cs;
}
@@ -161,7 +188,7 @@
* Unicode escape sequences
*/
public static Properties getCalendarProperties() throws IOException {
- // Android-changed: load from resources.
+ // Android-changed: load calendar Properties from resources.
Properties calendarProps = new Properties();
try (InputStream is = ClassLoader.getSystemResourceAsStream("calendars.properties")) {
calendarProps.load(is);
diff --git a/ojluni/src/main/java/sun/util/calendar/LocalGregorianCalendar.java b/ojluni/src/main/java/sun/util/calendar/LocalGregorianCalendar.java
index 4d0922d..3c969a7 100644
--- a/ojluni/src/main/java/sun/util/calendar/LocalGregorianCalendar.java
+++ b/ojluni/src/main/java/sun/util/calendar/LocalGregorianCalendar.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,13 +25,7 @@
package sun.util.calendar;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
@@ -60,6 +54,7 @@
private int gregorianYear = FIELD_UNDEFINED;
+ @Override
public Date setEra(Era era) {
if (getEra() != era) {
super.setEra(era);
@@ -68,12 +63,14 @@
return this;
}
+ @Override
public Date addYear(int localYear) {
super.addYear(localYear);
gregorianYear += localYear;
return this;
}
+ @Override
public Date setYear(int localYear) {
if (getYear() != localYear) {
super.setYear(localYear);
@@ -82,10 +79,12 @@
return this;
}
+ @Override
public int getNormalizedYear() {
return gregorianYear;
}
+ @Override
public void setNormalizedYear(int normalizedYear) {
this.gregorianYear = normalizedYear;
}
@@ -98,6 +97,7 @@
super.setYear(year);
}
+ @Override
public String toString() {
String time = super.toString();
time = time.substring(time.indexOf('T'));
@@ -118,20 +118,18 @@
}
static LocalGregorianCalendar getLocalGregorianCalendar(String name) {
- // Android-changed: use getCalendarProperties()
Properties calendarProps;
try {
- calendarProps = getCalendarProperties();
- } catch (IOException e) {
- throw new RuntimeException(e);
+ calendarProps = CalendarSystem.getCalendarProperties();
+ } catch (IOException | IllegalArgumentException e) {
+ throw new InternalError(e);
}
-
// Parse calendar.*.eras
String props = calendarProps.getProperty("calendar." + name + ".eras");
if (props == null) {
return null;
}
- List<Era> eras = new ArrayList<Era>();
+ List<Era> eras = new ArrayList<>();
StringTokenizer eraTokens = new StringTokenizer(props, ";");
while (eraTokens.hasMoreTokens()) {
String items = eraTokens.nextToken().trim();
@@ -168,11 +166,12 @@
Era era = new Era(eraName, abbr, since, localTime);
eras.add(era);
}
- // Android-changed: Throw if no eras were found, as other code depends on there being
- // at least one era.
+ // BEGIN Android-changed: Require at least one era.
+ // Other code depends on there being at least one era.
if (eras.isEmpty()) {
throw new RuntimeException("No eras for " + name);
}
+ // END Android-changed: Require at least one era.
Era[] eraArray = new Era[eras.size()];
eras.toArray(eraArray);
@@ -185,22 +184,27 @@
setEras(eras);
}
+ @Override
public String getName() {
return name;
}
+ @Override
public Date getCalendarDate() {
return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
}
+ @Override
public Date getCalendarDate(long millis) {
return getCalendarDate(millis, newCalendarDate());
}
+ @Override
public Date getCalendarDate(long millis, TimeZone zone) {
return getCalendarDate(millis, newCalendarDate(zone));
}
+ @Override
public Date getCalendarDate(long millis, CalendarDate date) {
Date ldate = (Date) super.getCalendarDate(millis, date);
return adjustYear(ldate, millis, ldate.getZoneOffset());
@@ -229,14 +233,17 @@
return ldate;
}
+ @Override
public Date newCalendarDate() {
return new Date();
}
+ @Override
public Date newCalendarDate(TimeZone zone) {
return new Date(zone);
}
+ @Override
public boolean validate(CalendarDate date) {
Date ldate = (Date) date;
Era era = ldate.getEra();
@@ -270,6 +277,7 @@
return false;
}
+ @Override
public boolean normalize(CalendarDate date) {
if (date.isNormalized()) {
return true;
@@ -343,6 +351,7 @@
return true;
}
+ @Override
void normalizeMonth(CalendarDate date) {
normalizeYear(date);
super.normalizeMonth(date);
@@ -364,6 +373,7 @@
* Returns whether the specified Gregorian year is a leap year.
* @see #isLeapYear(Era, int)
*/
+ @Override
public boolean isLeapYear(int gregorianYear) {
return CalendarUtils.isGregorianLeapYear(gregorianYear);
}
@@ -376,6 +386,7 @@
return isLeapYear(gyear);
}
+ @Override
public void getCalendarDateFromFixedDate(CalendarDate date, long fixedDate) {
Date ldate = (Date) date;
super.getCalendarDateFromFixedDate(ldate, fixedDate);
diff --git a/ojluni/src/main/java/sun/util/locale/BaseLocale.java b/ojluni/src/main/java/sun/util/locale/BaseLocale.java
index 6eee582..e0e9ed0 100644
--- a/ojluni/src/main/java/sun/util/locale/BaseLocale.java
+++ b/ojluni/src/main/java/sun/util/locale/BaseLocale.java
@@ -31,6 +31,7 @@
*/
package sun.util.locale;
+import java.lang.ref.SoftReference;
public final class BaseLocale {
@@ -163,11 +164,11 @@
return h;
}
- private static final class Key implements Comparable<Key> {
- private final String lang;
- private final String scrt;
- private final String regn;
- private final String vart;
+ private static final class Key {
+ private final SoftReference<String> lang;
+ private final SoftReference<String> scrt;
+ private final SoftReference<String> regn;
+ private final SoftReference<String> vart;
private final boolean normalized;
private final int hash;
@@ -179,10 +180,10 @@
assert language.intern() == language
&& region.intern() == region;
- lang = language;
- scrt = "";
- regn = region;
- vart = "";
+ lang = new SoftReference(language);
+ scrt = new SoftReference("");
+ regn = new SoftReference(region);
+ vart = new SoftReference("");
this.normalized = true;
int h = language.hashCode();
@@ -203,40 +204,40 @@
String variant, boolean normalized) {
int h = 0;
if (language != null) {
- lang = language;
+ lang = new SoftReference(language);
int len = language.length();
for (int i = 0; i < len; i++) {
h = 31*h + LocaleUtils.toLower(language.charAt(i));
}
} else {
- lang = "";
+ lang = new SoftReference("");
}
if (script != null) {
- scrt = script;
+ scrt = new SoftReference(script);
int len = script.length();
for (int i = 0; i < len; i++) {
h = 31*h + LocaleUtils.toLower(script.charAt(i));
}
} else {
- scrt = "";
+ scrt = new SoftReference("");
}
if (region != null) {
- regn = region;
+ regn = new SoftReference(region);
int len = region.length();
for (int i = 0; i < len; i++) {
h = 31*h + LocaleUtils.toLower(region.charAt(i));
}
} else {
- regn = "";
+ regn = new SoftReference("");
}
if (variant != null) {
- vart = variant;
+ vart = new SoftReference(variant);
int len = variant.length();
for (int i = 0; i < len; i++) {
h = 31*h + variant.charAt(i);
}
} else {
- vart = "";
+ vart = new SoftReference("");
}
hash = h;
this.normalized = normalized;
@@ -244,28 +245,31 @@
@Override
public boolean equals(Object obj) {
- return (this == obj) ||
- (obj instanceof Key)
- && this.hash == ((Key)obj).hash
- && LocaleUtils.caseIgnoreMatch(((Key)obj).lang, this.lang)
- && LocaleUtils.caseIgnoreMatch(((Key)obj).scrt, this.scrt)
- && LocaleUtils.caseIgnoreMatch(((Key)obj).regn, this.regn)
- && ((Key)obj).vart.equals(vart); // variant is case sensitive in JDK!
+ if (this == obj) {
+ return true;
}
- @Override
- public int compareTo(Key other) {
- int res = LocaleUtils.caseIgnoreCompare(this.lang, other.lang);
- if (res == 0) {
- res = LocaleUtils.caseIgnoreCompare(this.scrt, other.scrt);
- if (res == 0) {
- res = LocaleUtils.caseIgnoreCompare(this.regn, other.regn);
- if (res == 0) {
- res = this.vart.compareTo(other.vart);
+ if (obj instanceof Key && this.hash == ((Key)obj).hash) {
+ String tl = this.lang.get();
+ String ol = ((Key)obj).lang.get();
+ if (tl != null && ol != null &&
+ LocaleUtils.caseIgnoreMatch(ol, tl)) {
+ String ts = this.scrt.get();
+ String os = ((Key)obj).scrt.get();
+ if (ts != null && os != null &&
+ LocaleUtils.caseIgnoreMatch(os, ts)) {
+ String tr = this.regn.get();
+ String or = ((Key)obj).regn.get();
+ if (tr != null && or != null &&
+ LocaleUtils.caseIgnoreMatch(or, tr)) {
+ String tv = this.vart.get();
+ String ov = ((Key)obj).vart.get();
+ return (ov != null && ov.equals(tv));
}
}
}
- return res;
+ }
+ return false;
}
@Override
@@ -278,10 +282,10 @@
return key;
}
- String lang = LocaleUtils.toLowerString(key.lang).intern();
- String scrt = LocaleUtils.toTitleString(key.scrt).intern();
- String regn = LocaleUtils.toUpperString(key.regn).intern();
- String vart = key.vart.intern(); // preserve upper/lower cases
+ String lang = LocaleUtils.toLowerString(key.lang.get()).intern();
+ String scrt = LocaleUtils.toTitleString(key.scrt.get()).intern();
+ String regn = LocaleUtils.toUpperString(key.regn.get()).intern();
+ String vart = key.vart.get().intern(); // preserve upper/lower cases
return new Key(lang, scrt, regn, vart, true);
}
@@ -294,12 +298,18 @@
@Override
protected Key normalizeKey(Key key) {
+ assert key.lang.get() != null &&
+ key.scrt.get() != null &&
+ key.regn.get() != null &&
+ key.vart.get() != null;
+
return Key.normalize(key);
}
@Override
protected BaseLocale createObject(Key key) {
- return new BaseLocale(key.lang, key.scrt, key.regn, key.vart);
+ return new BaseLocale(key.lang.get(), key.scrt.get(),
+ key.regn.get(), key.vart.get());
}
}
}
diff --git a/ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java b/ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java
index 378fb6c..81fa86e 100644
--- a/ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java
+++ b/ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java
@@ -419,8 +419,9 @@
}
if (variant.length() > 0) {
- // normalize separators to "_"
+ // BEGIN Android-added: normalize separators to "_"
variant = variant.replaceAll(LanguageTag.SEP, BaseLocale.SEP);
+ // END Android-added: normalize separators to "_"
int errIdx = checkVariants(variant, BaseLocale.SEP);
if (errIdx != -1) {
throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
diff --git a/ojluni/src/main/java/sun/util/locale/LanguageTag.java b/ojluni/src/main/java/sun/util/locale/LanguageTag.java
index fc7b07b..2247398 100644
--- a/ojluni/src/main/java/sun/util/locale/LanguageTag.java
+++ b/ojluni/src/main/java/sun/util/locale/LanguageTag.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -134,7 +134,7 @@
}
/*
- * BNF in RFC5464
+ * BNF in RFC5646
*
* Language-Tag = langtag ; normal language tags
* / privateuse ; private use tag
diff --git a/ojluni/src/main/java/sun/util/locale/LocaleMatcher.java b/ojluni/src/main/java/sun/util/locale/LocaleMatcher.java
index 6b5f597..70fabc7 100644
--- a/ojluni/src/main/java/sun/util/locale/LocaleMatcher.java
+++ b/ojluni/src/main/java/sun/util/locale/LocaleMatcher.java
@@ -212,7 +212,7 @@
if (range.equals("*")) {
continue;
}
-
+ // Android-changed: backport OpenJDK 9 fix for JDK-8166994
String rangeForRegex = range.replace("*", "\\p{Alnum}*");
while (rangeForRegex.length() > 0) {
for (String tag : tags) {
@@ -242,6 +242,7 @@
}
public static List<LanguageRange> parse(String ranges) {
+ // Android-changed: backport OpenJDK 9 fix for JDK-8166994
ranges = ranges.replace(" ", "").toLowerCase();
if (ranges.startsWith("accept-language:")) {
ranges = ranges.substring(16); // delete unnecessary prefix
@@ -331,6 +332,7 @@
return list;
}
+ // BEGIN Android-added: backport OpenJDK 9 fix for JDK-8166994
/**
* A faster alternative approach to String.replaceFirst(), if the given
* string is a literal String, not a regex.
@@ -345,6 +347,7 @@
+ range.substring(pos + substr.length());
}
}
+ // END Android-added: backport OpenJDK 9 fix for JDK-8166994
private static String[] getEquivalentsForLanguage(String range) {
String r = range;
@@ -354,6 +357,9 @@
String equiv = LocaleEquivalentMaps.singleEquivMap.get(r);
// Return immediately for performance if the first matching
// subtag is found.
+// BEGIN Android-added: backport OpenJDK 9 fix for JDK-8166994
+// Upstream bug: https://bugs.openjdk.java.net/browse/JDK-8166994
+// Upstream fix: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/60837db5d445
return new String[]{replaceFirstSubStringMatch(range,
r, equiv)};
} else if (LocaleEquivalentMaps.multiEquivsMap.containsKey(r)) {
@@ -364,6 +370,7 @@
r, equivs[i]);
}
return result;
+// END Android-added: backport OpenJDK 9 fix for JDK-8166994
}
// Truncate the last subtag simply.
diff --git a/ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java b/ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java
index 88920aa..eae1480 100644
--- a/ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java
+++ b/ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java
@@ -57,8 +57,10 @@
value = entry.get();
}
if (value == null) {
- key = normalizeKey(key);
V newVal = createObject(key);
+ // make sure key is normalized *after* the object creation
+ // so that newVal is assured to be created from a valid key.
+ key = normalizeKey(key);
if (key == null || newVal == null) {
// subclass must return non-null key/value object
return null;
diff --git a/ojluni/src/main/java/sun/util/locale/LocaleUtils.java b/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
index 9a89dc0..ead48fc 100644
--- a/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
+++ b/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/sun/util/logging/LoggingProxy.java b/ojluni/src/main/java/sun/util/logging/LoggingProxy.java
index 9fbcc73..c044a5a 100644
--- a/ojluni/src/main/java/sun/util/logging/LoggingProxy.java
+++ b/ojluni/src/main/java/sun/util/logging/LoggingProxy.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/sun/util/logging/LoggingSupport.java b/ojluni/src/main/java/sun/util/logging/LoggingSupport.java
index dd65b74..67b617d 100644
--- a/ojluni/src/main/java/sun/util/logging/LoggingSupport.java
+++ b/ojluni/src/main/java/sun/util/logging/LoggingSupport.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/sun/util/logging/PlatformLogger.java b/ojluni/src/main/java/sun/util/logging/PlatformLogger.java
index f9849c5..1ed8811 100644
--- a/ojluni/src/main/java/sun/util/logging/PlatformLogger.java
+++ b/ojluni/src/main/java/sun/util/logging/PlatformLogger.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -84,22 +84,18 @@
* @since 1.7
*/
public class PlatformLogger {
- /*
- * These constants should be shortcuts to Level enum constants that
- * the clients of sun.util.logging.PlatformLogger require no source
- * modification and avoid the conversion from int to Level enum.
- *
- * This can be done when JavaFX is converted to use the new PlatformLogger.Level API.
- */
- public static final int OFF = Integer.MAX_VALUE;
- public static final int SEVERE = 1000;
- public static final int WARNING = 900;
- public static final int INFO = 800;
- public static final int CONFIG = 700;
- public static final int FINE = 500;
- public static final int FINER = 400;
- public static final int FINEST = 300;
- public static final int ALL = Integer.MIN_VALUE;
+
+ // The integer values must match that of {@code java.util.logging.Level}
+ // objects.
+ private static final int OFF = Integer.MAX_VALUE;
+ private static final int SEVERE = 1000;
+ private static final int WARNING = 900;
+ private static final int INFO = 800;
+ private static final int CONFIG = 700;
+ private static final int FINE = 500;
+ private static final int FINER = 400;
+ private static final int FINEST = 300;
+ private static final int ALL = Integer.MIN_VALUE;
/**
* PlatformLogger logging levels.
@@ -126,19 +122,19 @@
/* java.util.logging.Level */ Object javaLevel;
// ascending order for binary search matching the list of enum constants
- private static final int[] levelValues = new int[] {
+ private static final int[] LEVEL_VALUES = new int[] {
PlatformLogger.ALL, PlatformLogger.FINEST, PlatformLogger.FINER,
PlatformLogger.FINE, PlatformLogger.CONFIG, PlatformLogger.INFO,
PlatformLogger.WARNING, PlatformLogger.SEVERE, PlatformLogger.OFF
};
public int intValue() {
- return levelValues[this.ordinal()];
+ return LEVEL_VALUES[this.ordinal()];
}
static Level valueOf(int level) {
switch (level) {
- // ordering per the highest occurences in the jdk source
+ // ordering per the highest occurrences in the jdk source
// finest, fine, finer, info first
case PlatformLogger.FINEST : return Level.FINEST;
case PlatformLogger.FINE : return Level.FINE;
@@ -152,7 +148,7 @@
}
// return the nearest Level value >= the given level,
// for level > SEVERE, return SEVERE and exclude OFF
- int i = Arrays.binarySearch(levelValues, 0, levelValues.length-2, level);
+ int i = Arrays.binarySearch(LEVEL_VALUES, 0, LEVEL_VALUES.length-2, level);
return values()[i >= 0 ? i : (-i-1)];
}
}
@@ -169,23 +165,22 @@
}
});
- // Android-removed: Unnecessary on android, and gets in the way of obfuscated
- // releases.
- //
+ // Android-removed: JavaLoggerProxy is unneeded, complicates obfuscated releases.
+ /*
// force loading of all JavaLoggerProxy (sub)classes to make JIT de-optimizations
// less probable. Don't initialize JavaLoggerProxy class since
// java.util.logging may not be enabled.
- //
- // try {
- // Class.forName("sun.util.logging.PlatformLogger$DefaultLoggerProxy",
- // false,
- // PlatformLogger.class.getClassLoader());
- // Class.forName("sun.util.logging.PlatformLogger$JavaLoggerProxy",
- // false, // do not invoke class initializer
- // PlatformLogger.class.getClassLoader());
- // } catch (ClassNotFoundException ex) {
- // throw new InternalError(ex.getMessage());
- // }
+ try {
+ Class.forName("sun.util.logging.PlatformLogger$DefaultLoggerProxy",
+ false,
+ PlatformLogger.class.getClassLoader());
+ Class.forName("sun.util.logging.PlatformLogger$JavaLoggerProxy",
+ false, // do not invoke class initializer
+ PlatformLogger.class.getClassLoader());
+ } catch (ClassNotFoundException ex) {
+ throw new InternalError(ex);
+ }
+ */
}
// Table of known loggers. Maps names to PlatformLoggers.
@@ -267,39 +262,6 @@
/**
* Returns true if a message of the given level would actually
* be logged by this logger.
- *
- * @deprecated Use isLoggable(Level) instead.
- */
- @Deprecated
- public boolean isLoggable(int levelValue) {
- return isLoggable(Level.valueOf(levelValue));
- }
-
- /**
- * Gets the current log level. Returns 0 if the current effective level is
- * not set (equivalent to Logger.getLevel() returns null).
- *
- * @deprecated Use level() instead
- */
- @Deprecated
- public int getLevel() {
- Level level = loggerProxy.getLevel();
- return level != null ? level.intValue() : 0;
- }
-
- /**
- * Sets the log level.
- *
- * @deprecated Use setLevel(Level) instead
- */
- @Deprecated
- public void setLevel(int newLevel) {
- loggerProxy.setLevel(newLevel == 0 ? null : Level.valueOf(newLevel));
- }
-
- /**
- * Returns true if a message of the given level would actually
- * be logged by this logger.
*/
public boolean isLoggable(Level level) {
if (level == null) {
@@ -588,6 +550,16 @@
String logClassName = "sun.util.logging.PlatformLogger";
boolean lookingForLogger = true;
+ // Android-changed: Different way to access throwable.getStackTrace()
+ // OpenJDK's faster way via SharedSecrets.getJavaLangAccess()
+ // is not available on Android.
+ /*
+ for (int ix = 0; ix < depth; ix++) {
+ // Calling getStackTraceElement directly prevents the VM
+ // from paying the cost of building the entire stack frame.
+ StackTraceElement frame =
+ access.getStackTraceElement(throwable, ix);
+ */
for (StackTraceElement frame : throwable.getStackTrace()) {
String cname = frame.getClassName();
if (lookingForLogger) {
diff --git a/ojluni/src/main/java/sun/util/resources/OpenListResourceBundle.java b/ojluni/src/main/java/sun/util/resources/OpenListResourceBundle.java
index 86a91f8..462b0a7 100644
--- a/ojluni/src/main/java/sun/util/resources/OpenListResourceBundle.java
+++ b/ojluni/src/main/java/sun/util/resources/OpenListResourceBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,7 @@
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
@@ -66,7 +67,8 @@
}
// Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification.
- public Object handleGetObject(String key) {
+ @Override
+ protected Object handleGetObject(String key) {
if (key == null) {
throw new NullPointerException();
}
@@ -78,26 +80,39 @@
/**
* Implementation of ResourceBundle.getKeys.
*/
+ @Override
public Enumeration<String> getKeys() {
- ResourceBundle parent = this.parent;
- return new ResourceBundleEnumeration(handleGetKeys(),
- (parent != null) ? parent.getKeys() : null);
- }
+ ResourceBundle parentBundle = this.parent;
+ return new ResourceBundleEnumeration(handleKeySet(),
+ (parentBundle != null) ? parentBundle.getKeys() : null);
+ }
/**
- * Returns a set of keys provided in this resource bundle
+ * Returns a set of keys provided in this resource bundle,
+ * including no parents.
*/
- public Set<String> handleGetKeys() {
+ @Override
+ protected Set<String> handleKeySet() {
loadLookupTablesIfNecessary();
-
return lookup.keySet();
}
- /**
- * Returns the parent bundle
- */
- public OpenListResourceBundle getParent() {
- return (OpenListResourceBundle)parent;
+ @Override
+ public Set<String> keySet() {
+ if (keyset != null) {
+ return keyset;
+ }
+ Set<String> ks = createSet();
+ ks.addAll(handleKeySet());
+ if (parent != null) {
+ ks.addAll(parent.keySet());
+ }
+ synchronized (this) {
+ if (keyset == null) {
+ keyset = ks;
+ }
+ }
+ return keyset;
}
/**
@@ -118,12 +133,9 @@
* We lazily load the lookup hashtable. This function does the
* loading.
*/
- private synchronized void loadLookup() {
- if (lookup != null)
- return;
-
+ private void loadLookup() {
Object[][] contents = getContents();
- Map temp = createMap(contents.length);
+ Map<String, Object> temp = createMap(contents.length);
for (int i = 0; i < contents.length; ++i) {
// key must be non-null String, value must be non-null
String key = (String) contents[i][0];
@@ -133,16 +145,25 @@
}
temp.put(key, value);
}
- lookup = temp;
+ synchronized (this) {
+ if (lookup == null) {
+ lookup = temp;
+ }
+ }
}
/**
* Lets subclasses provide specialized Map implementations.
* Default uses HashMap.
*/
- protected Map createMap(int size) {
- return new HashMap(size);
+ protected <K, V> Map<K, V> createMap(int size) {
+ return new HashMap<>(size);
}
- private Map lookup = null;
+ protected <E> Set<E> createSet() {
+ return new HashSet<>();
+ }
+
+ private volatile Map<String, Object> lookup = null;
+ private volatile Set<String> keyset;
}
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index 7c13ca6..e500bd86 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -1398,7 +1398,6 @@
ojluni/src/main/java/sun/misc/FloatConsts.java \
ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java \
ojluni/src/main/java/sun/misc/FpUtils.java \
- ojluni/src/main/java/sun/misc/Hashing.java \
ojluni/src/main/java/sun/misc/HexDumpEncoder.java \
ojluni/src/main/java/sun/misc/InvalidJarIndexException.java \
ojluni/src/main/java/sun/misc/IOUtils.java \
diff --git a/tools/docs/crypto/README b/tools/docs/crypto/README
index cc6b6eb..9a34b7f 100644
--- a/tools/docs/crypto/README
+++ b/tools/docs/crypto/README
@@ -2,7 +2,8 @@
The central file is data/crypto_support.json, which is a JSON file that contains
the supported API levels for each crypto algorithm that has ever been supported
-by Android. The categories are identified as described in the JCA.
+by Android. The categories are identified as described in the JCA, along with
+a couple extra classes.
Each algorithm has up to three properties:
@@ -24,9 +25,8 @@
Getting the set of supported algorithms is done using
src/java/libcore/java/security/ListProviders.java. It's important that this is
-run using vogar (in mode=device, the default) rather than in an app container,
-as this documentation only includes the libcore-supported crypto support, but
-the Android frameworks (in particular, Android KeyStore) can add additional
+run using vogar in mode=activity rather than the default of mode=device, as
+the Android frameworks (in particular, Android Keystore) can add additional
support.
The data from ListProviders is fed into update_crypto_support.py, which rewrites
@@ -38,4 +38,5 @@
Finally, format_supported_algorithm_table.py reads the data file and outputs
a collection of HTML tables suitable for copying-and-pasting into the docs
-to stdout.
+to stdout. Add --javadoc to produce output appropriate for inclusion in
+Javadoc.
diff --git a/tools/docs/crypto/crypto_docs.py b/tools/docs/crypto/crypto_docs.py
index d1f220d..482e38e 100644
--- a/tools/docs/crypto/crypto_docs.py
+++ b/tools/docs/crypto/crypto_docs.py
@@ -29,3 +29,11 @@
data = json.loads(stripped_contents)
f.close()
return data
+
+
+def find_by_name(seq, name):
+ """Returns the first element in seq with the given name."""
+ for item in seq:
+ if item['name'] == name:
+ return item
+ return None
diff --git a/tools/docs/crypto/data/crypto_support.json b/tools/docs/crypto/data/crypto_support.json
index 38834d9..124a457 100644
--- a/tools/docs/crypto/data/crypto_support.json
+++ b/tools/docs/crypto/data/crypto_support.json
@@ -887,6 +887,1500 @@
{
"algorithms": [
{
+ "deprecated": "true",
+ "name": "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_DSS_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_RC4_128_MD5",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "9-23"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_DES_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+ "supported_api_levels": "24+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "20-23"
+ },
+ {
+ "name": "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
+ "supported_api_levels": "24+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+ "supported_api_levels": "24+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "20-23"
+ },
+ {
+ "name": "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
+ "supported_api_levels": "20+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_PSK_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": ""
+ },
+ {
+ "name": "TLS_PSK_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_PSK_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "1-8"
+ }
+ ],
+ "name": "SSLEngine.Enabled"
+ },
+ {
+ "algorithms": [
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_DSS_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DH_anon_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DH_anon_WITH_RC4_128_MD5",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "name": "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9+"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_NULL_MD5",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_NULL_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_RC4_128_MD5",
+ "supported_api_levels": "9-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "9-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_DES_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "9-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_DSS_WITH_DES_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_AES_256_CBC_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_DES_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+ "supported_api_levels": "24+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_ECDSA_WITH_NULL_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "name": "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
+ "supported_api_levels": "24+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+ "supported_api_levels": "24+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_RSA_WITH_NULL_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_NULL_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_NULL_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_anon_WITH_NULL_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_anon_WITH_RC4_128_SHA",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "name": "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_FALLBACK_SCSV",
+ "supported_api_levels": "21+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_NULL_WITH_NULL_NULL",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_PSK_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "21-22"
+ },
+ {
+ "name": "TLS_PSK_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_PSK_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_PSK_WITH_RC4_128_SHA",
+ "supported_api_levels": "21-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "9+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_256_CBC_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_RSA_WITH_NULL_MD5",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_RSA_WITH_NULL_SHA",
+ "supported_api_levels": "1-8"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_RSA_WITH_NULL_SHA256",
+ "supported_api_levels": "20-22"
+ }
+ ],
+ "name": "SSLEngine.Supported"
+ },
+ {
+ "algorithms": [
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_DSS_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_RC4_128_MD5",
+ "supported_api_levels": "9-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "9-23"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "11-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "11-19"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "11+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "11+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+ "supported_api_levels": "24+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "11-23"
+ },
+ {
+ "name": "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
+ "supported_api_levels": "24+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "11-19"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "11+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "11+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+ "supported_api_levels": "24+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "11-23"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "11-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "11-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "11-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "11-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "11-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "11-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "11-19"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "11-19"
+ },
+ {
+ "name": "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
+ "supported_api_levels": "11+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_PSK_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": ""
+ },
+ {
+ "name": "TLS_PSK_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_PSK_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "11+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20+"
+ }
+ ],
+ "name": "SSLSocket.Enabled"
+ },
+ {
+ "algorithms": [
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_DSS_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DHE_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DH_anon_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_DH_anon_WITH_RC4_128_MD5",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "name": "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "9+"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_DES_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_NULL_MD5",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_NULL_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_RC4_128_MD5",
+ "supported_api_levels": "9-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "SSL_RSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "9-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "9-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "9-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_AES_256_CBC_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_DH_anon_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "11+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "11+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+ "supported_api_levels": "24+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_ECDSA_WITH_NULL_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "11-25"
+ },
+ {
+ "name": "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
+ "supported_api_levels": "24+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "11+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "11+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+ "supported_api_levels": "24+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_RSA_WITH_NULL_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "11-25"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_NULL_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_NULL_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_RSA_WITH_RC4_128_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_anon_WITH_NULL_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_ECDH_anon_WITH_RC4_128_SHA",
+ "supported_api_levels": "11-22"
+ },
+ {
+ "name": "TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
+ "supported_api_levels": "11+"
+ },
+ {
+ "name": "TLS_FALLBACK_SCSV",
+ "supported_api_levels": "21+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_PSK_WITH_3DES_EDE_CBC_SHA",
+ "supported_api_levels": "21-22"
+ },
+ {
+ "name": "TLS_PSK_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "name": "TLS_PSK_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "21+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_PSK_WITH_RC4_128_SHA",
+ "supported_api_levels": "21-25"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_128_CBC_SHA",
+ "supported_api_levels": "9+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_128_CBC_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_128_GCM_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_256_CBC_SHA",
+ "supported_api_levels": "9+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_256_CBC_SHA256",
+ "supported_api_levels": "20+"
+ },
+ {
+ "name": "TLS_RSA_WITH_AES_256_GCM_SHA384",
+ "supported_api_levels": "20+"
+ },
+ {
+ "deprecated": "true",
+ "name": "TLS_RSA_WITH_NULL_SHA256",
+ "supported_api_levels": "20-22"
+ }
+ ],
+ "name": "SSLSocket.Supported"
+ },
+ {
+ "algorithms": [
+ {
"name": "AES",
"supported_api_levels": "23+"
},
@@ -1227,5 +2721,5 @@
"name": "TrustManagerFactory"
}
],
- "last_updated": "2017-03-21 16:04:30 UTC"
+ "last_updated": "2017-05-05 07:40:17 UTC"
}
\ No newline at end of file
diff --git a/tools/docs/crypto/format_supported_algorithm_table.py b/tools/docs/crypto/format_supported_algorithm_table.py
index 3b23066..5a6dd15 100755
--- a/tools/docs/crypto/format_supported_algorithm_table.py
+++ b/tools/docs/crypto/format_supported_algorithm_table.py
@@ -26,6 +26,9 @@
import crypto_docs
+find_by_name = crypto_docs.find_by_name
+
+
def sort_by_name(seq):
return sorted(seq, key=lambda x: x['name'])
@@ -46,10 +49,14 @@
output.append('')
output.append('<ul>')
for category in categories:
- output.append(' <li><a href="#Supported{name}">'
- '<code>{name}</code></a></li>'.format(**category))
+ if not category['name'].endswith('.Enabled'):
+ output.append(' <li><a href="#Supported{name}">'
+ '<code>{name}</code></a></li>'.format(**category))
output.append('</ul>')
for category in categories:
+ if category['name'].endswith('.Enabled'):
+ # These are handled in the "Supported" section below
+ continue
if category['name'] == 'Cipher':
# We display ciphers in a four-column table to conserve space and
# so that it's more comprehensible. To do this, we have to
@@ -155,6 +162,39 @@
i += 1
output.append(' </tbody>')
output.append('</table>')
+ elif category['name'].endswith('.Supported'):
+ # Some categories come with a "Supported" and "Enabled" list, and we
+ # group those together in one table for display. Every entry that's enabled
+ # must be supported, so we can just look up the enabled version for each
+ # supported item
+ basename = category['name'][:-len('.Supported')]
+ supported = sort_by_name(category['algorithms'])
+ enabled = sort_by_name(find_by_name(categories, basename + '.Enabled')['algorithms'])
+ output.append('<h3 id="Supported{0}">{0}</h3>'.format(basename))
+ output.append('<table>')
+ output.append(' <thead>')
+ output.append(' <tr>')
+ output.append(' <th>Algorithm</th>')
+ output.append(' <th>Supported API Levels</th>')
+ output.append(' <th>Enabled By Default</th>')
+ output.append(' </tr>')
+ output.append(' </thead>')
+ output.append(' <tbody>')
+ for algorithm in supported:
+ if 'deprecated' in algorithm and algorithm['deprecated']:
+ output.append(' <tr class="deprecated">')
+ else:
+ output.append(' <tr>')
+ output.append(' <td>{name}</td>'.format(**algorithm))
+ output.append(' <td>{supported_api_levels}</td>'.format(**algorithm))
+ enabled_alg = find_by_name(enabled, algorithm['name'])
+ if enabled_alg is None:
+ output.append(' <td></td>')
+ else:
+ output.append(' <td>{supported_api_levels}</td>'.format(**enabled_alg))
+ output.append(' </tr>')
+ output.append(' </tbody>')
+ output.append('</table>')
else:
output.append('<h3 id="Supported{name}">{name}</h3>'.format(**category))
output.append('<table>')
diff --git a/tools/docs/crypto/run_update_crypto_support.sh b/tools/docs/crypto/run_update_crypto_support.sh
index 5908fcc..501891c 100755
--- a/tools/docs/crypto/run_update_crypto_support.sh
+++ b/tools/docs/crypto/run_update_crypto_support.sh
@@ -13,5 +13,5 @@
exit 1
fi
-make -j48 vogar
+make -j48 vogar dx
vogar --mode=activity --toolchain=jdk --multidex=false libcore/tools/docs/crypto/src/java/libcore/java/security/ListProviders.java | libcore/tools/docs/crypto/update_crypto_support.py --api_level=$1 --rewrite_file libcore/tools/docs/crypto/data/crypto_support.json
diff --git a/tools/docs/crypto/src/java/libcore/java/security/ListProviders.java b/tools/docs/crypto/src/java/libcore/java/security/ListProviders.java
index 1cd86467..ab25382 100644
--- a/tools/docs/crypto/src/java/libcore/java/security/ListProviders.java
+++ b/tools/docs/crypto/src/java/libcore/java/security/ListProviders.java
@@ -16,18 +16,22 @@
package libcore.java.security;
+import android.net.PskKeyManager;
+
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
/**
* Prints a list of all algorithms provided by security providers. Intended to be run
@@ -81,7 +85,7 @@
System.out.println((SHOW_PROVIDER ? p.getName() + ": " : "") + type + " " + algorithm);
}
- public static void main(String[] argv) {
+ public static void main(String[] argv) throws Exception {
System.out.println("BEGIN ALGORITHM LIST");
for (Provider p : Security.getProviders()) {
Set<Provider.Service> services = new TreeSet<Provider.Service>(
@@ -126,6 +130,31 @@
}
}
}
+ // SSLEngine and SSLSocket algorithms are handled outside the default provider system
+ SSLContext defaultContext = SSLContext.getDefault();
+ // PSK cipher suites are only enabled when a PskKeyManager is available, but some other
+ // suites are disabled in that case, so check for both
+ SSLContext pskContext = SSLContext.getInstance("TLS");
+ pskContext.init(
+ new KeyManager[] {new PskKeyManager(){}},
+ new TrustManager[0],
+ null);
+ for (SSLContext sslContext : new SSLContext[] {defaultContext, pskContext}) {
+ SSLEngine engine = sslContext.createSSLEngine();
+ for (String suite : engine.getSupportedCipherSuites()) {
+ print(sslContext.getProvider(), "SSLEngine.Supported", suite);
+ }
+ for (String suite : engine.getEnabledCipherSuites()) {
+ print(sslContext.getProvider(), "SSLEngine.Enabled", suite);
+ }
+ SSLSocketFactory socketFactory = sslContext.getSocketFactory();
+ for (String suite : socketFactory.getSupportedCipherSuites()) {
+ print(sslContext.getProvider(), "SSLSocket.Supported", suite);
+ }
+ for (String suite : socketFactory.getDefaultCipherSuites()) {
+ print(sslContext.getProvider(), "SSLSocket.Enabled", suite);
+ }
+ }
System.out.println("END ALGORITHM LIST");
}
}
\ No newline at end of file
diff --git a/tools/docs/crypto/update_crypto_support.py b/tools/docs/crypto/update_crypto_support.py
index 207e0f4..3138d7d 100755
--- a/tools/docs/crypto/update_crypto_support.py
+++ b/tools/docs/crypto/update_crypto_support.py
@@ -51,16 +51,24 @@
'SecureRandom',
'Signature',
'SSLContext',
+ 'SSLEngine.Enabled',
+ 'SSLEngine.Supported',
+ 'SSLSocket.Enabled',
+ 'SSLSocket.Supported',
'TrustManagerFactory',
]
+# For these categories, we really want to maintain the casing that was in the
+# original data, so avoid changing it.
+CASE_SENSITIVE_CATEGORIES = [
+ 'SSLEngine.Enabled',
+ 'SSLEngine.Supported',
+ 'SSLSocket.Enabled',
+ 'SSLSocket.Supported',
+]
-def find_by_name(seq, name):
- """Returns the first element in seq with the given name."""
- for item in seq:
- if item['name'] == name:
- return item
- return None
+
+find_by_name = crypto_docs.find_by_name
def find_by_normalized_name(seq, name):
@@ -193,7 +201,8 @@
new_algorithm = {'name': prev_alg['name']}
else:
new_algorithm = {'name': alg}
- new_algorithm['name'] = fix_name_caps_for_output(new_algorithm['name'])
+ if category not in CASE_SENSITIVE_CATEGORIES:
+ new_algorithm['name'] = fix_name_caps_for_output(new_algorithm['name'])
new_level = None
if alg in current_category and alg in prev_algorithms:
# Both old and new have it, just ensure the API level is right
diff --git a/tzdata/prototype_data/Android.mk b/tzdata/prototype_data/Android.mk
new file mode 100644
index 0000000..568bbaf
--- /dev/null
+++ b/tzdata/prototype_data/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2017 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_PACKAGE_NAME := PrototypeTimeZoneDataApp
+LOCAL_CERTIFICATE := platform
+LOCAL_PRIVILEGED_MODULE := true
+include $(BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_PACKAGE_NAME := PrototypeTimeZoneDataApp_data
+LOCAL_CERTIFICATE := platform
+# Needed to ensure the .apk can be installed. Without it the .apk is missing a .dex.
+LOCAL_DEX_PREOPT := false
+include $(BUILD_PACKAGE)
diff --git a/tzdata/prototype_data/AndroidManifest.xml b/tzdata/prototype_data/AndroidManifest.xml
new file mode 100644
index 0000000..ae0fe6b
--- /dev/null
+++ b/tzdata/prototype_data/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="libcore.tzdata.prototype_data"
+ android:versionCode="1">
+
+ <application
+ android:allowBackup="false"
+ android:label="@string/app_name">
+
+ <provider
+ android:name="libcore.tzdata.prototypedata.TimeZoneRulesDataProvider"
+ android:authorities="com.android.timezone"
+ android:grantUriPermissions="true"
+ android:readPermission="android.permission.UPDATE_TIME_ZONE_RULES"
+ android:exported="true">
+ <meta-data android:name="android.timezoneprovider.OPERATION"
+ android:value="INSTALL"/>
+ <meta-data android:name="android.timezoneprovider.DATA_ASSET"
+ android:value="test_2030a.zip"/>
+ <meta-data android:name="android.timezoneprovider.DISTRO_MAJOR_VERSION"
+ android:value="1"/>
+ <meta-data android:name="android.timezoneprovider.DISTRO_MINOR_VERSION"
+ android:value="1"/>
+ <meta-data android:name="android.timezoneprovider.RULES_VERSION"
+ android:value="2030a"/>
+ <meta-data android:name="android.timezoneprovider.REVISION"
+ android:value="1"/>
+ </provider>
+ </application>
+</manifest>
diff --git a/tzdata/prototype_data/assets/test_2030a.zip b/tzdata/prototype_data/assets/test_2030a.zip
new file mode 100644
index 0000000..ae274cd
--- /dev/null
+++ b/tzdata/prototype_data/assets/test_2030a.zip
Binary files differ
diff --git a/tzdata/prototype_data/res/values/strings.xml b/tzdata/prototype_data/res/values/strings.xml
new file mode 100644
index 0000000..e25341c
--- /dev/null
+++ b/tzdata/prototype_data/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 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.
+ -->
+
+<resources>
+ <string name="app_name">DataPrototypeApp</string>
+</resources>
diff --git a/tzdata/prototype_data/src/libcore/tzdata/prototypedata/TimeZoneRulesDataProvider.java b/tzdata/prototype_data/src/libcore/tzdata/prototypedata/TimeZoneRulesDataProvider.java
new file mode 100644
index 0000000..c7be72a
--- /dev/null
+++ b/tzdata/prototype_data/src/libcore/tzdata/prototypedata/TimeZoneRulesDataProvider.java
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2017 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.tzdata.prototypedata;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.database.AbstractCursor;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.ParcelFileDescriptor;
+import android.provider.TimeZoneRulesDataContract;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import libcore.io.Streams;
+
+import static android.content.res.AssetManager.ACCESS_STREAMING;
+import static android.provider.TimeZoneRulesDataContract.COLUMN_DISTRO_MAJOR_VERSION;
+import static android.provider.TimeZoneRulesDataContract.COLUMN_DISTRO_MINOR_VERSION;
+import static android.provider.TimeZoneRulesDataContract.COLUMN_OPERATION;
+import static android.provider.TimeZoneRulesDataContract.COLUMN_REVISION;
+import static android.provider.TimeZoneRulesDataContract.COLUMN_RULES_VERSION;
+import static android.provider.TimeZoneRulesDataContract.OPERATION_INSTALL;
+
+/**
+ * A basic implementation of a time zone data provider that can be used by OEMs to implement
+ * an APK asset-based solution for time zone updates.
+ */
+public final class TimeZoneRulesDataProvider extends ContentProvider {
+
+ static final String TAG = "TimeZoneRulesDataProvider";
+
+ private static final String METADATA_KEY_OPERATION = "android.timezoneprovider.OPERATION";
+ private static final String METADATA_KEY_ASSET = "android.timezoneprovider.DATA_ASSET";
+ private static final String METADATA_KEY_DISTRO_MAJOR_VERSION
+ = "android.timezoneprovider.DISTRO_MAJOR_VERSION";
+ private static final String METADATA_KEY_DISTRO_MINOR_VERSION
+ = "android.timezoneprovider.DISTRO_MINOR_VERSION";
+ private static final String METADATA_KEY_RULES_VERSION
+ = "android.timezoneprovider.RULES_VERSION";
+ private static final String METADATA_KEY_REVISION
+ = "android.timezoneprovider.REVISION";
+
+ private static final Set<String> KNOWN_COLUMN_NAMES;
+ private static final Map<String, Class<?>> KNOWN_COLUMN_TYPES;
+ static {
+ Set<String> columnNames = new HashSet<>();
+ columnNames.add(COLUMN_OPERATION);
+ columnNames.add(COLUMN_DISTRO_MAJOR_VERSION);
+ columnNames.add(COLUMN_DISTRO_MINOR_VERSION);
+ columnNames.add(COLUMN_RULES_VERSION);
+ columnNames.add(COLUMN_REVISION);
+ KNOWN_COLUMN_NAMES = Collections.unmodifiableSet(columnNames);
+
+ Map<String, Class<?>> columnTypes = new HashMap<>();
+ columnTypes.put(COLUMN_OPERATION, String.class);
+ columnTypes.put(COLUMN_DISTRO_MAJOR_VERSION, Integer.class);
+ columnTypes.put(COLUMN_DISTRO_MINOR_VERSION, Integer.class);
+ columnTypes.put(COLUMN_RULES_VERSION, String.class);
+ columnTypes.put(COLUMN_REVISION, Integer.class);
+ KNOWN_COLUMN_TYPES = Collections.unmodifiableMap(columnTypes);
+ }
+
+ private Map<String, Object> mColumnData = new HashMap<>();
+ private String mAssetName;
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public void attachInfo(Context context, ProviderInfo info) {
+ super.attachInfo(context, info);
+
+ // Sanity check our security
+ if (!TimeZoneRulesDataContract.AUTHORITY.equals(info.authority)) {
+ // The authority looked for by the time zone updater is fixed.
+ throw new SecurityException(
+ "android:authorities must be \"" + TimeZoneRulesDataContract.AUTHORITY + "\"");
+ }
+ if (!info.grantUriPermissions) {
+ throw new SecurityException("Provider must grant uri permissions");
+ }
+ if (!info.exported) {
+ // The content provider is accessed directly so must be exported.
+ throw new SecurityException("android:exported must be \"true\"");
+ }
+ if (info.pathPermissions != null || info.writePermission != null) {
+ // Use readPermission only to implement permissions.
+ throw new SecurityException("Use android:readPermission only");
+ }
+ if (!android.Manifest.permission.UPDATE_TIME_ZONE_RULES.equals(info.readPermission)) {
+ // Writing is not supported.
+ throw new SecurityException("android:readPermission must be set to \""
+ + android.Manifest.permission.UPDATE_TIME_ZONE_RULES
+ + "\" is: " + info.readPermission);
+ }
+
+ // info.metadata is not filled in by default. Must ask for it again.
+ final ProviderInfo infoWithMetadata = context.getPackageManager()
+ .resolveContentProvider(info.authority, PackageManager.GET_META_DATA);
+ Bundle metaData = infoWithMetadata.metaData;
+ if (metaData == null) {
+ throw new SecurityException("meta-data must be set");
+ }
+
+ String operation;
+ try {
+ operation = getMandatoryMetaDataString(metaData, METADATA_KEY_OPERATION);
+ mColumnData.put(COLUMN_OPERATION, operation);
+ } catch (IllegalArgumentException e) {
+ throw new SecurityException(METADATA_KEY_OPERATION + " meta-data not set.");
+ }
+ if (OPERATION_INSTALL.equals(operation)) {
+ mColumnData.put(
+ COLUMN_DISTRO_MAJOR_VERSION,
+ getMandatoryMetaDataInt(metaData, METADATA_KEY_DISTRO_MAJOR_VERSION));
+ mColumnData.put(
+ COLUMN_DISTRO_MINOR_VERSION,
+ getMandatoryMetaDataInt(metaData, METADATA_KEY_DISTRO_MINOR_VERSION));
+ mColumnData.put(
+ COLUMN_RULES_VERSION,
+ getMandatoryMetaDataString(metaData, METADATA_KEY_RULES_VERSION));
+ mColumnData.put(
+ COLUMN_REVISION,
+ getMandatoryMetaDataInt(metaData, METADATA_KEY_REVISION));
+
+ // Make sure the asset containing the data to install exists.
+ String assetName = getMandatoryMetaDataString(metaData, METADATA_KEY_ASSET);
+ try {
+ InputStream is = context.getAssets().open(assetName);
+ // An exception is thrown if the asset does not exist. list(assetName) appears not
+ // to work with file paths.
+ is.close();
+ } catch (IOException e) {
+ throw new SecurityException("Unable to open asset:" + assetName);
+ }
+ mAssetName = assetName;
+ }
+ }
+
+ @Override
+ public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection,
+ @Nullable String[] selectionArgs, @Nullable String sortOrder) {
+ if (!TimeZoneRulesDataContract.OPERATION_URI.equals(uri)) {
+ return null;
+ }
+ final List<String> projectionList = Arrays.asList(projection);
+ if (projection != null && !KNOWN_COLUMN_NAMES.containsAll(projectionList)) {
+ throw new UnsupportedOperationException(
+ "Only " + KNOWN_COLUMN_NAMES + " columns supported.");
+ }
+
+ return new AbstractCursor() {
+ @Override
+ public int getCount() {
+ return 1;
+ }
+
+ @Override
+ public String[] getColumnNames() {
+ return projectionList.toArray(new String[0]);
+ }
+
+ @Override
+ public int getType(int column) {
+ String columnName = projectionList.get(column);
+ Class<?> columnJavaType = KNOWN_COLUMN_TYPES.get(columnName);
+ if (columnJavaType == String.class) {
+ return Cursor.FIELD_TYPE_STRING;
+ } else if (columnJavaType == Integer.class) {
+ return Cursor.FIELD_TYPE_INTEGER;
+ } else {
+ throw new UnsupportedOperationException(
+ "Unsupported type: " + columnJavaType + " for " + columnName);
+ }
+ }
+
+ @Override
+ public String getString(int column) {
+ checkPosition();
+ String columnName = projectionList.get(column);
+ if (KNOWN_COLUMN_TYPES.get(columnName) != String.class) {
+ throw new UnsupportedOperationException();
+ }
+ return (String) mColumnData.get(columnName);
+ }
+
+ @Override
+ public short getShort(int column) {
+ checkPosition();
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getInt(int column) {
+ checkPosition();
+ String columnName = projectionList.get(column);
+ if (KNOWN_COLUMN_TYPES.get(columnName) != Integer.class) {
+ throw new UnsupportedOperationException();
+ }
+ return (Integer) mColumnData.get(columnName);
+ }
+
+ @Override
+ public long getLong(int column) {
+ return getInt(column);
+ }
+
+ @Override
+ public float getFloat(int column) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public double getDouble(int column) {
+ checkPosition();
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isNull(int column) {
+ checkPosition();
+ return column != 0;
+ }
+ };
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode)
+ throws FileNotFoundException {
+ if (!TimeZoneRulesDataContract.DATA_URI.equals(uri)) {
+ return null;
+ }
+ if (mAssetName == null) {
+ throw new FileNotFoundException();
+ }
+ if (!mode.equals("r")) {
+ throw new SecurityException("Only read-only access supported.");
+ }
+
+ // Extract the asset to a local dir. We do it every time: we don't make assumptions that the
+ // current copy (if any) is valid.
+ File localFile = extractAssetToLocalFile();
+
+ // Create a read-only ParcelFileDescriptor that can be passed to the caller process.
+ try {
+ return ParcelFileDescriptor.open(localFile, ParcelFileDescriptor.MODE_READ_ONLY,
+ new Handler(Looper.getMainLooper()),
+ e -> {
+ if (e != null) {
+ Log.w(TAG, "Error in OnCloseListener for " + localFile, e);
+ }
+ localFile.delete();
+ });
+ } catch (IOException e) {
+ throw new RuntimeException("Unable to open asset file", e);
+ }
+ }
+
+ private File extractAssetToLocalFile() throws FileNotFoundException {
+ File extractedFile = new File(getContext().getFilesDir(), "timezone_data.zip");
+ InputStream is;
+ try {
+ is = getContext().getAssets().open(mAssetName, ACCESS_STREAMING);
+ } catch (FileNotFoundException e) {
+ throw e;
+ } catch (IOException e) {
+ FileNotFoundException fnfe = new FileNotFoundException("Problem reading asset");
+ fnfe.initCause(e);
+ throw fnfe;
+ }
+
+ try (InputStream fis = is;
+ FileOutputStream fos = new FileOutputStream(extractedFile, false /* append */)) {
+ Streams.copy(fis, fos);
+ } catch (IOException e) {
+ throw new RuntimeException("Unable to create asset storage file: " + extractedFile, e);
+ }
+ return extractedFile;
+ }
+
+ @Override
+ public String getType(@NonNull Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int delete(@NonNull Uri uri, @Nullable String selection,
+ @Nullable String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection,
+ @Nullable String[] selectionArgs) {
+ throw new UnsupportedOperationException();
+ }
+
+ private static String getMandatoryMetaDataString(Bundle metaData, String key) {
+ if (!metaData.containsKey(key)) {
+ throw new SecurityException("No metadata with key " + key + " found.");
+ }
+ return metaData.getString(key);
+ }
+
+ private static int getMandatoryMetaDataInt(Bundle metaData, String key) {
+ if (!metaData.containsKey(key)) {
+ throw new SecurityException("No metadata with key " + key + " found.");
+ }
+ return metaData.getInt(key, -1);
+ }
+}
diff --git a/tzdata/prototype_updater/Android.mk b/tzdata/prototype_updater/Android.mk
new file mode 100644
index 0000000..0ddaa45
--- /dev/null
+++ b/tzdata/prototype_updater/Android.mk
@@ -0,0 +1,24 @@
+# Copyright (C) 2017 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_PACKAGE_NAME := PrototypeTimeZoneUpdaterApp
+LOCAL_CERTIFICATE := platform
+LOCAL_PRIVILEGED_MODULE := true
+include $(BUILD_PACKAGE)
diff --git a/tzdata/prototype_updater/AndroidManifest.xml b/tzdata/prototype_updater/AndroidManifest.xml
new file mode 100644
index 0000000..9b73b0b
--- /dev/null
+++ b/tzdata/prototype_updater/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="libcore.tzdata.prototype_updater"
+ android:versionCode="1">
+
+ <uses-permission android:name="android.permission.UPDATE_TIME_ZONE_RULES" />
+
+ <application
+ android:allowBackup="false"
+ android:label="@string/app_name">
+
+ <receiver android:name=".RulesCheckReceiver"
+ android:permission="android.permission.TRIGGER_TIME_ZONE_RULES_CHECK"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK" />
+ </intent-filter>
+ </receiver>
+
+ </application>
+
+</manifest>
diff --git a/tzdata/prototype_updater/res/values/strings.xml b/tzdata/prototype_updater/res/values/strings.xml
new file mode 100644
index 0000000..204ae27
--- /dev/null
+++ b/tzdata/prototype_updater/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 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.
+ -->
+
+<resources>
+ <string name="app_name">PrototypeUpdaterApp</string>
+</resources>
diff --git a/tzdata/prototype_updater/src/libcore/tzdata/prototype_updater/RulesCheckReceiver.java b/tzdata/prototype_updater/src/libcore/tzdata/prototype_updater/RulesCheckReceiver.java
new file mode 100644
index 0000000..9f3a3b8
--- /dev/null
+++ b/tzdata/prototype_updater/src/libcore/tzdata/prototype_updater/RulesCheckReceiver.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2017 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.tzdata.prototype_updater;
+
+import android.app.timezone.Callback;
+import android.app.timezone.DistroFormatVersion;
+import android.app.timezone.DistroRulesVersion;
+import android.app.timezone.RulesManager;
+import android.app.timezone.RulesState;
+import android.app.timezone.RulesUpdaterContract;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.os.ParcelFileDescriptor;
+import android.provider.TimeZoneRulesDataContract;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import libcore.io.Streams;
+
+// TODO(nfuller): Prevent multiple broadcasts being handled at once?
+// TODO(nfuller): Improve logging
+// TODO(nfuller): Make the rules check async?
+// TODO(nfuller): Need async generally for SystemService calls from BroadcastReceiver?
+public class RulesCheckReceiver extends BroadcastReceiver {
+ final static String TAG = "RulesCheckReceiver";
+
+ private RulesManager mRulesManager;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!RulesUpdaterContract.ACTION_TRIGGER_RULES_UPDATE_CHECK.equals(intent.getAction())) {
+ // Unknown. Do nothing.
+ Log.w(TAG, "Unrecognized intent action received: " + intent
+ + ", action=" + intent.getAction());
+ return;
+ }
+
+ mRulesManager = (RulesManager) context.getSystemService("timezone");
+
+ byte[] token = intent.getByteArrayExtra(RulesUpdaterContract.EXTRA_CHECK_TOKEN);
+
+ // Note: We rely on the system server to check that the configured data application is the
+ // one that exposes the content provider with the well-known authority, and is a privileged
+ // application as required. It is *not* checked here and it is assumed the updater can trust
+ // the data application.
+
+ // Obtain the information about what the data app is telling us to do.
+ String operation = getOperation(context);
+ if (operation == null) {
+ // TODO Log
+ boolean success = true; // No point in retrying.
+ handleCheckComplete(token, success);
+ return;
+ }
+ switch (operation) {
+ case TimeZoneRulesDataContract.OPERATION_NO_OP:
+ // TODO Log
+ // No-op. Just acknowledge the check.
+ handleCheckComplete(token, true /* success */);
+ break;
+ case TimeZoneRulesDataContract.OPERATION_UNINSTALL:
+ // TODO Log
+ handleUninstall(token);
+ break;
+ case TimeZoneRulesDataContract.OPERATION_INSTALL:
+ // TODO Log
+ DistroVersionInfo distroVersionInfo = getDistroVersionInfo(context);
+ handleCopyAndInstall(context, token, distroVersionInfo);
+ break;
+ default:
+ // TODO Log
+ final boolean success = true; // No point in retrying.
+ handleCheckComplete(token, success);
+ }
+ }
+
+ private String getOperation(Context context) {
+ Cursor cursor = context.getContentResolver()
+ .query(TimeZoneRulesDataContract.OPERATION_URI,
+ new String[] { TimeZoneRulesDataContract.COLUMN_OPERATION },
+ null /* selection */, null /* selectionArgs */, null /* sortOrder */);
+ if (cursor == null) {
+ Log.e(TAG, "getOperation: query returned null");
+ return null;
+ }
+ if (!cursor.moveToFirst()) {
+ Log.e(TAG, "getOperation: query returned empty results");
+ return null;
+ }
+
+ try {
+ return cursor.getString(0);
+ } catch (Exception e) {
+ Log.e(TAG, "getOperation: getString() threw an exception", e);
+ return null;
+ }
+ }
+
+ private DistroVersionInfo getDistroVersionInfo(Context context) {
+ Cursor cursor = context.getContentResolver()
+ .query(TimeZoneRulesDataContract.OPERATION_URI,
+ new String[] {
+ TimeZoneRulesDataContract.COLUMN_DISTRO_MAJOR_VERSION,
+ TimeZoneRulesDataContract.COLUMN_DISTRO_MINOR_VERSION,
+ TimeZoneRulesDataContract.COLUMN_RULES_VERSION,
+ TimeZoneRulesDataContract.COLUMN_REVISION},
+ null /* selection */, null /* selectionArgs */, null /* sortOrder */);
+ if (cursor == null) {
+ Log.e(TAG, "getDistroVersionInfo: query returned null");
+ return null;
+ }
+ if (!cursor.moveToFirst()) {
+ Log.e(TAG, "getDistroVersionInfo: query returned empty results");
+ return null;
+ }
+
+ try {
+ return new DistroVersionInfo(
+ cursor.getInt(0),
+ cursor.getInt(1),
+ cursor.getString(2),
+ cursor.getInt(3));
+ } catch (Exception e) {
+ Log.e(TAG, "getDistroVersionInfo: getInt()/getString() threw an exception", e);
+ return null;
+ }
+ }
+
+ private void handleCopyAndInstall(Context context, byte[] checkToken,
+ DistroVersionInfo distroVersionInfo) {
+
+ // Decide whether to proceed with the install.
+ RulesState rulesState = mRulesManager.getRulesState();
+ if (!(rulesState.isDistroFormatVersionSupported(distroVersionInfo.mDistroFormatVersion)
+ && rulesState.isSystemVersionOlderThan(distroVersionInfo.mDistroRulesVersion))) {
+ // Nothing to do.
+ handleCheckComplete(checkToken, true /* success */);
+ return;
+ }
+
+ // Copy the data locally before passing it on....security and whatnot.
+ // TODO(nfuller): Need to do the copy here?
+ File file = copyDataToLocalFile(context);
+ if (file == null) {
+ // It's possible this may get better if the problem is related to storage space.
+ boolean success = false;
+ handleCheckComplete(checkToken, success);
+ return;
+ }
+ handleInstall(checkToken, file);
+ }
+
+ private static File copyDataToLocalFile(Context context) {
+ File extractedFile = new File(context.getFilesDir(), "temp.zip");
+ ParcelFileDescriptor fileDescriptor;
+ try {
+ fileDescriptor = context.getContentResolver().openFileDescriptor(
+ TimeZoneRulesDataContract.DATA_URI, "r");
+ if (fileDescriptor == null) {
+ throw new FileNotFoundException("ContentProvider returned null");
+ }
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "copyDataToLocalFile: Unable to open file descriptor"
+ + TimeZoneRulesDataContract.DATA_URI, e);
+ return null;
+ }
+
+ try (ParcelFileDescriptor pfd = fileDescriptor;
+ InputStream fis = new FileInputStream(pfd.getFileDescriptor());
+ FileOutputStream fos = new FileOutputStream(extractedFile, false /* append */)) {
+ Streams.copy(fis, fos);
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to create asset storage file: " + extractedFile, e);
+ return null;
+ }
+ return extractedFile;
+ }
+
+ private void handleInstall(final byte[] checkToken, final File contentFile) {
+ // Convert the distroFile to a ParcelFileDescriptor.
+ final ParcelFileDescriptor distroFileDescriptor;
+ try {
+ distroFileDescriptor =
+ ParcelFileDescriptor.open(contentFile, ParcelFileDescriptor.MODE_READ_ONLY);
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "Unable to create ParcelFileDescriptor from " + contentFile);
+ handleCheckComplete(checkToken, false /* success */);
+ return;
+ }
+
+ Callback callback = new Callback() {
+ @Override
+ public void onFinished(int status) {
+ Log.i(TAG, "onFinished: Finished install: " + status);
+
+ // TODO(nfuller): Can this be closed sooner?
+ try {
+ distroFileDescriptor.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to close ParcelFileDescriptor for " + contentFile, e);
+ } finally {
+ // Delete the file we no longer need.
+ contentFile.delete();
+ }
+ }
+ };
+
+ try {
+ int requestStatus =
+ mRulesManager.requestInstall(distroFileDescriptor, checkToken, callback);
+ Log.i(TAG, "handleInstall: Request sent:" + requestStatus);
+ } catch (Exception e) {
+ Log.e(TAG, "handleInstall: Error", e);
+ }
+ }
+
+ private void handleUninstall(byte[] checkToken) {
+ Callback callback = new Callback() {
+ @Override
+ public void onFinished(int status) {
+ Log.i(TAG, "onFinished: Finished uninstall: " + status);
+ }
+ };
+
+ try {
+ int requestStatus =
+ mRulesManager.requestUninstall(checkToken, callback);
+ Log.i(TAG, "handleUninstall: Request sent" + requestStatus);
+ } catch (Exception e) {
+ Log.e(TAG, "handleUninstall: Error", e);
+ }
+ }
+
+ private void handleCheckComplete(final byte[] token, final boolean success) {
+ try {
+ mRulesManager.requestNothing(token, success);
+ Log.i(TAG, "doInBackground: Called checkComplete: token="
+ + Arrays.toString(token) + ", success=" + success);
+ } catch (Exception e) {
+ Log.e(TAG, "doInBackground: Error calling checkComplete()", e);
+ }
+ }
+
+ private static class DistroVersionInfo {
+
+ final DistroFormatVersion mDistroFormatVersion;
+ final DistroRulesVersion mDistroRulesVersion;
+
+ DistroVersionInfo(int distroMajorVersion, int distroMinorVersion,
+ String rulesVersion, int revision) {
+ mDistroFormatVersion = new DistroFormatVersion(distroMajorVersion, distroMinorVersion);
+ mDistroRulesVersion = new DistroRulesVersion(rulesVersion, revision);
+ }
+ }
+}
diff --git a/tzdata/update_test_app2/Android.mk b/tzdata/update_test_app2/Android.mk
new file mode 100644
index 0000000..c1ae636
--- /dev/null
+++ b/tzdata/update_test_app2/Android.mk
@@ -0,0 +1,25 @@
+# Copyright (C) 2015 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_PACKAGE_NAME := UpdateTestApp2
+LOCAL_CERTIFICATE := platform
+include $(BUILD_PACKAGE)
diff --git a/tzdata/update_test_app2/AndroidManifest.xml b/tzdata/update_test_app2/AndroidManifest.xml
new file mode 100644
index 0000000..fd42bb5
--- /dev/null
+++ b/tzdata/update_test_app2/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="libcore.tzdata.update_test_app2.installupdatetestapp" >
+
+ <uses-permission android:name="android.permission.UPDATE_TIME_ZONE_RULES" />
+
+ <application
+ android:allowBackup="false"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.Holo.Light">
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/tzdata/update_test_app2/res/drawable/ic_launcher.png b/tzdata/update_test_app2/res/drawable/ic_launcher.png
new file mode 100644
index 0000000..96a442e
--- /dev/null
+++ b/tzdata/update_test_app2/res/drawable/ic_launcher.png
Binary files differ
diff --git a/tzdata/update_test_app2/res/layout/activity_main.xml b/tzdata/update_test_app2/res/layout/activity_main.xml
new file mode 100644
index 0000000..16e4b11
--- /dev/null
+++ b/tzdata/update_test_app2/res/layout/activity_main.xml
@@ -0,0 +1,98 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ tools:context=".MainActivity">
+
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/content_path"
+ android:id="@+id/content_path_label" />
+
+ <EditText
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/default_content_path"
+ android:id="@+id/content_path" />
+
+ </LinearLayout>
+
+ <Button
+ android:id="@+id/trigger_install_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:text="@string/trigger_install" />
+
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="2dip"
+ android:background="#FF00FF00" />
+
+ <Button
+ android:id="@+id/trigger_uninstall_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:text="@string/trigger_uninstall" />
+
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="2dip"
+ android:background="#FF00FF00" />
+
+ <CheckBox android:id="@+id/success_checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/success" />
+
+ <Button
+ android:id="@+id/trigger_nothing"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:text="@string/trigger_nothing" />
+
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="2dip"
+ android:background="#FF00FF00" />
+
+ <Button
+ android:id="@+id/get_rules_state_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:text="@string/get_rules_state" />
+
+ <View
+ android:layout_width="fill_parent"
+ android:layout_height="2dip"
+ android:background="#FF00FF00" />
+
+ <ScrollView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:scrollbars="vertical"
+ android:fillViewport="true">
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/log"
+ android:singleLine="false" />
+
+ </ScrollView>
+
+</LinearLayout>
diff --git a/tzdata/update_test_app2/res/values/strings.xml b/tzdata/update_test_app2/res/values/strings.xml
new file mode 100644
index 0000000..9bb5f57
--- /dev/null
+++ b/tzdata/update_test_app2/res/values/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">InstallUpdateTestApp2</string>
+ <string name="content_path">Content Path</string>
+ <string name="default_content_path">/data/local/tmp/out.zip</string>
+ <string name="trigger_install">Request Install</string>
+ <string name="trigger_uninstall">Request Uninstall</string>
+ <string name="trigger_nothing">Request Nothing</string>
+ <string name="success">Success</string>
+ <string name="get_rules_state">Get rules state</string>
+</resources>
diff --git a/tzdata/update_test_app2/src/libcore/tzdata/update_test_app2/installupdatetestapp/MainActivity.java b/tzdata/update_test_app2/src/libcore/tzdata/update_test_app2/installupdatetestapp/MainActivity.java
new file mode 100644
index 0000000..caa52c4
--- /dev/null
+++ b/tzdata/update_test_app2/src/libcore/tzdata/update_test_app2/installupdatetestapp/MainActivity.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2015 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.tzdata.update_test_app2.installupdatetestapp;
+
+import android.app.Activity;
+import android.app.timezone.Callback;
+import android.app.timezone.RulesManager;
+import android.app.timezone.RulesState;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Date;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class MainActivity extends Activity implements View.OnClickListener {
+
+ private EditText contentPathEditText;
+ private TextView logView;
+
+ private RulesManager rulesManager;
+ private Callback callback;
+ private ExecutorService executor;
+ private CheckBox successCheckbox;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ Button triggerInstallButton = (Button) findViewById(R.id.trigger_install_button);
+ triggerInstallButton.setOnClickListener(this);
+ Button triggerUninstallButton = (Button) findViewById(R.id.trigger_uninstall_button);
+ triggerUninstallButton.setOnClickListener(this);
+ Button triggerCheckCompleteButton = (Button) findViewById(R.id.trigger_nothing);
+ triggerCheckCompleteButton.setOnClickListener(this);
+ successCheckbox = (CheckBox) findViewById(R.id.success_checkbox);
+
+ Button getRulesStateButton = (Button) findViewById(R.id.get_rules_state_button);
+ getRulesStateButton.setOnClickListener(this);
+
+ contentPathEditText = (EditText) findViewById(R.id.content_path);
+ logView = (TextView) findViewById(R.id.log);
+ executor = Executors.newFixedThreadPool(1);
+ rulesManager = (RulesManager) getSystemService("timezone");
+ callback = new Callback() {
+ @Override
+ public void onFinished(int status) {
+ logString("Operation finished. Status=" + status);
+ }
+ };
+ }
+
+ private abstract class MyAsyncTask extends AsyncTask<Void, String, Void> {
+ @Override
+ protected void onProgressUpdate(String... values) {
+ for (String message : values) {
+ addToLog(message, null);
+ }
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ MyAsyncTask task;
+ if (v.getId() == R.id.trigger_install_button) {
+ final String contentPath = contentPathEditText.getText().toString();
+ final File contentFile = new File(contentPath);
+
+ // Convert the contentFile to a ParcelFileDescriptor.
+ final ParcelFileDescriptor distroFileDescriptor =
+ createParcelFileDescriptor(contentFile);
+ if (distroFileDescriptor == null) {
+ return;
+ }
+
+ Callback callback = new Callback() {
+ @Override
+ public void onFinished(int status) {
+ logString("onFinished: Finished install: " + status);
+
+ // TODO(nfuller): Can this be closed sooner?
+ try {
+ distroFileDescriptor.close();
+ } catch (IOException e) {
+ logString("Unable to close ParcelFileDescriptor for " + contentFile + ": "
+ + exceptionToString(e));
+ }
+ }
+ };
+
+ task = new MyAsyncTask() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ if (!contentFile.exists()) {
+ publishProgress("Error: " + contentFile + " does not exist.");
+ return null;
+ }
+ try {
+ int requestStatus = rulesManager.requestInstall(
+ distroFileDescriptor, null /* checkToken */, callback);
+ publishProgress("Request sent:" + requestStatus);
+ } catch (Exception e) {
+ publishProgress("Error", exceptionToString(e));
+ }
+ return null;
+ }
+ };
+ } else if (v.getId() == R.id.trigger_uninstall_button) {
+ task = new MyAsyncTask() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ try {
+ int requestStatus = rulesManager.requestUninstall(
+ null /* checkToken */, callback);
+ publishProgress("Request sent:" + requestStatus);
+ } catch (Exception e) {
+ publishProgress("Error", exceptionToString(e));
+ }
+ return null;
+ }
+ };
+ } else if (v.getId() == R.id.trigger_nothing) {
+ final boolean success = successCheckbox.isChecked();
+ task = new MyAsyncTask() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ try {
+ rulesManager.requestNothing(null /* checkToken */, success);
+ publishProgress("Request sent");
+ } catch (Exception e) {
+ publishProgress("Error", exceptionToString(e));
+ }
+ return null;
+ }
+ };
+ } else if (v.getId() == R.id.get_rules_state_button) {
+ task = new MyAsyncTask() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ try {
+ RulesState rulesState = rulesManager.getRulesState();
+ publishProgress("Rules state: " + rulesState);
+ } catch (Exception e) {
+ publishProgress("Error", exceptionToString(e));
+ }
+ return null;
+ }
+ };
+ } else {
+ addToLog("Unknown button", null);
+ return;
+ }
+ task.executeOnExecutor(executor);
+ }
+
+ private ParcelFileDescriptor createParcelFileDescriptor(File contentFile) {
+ try {
+ return ParcelFileDescriptor.open(contentFile, ParcelFileDescriptor.MODE_READ_ONLY);
+ } catch (FileNotFoundException e) {
+ logString("Unable to create ParcelFileDescriptor from " + contentFile + ": "
+ + exceptionToString(e));
+ return null;
+ }
+ }
+
+ private void addToLog(String message, Exception e) {
+ logString(message);
+ if (e != null) {
+ String text = exceptionToString(e);
+ logString(text);
+ }
+ }
+
+ private void logString(String value) {
+ logView.append(new Date() + " " + value + "\n");
+ int scrollAmount =
+ logView.getLayout().getLineTop(logView.getLineCount()) - logView.getHeight();
+ logView.scrollTo(0, scrollAmount);
+ }
+
+ private static String exceptionToString(Exception e) {
+ StringWriter writer = new StringWriter();
+ e.printStackTrace(new PrintWriter(writer));
+ return writer.getBuffer().toString();
+ }
+}