RI 6 support for javax.net.ssl

Summary:
- RI 6 support for javax.net.ssl
- SSLEngine fixes based on new SSLEngineTest
- fix Cipher.checkMode bug recently introduced in dalvik-dev

Details:

Fix Cipher.checkMode that was preventing most javax.net.ssl tests from working

	luni/src/main/java/javax/crypto/Cipher.java

RI 6 has introduced the concept of a "Default" SSLContext. This is
accessed via SSLContext.getDefault() and also
SSLContext.getInstance("Default"). Harmony had its own
DefaultSSLContext but it was not created via an SSLContextSpi. It also
was a single shared instance whereas the new RI6 Default SSLContext
shares internal SSLSessionContext instances between different Default
SSLContexts.

    Refactored the old code into an SSLContextImpl subclass that
    allows it to be created via SSLContext.getInstance. SSLContextImpl
    ensures that we only ever create one set of SSLSessionContext
    instances for the Default context.

	luni/src/main/java/javax/net/ssl/DefaultSSLContext.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java

    Added SSLContext.getDefault and SSLContext.setDefault

	luni/src/main/java/javax/net/ssl/SSLContext.java

    Replace dependencies of old DefaultSSLContext with use of SSLContext.getDefault

	luni/src/main/java/javax/net/ssl/SSLServerSocketFactory.java
	luni/src/main/java/javax/net/ssl/SSLSocketFactory.java

    Register "SSLContext.Default" as DefaultSSLContextImpl class for SSLContext.getInstance()

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java

    Added constant for new "Default" standard name and added it to
    SSL_CONTEXT_PROTOCOLS. New tests based on SSL_CONTEXT_PROTOCOLS
    made it clear that neither Android or RI support SSLv2 so removed
    it from SSL_CONTEXT_PROTOCOLS and SSL_SOCKET_PROTOCOLS. Added
    constant for TLS as well which was previously scattered all over
    tests. Remove SSLv2Hello from SSL_SOCKET_PROTOCOLS for Android
    since with OpenSSL disablign SSLv2 means you can not use
    SSLv2Hello either.

	support/src/test/java/javax/net/ssl/StandardNames.java

    Added tests for SSLContext.getDefault and
    SSLContext.setDefault. Changed existing tests to work on all
    protocols including new "Default".

	luni/src/test/java/javax/net/ssl/SSLContextTest.java

RI 6 has introduced the notion of SSLParameters which encapsulate SSL
the handshake parameters of desired cipher suites, protocols, and
client authentication requirements.

    The main new class SSLParameters is basically just a bag of fields
    with accessors and a couple simple constructors. The only things
    of note are that it clones all String arrays on input and output
    and the setters for the two boolean fields ensure that only one is
    true at a time.

	luni/src/main/java/javax/net/ssl/SSLParameters.java

    Added SSLContext.getDefaultSSLParameters and
    SSLContext.getSupportedSSLParameters which simply delegate to the
    SSLContextSpi.

	luni/src/main/java/javax/net/ssl/SSLContext.java

    Added abstract SSLContextSpi.engineGetDefaultSSLParameters and
    SSLContext.engineGetSupportedSSLParameters.

	luni/src/main/java/javax/net/ssl/SSLContextSpi.java

    Added engineGetDefaultSSLParameters and
    engineGetSupportedSSLParameters implementation. The RI documents
    in SSLContextSpi that these are implemented by default by creating
    a socket via the SSLContext's SocketFactory and asking for the
    enabled/supported cipher suites and protocols respectively, so
    that is what is done. The doc mentions throwing
    UnsupportedOperationException if there is a problem, so we do that
    as well.

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java

    Added {SSLEngine,SSLSocket}.{getSSLParameters,setSSLParameters}
    which are analogous.

	luni/src/main/java/javax/net/ssl/SSLEngine.java
	luni/src/main/java/javax/net/ssl/SSLSocket.java

   Added SSLParametersTest

	luni/src/test/java/javax/net/ssl/SSLParametersTest.java
	luni/src/test/java/javax/net/ssl/AllTests.java

   Added SSLContext.get{Default,Supported}SSLParameters tests

	luni/src/test/java/javax/net/ssl/SSLContextTest.java

   Added SSLSocket.{getSSLParameters,setSSLParameters} tests and added
   some extra asserts to test_SSLSocketPair_create based on experience
   with test_SSLEnginePair_create.

	luni/src/test/java/javax/net/ssl/SSLSocketTest.java

   Dummy implementation of new SSLContextSpi for test classes.

	support/src/test/java/org/apache/harmony/security/tests/support/MySSLContextSpi.java
	support/src/test/java/org/apache/harmony/xnet/tests/support/MySSLContextSpi.java

Other minor RI 6 API changes:

    RI 6 removed Serializable from HandshakeCompletedEvent and SSLSessionBindingEvent

	luni/src/main/java/javax/net/ssl/HandshakeCompletedEvent.java
	luni/src/main/java/javax/net/ssl/SSLSessionBindingEvent.java

    RI 6 added generic types to the KeyStoreBuilderParameters List
    constructor and accessor as well as to
    SSLSessionContext.getIds. Fixed tests to compile with generic types.

	luni/src/main/java/javax/net/ssl/KeyStoreBuilderParameters.java
	luni/src/main/java/javax/net/ssl/SSLSessionContext.java
	luni/src/test/java/tests/api/javax/net/ssl/KeyStoreBuilderParametersTest.java

SSLEngine improvements. Since I was changing SSLEngine, I wrote an
SSLEngineTest based on my SSLSocketTest to do some simply sanity
checking. It expose a number of issues. I've fixed the small ones,
marked the rest as known failures.

   Renamed some TLS_ cipher suites to SSL_ to match JSSE standard
   names. These were all old suites no longer supported by RI or
   OpenSSL which is why they were missed in an earlier cleanup of this
   type in this class. Also fixed SSLEngine supported cipher suites
   list not to include SSL_NULL_WITH_NULL_NULL which is not a valid
   suite to negotiate.

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java

   SSLEngine instances can have null host values, which caused a
   NullPointerException in the ClientSessionContext implementation.

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java

   SSLEngine tests were failing because SSLParameters was throwing
   NullPointerException instead of IllegalArgument exception on null
   element values. Fixed null pointer message style while I was here.

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java

    Fixed SSLEngine instances to default to server mode like RI

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java

   Fixed KEY_TYPES based on SSLEngine implementation. Removed dead
   code NativeCrypto.getEnabledProtocols which was recently made
   obsolete. Cleaned up null exception messages to follow our convention.

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java

   Added SSLEngineTest which parallels SSLSocketTest in its
   coverage. Similarly added TestSSLEnginePair which loosely parallels
   TestSSLSocketPair.

	luni/src/test/java/javax/net/ssl/SSLEngineTest.java
	luni/src/test/java/javax/net/ssl/AllTests.java
	support/src/test/java/javax/net/ssl/TestSSLEnginePair.java

   SSLEngineTest betters exposed the differences between SSLSocket and
   SSLEngine supported cipher suites. StandardNames now has an
   CIPHER_SUITES_SSLENGINE definition which denotes what is missing
   and what is extra and why in the SSLEngine implementation.

	support/src/test/java/javax/net/ssl/StandardNames.java

    Created StandardNames.assert{Valid,Supported}{CipherSuites,Protocols}
    to factor out some code test code that is also used by new tests.

	support/src/test/java/javax/net/ssl/StandardNames.java
	luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java
	luni/src/test/java/javax/net/ssl/SSLSocketTest.java

    Remove SSLSocketTest known failure and add new SSLEngineTest known failures

	expectations/knownfailures.txt

SSL_OP_NO_TICKET change was recently merged from master which required some fixes.

    For the moment, sslServerSocketSupportsSessionTickets always returns false.

	support/src/test/java/javax/net/ssl/TestSSLContext.java

    Fixed flakey test_SSLSocket_HandshakeCompletedListener which had a
    race because the client thread look in the server session context
    for an session by id potentially before the server thread had a
    chance to store its session. Made noticable because of
    SSL_OP_NO_TICKET recently merged from master (before this code
    path was host only, not device)

	luni/src/test/java/javax/net/ssl/SSLSocketTest.java

    Fix checkjni issue where we need to check for pending exception in
    OpenSSL callback.  Possibly introduced by recent merge of
    SSL_OP_NO_TICKET from master.

	luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp

Expectation updates

    Remove SSLSocketTest known failure and add new SSLEngineTest known failures

	expectations/knownfailures.txt

    Tag test_SSLSocket_getSupportedCipherSuites_connect as large

	expectations/taggedtests.txt

Misc changes:

   opening brace on wrong line

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java

   Long line cleanup while debugging

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketFactoryImpl.java
	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java
	support/src/test/java/javax/net/ssl/TestKeyStore.java

   Removed bogus import

	luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java

   Comment clarify while debugging

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java

   Ctor -> Constructor in comment

	luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java

   Fixed naming of SocketTest_Test_create to TestSocketPair_Create to match renamed classes

	luni/src/test/java/javax/net/ssl/SSLSocketTest.java

Change-Id: I99505e97d6047eeabe4a0b93202075a0b2d486ec
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index 31f0863..4394d94 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -871,8 +871,32 @@
 test tests.api.javax.net.ssl.HostnameVerifierTest#testSubjectAlt
 result EXEC_FAILED
 
-# Need to support SSL_RSA_EXPORT_WITH_RC4_40_MD5
-test javax.net.ssl.SSLSocketTest#test_SSLSocket_getSupportedCipherSuites_connect
+# NO SERVER CERTIFICATE FOUND - selectSuite should not pick a suite that needs a certificate if it is missing
+test javax.net.ssl.SSLEngineTest#test_SSLEngine_beginHandshake_noKeyStore
+result EXEC_FAILED
+
+# NO SERVER CERTIFICATE FOUND - selectSuite should not pick a suite that needs a certificate if it is missing
+test javax.net.ssl.SSLEngineTest#test_SSLEngine_getSupportedCipherSuites_connect
+result EXEC_FAILED
+
+# init - invalid private key
+test javax.net.ssl.SSLEngineTest#test_SSLEngine_clientAuth
+result EXEC_FAILED
+
+# AlertException instead of SSLException
+test javax.net.ssl.SSLEngineTest#test_SSLEngine_setEnableSessionCreation_client
+result EXEC_FAILED
+
+# SSLException instead of failure to handshake
+test javax.net.ssl.SSLEngineTest#test_SSLEngine_setEnableSessionCreation_server
+result EXEC_FAILED
+
+# SSLHandshakeException instead of failure to handshake
+test javax.net.ssl.SSLEngineTest#test_SSLEngine_setUseClientMode
+result EXEC_FAILED
+
+# No *_WITH_NULL_* ciphers work because of 'Invalid transformation: null'
+test javax.net.ssl.SSLEngineTest#test_SSLEngine_getSupportedCipherSuites_connect
 result EXEC_FAILED
 
 # method test fails once in a while. Cannot be sure that exception is thrown in every test execution.
diff --git a/expectations/taggedtests.txt b/expectations/taggedtests.txt
index c4ee467..0a5dbfb 100644
--- a/expectations/taggedtests.txt
+++ b/expectations/taggedtests.txt
@@ -6,3 +6,6 @@
 test org.apache.harmony.tests.java.util.regex.MatcherTest.testAllCodePoints
 tags large
 
+# Takes a long time because it tries connecting every supported cipher suite
+test javax.net.ssl.SSLSocketTest#test_SSLSocket_getSupportedCipherSuites_connect
+tags large
diff --git a/luni/src/main/java/javax/crypto/Cipher.java b/luni/src/main/java/javax/crypto/Cipher.java
index c34ba40..3a2dedd 100644
--- a/luni/src/main/java/javax/crypto/Cipher.java
+++ b/luni/src/main/java/javax/crypto/Cipher.java
@@ -505,7 +505,7 @@
      *             if the specified opmode is invalid.
      */
     public final void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
-        checkMode(mode);
+        checkMode(opmode);
         //        FIXME InvalidKeyException
         //        if keysize exceeds the maximum allowable keysize
         //        (jurisdiction policy files)
@@ -598,7 +598,7 @@
     public final void init(int opmode, Key key, AlgorithmParameterSpec params,
             SecureRandom random) throws InvalidKeyException,
             InvalidAlgorithmParameterException {
-        checkMode(mode);
+        checkMode(opmode);
         //        FIXME InvalidKeyException
         //        if keysize exceeds the maximum allowable keysize
         //        (jurisdiction policy files)
@@ -689,7 +689,7 @@
     public final void init(int opmode, Key key, AlgorithmParameters params,
             SecureRandom random) throws InvalidKeyException,
             InvalidAlgorithmParameterException {
-        checkMode(mode);
+        checkMode(opmode);
         //        FIXME InvalidKeyException
         //        if keysize exceeds the maximum allowable keysize
         //        (jurisdiction policy files)
@@ -777,7 +777,7 @@
      */
     public final void init(int opmode, Certificate certificate,
             SecureRandom random) throws InvalidKeyException {
-        checkMode(mode);
+        checkMode(opmode);
         if (certificate instanceof X509Certificate) {
             Set<String> ce = ((X509Certificate) certificate).getCriticalExtensionOIDs();
             boolean critical = false;
diff --git a/luni/src/main/java/javax/net/ssl/DefaultSSLContext.java b/luni/src/main/java/javax/net/ssl/DefaultSSLContext.java
deleted file mode 100644
index bcb51ff..0000000
--- a/luni/src/main/java/javax/net/ssl/DefaultSSLContext.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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 javax.net.ssl;
-
-import java.io.FileInputStream;
-import java.security.AccessController;
-import java.security.KeyStore;
-import java.security.PrivilegedAction;
-import java.security.Provider;
-import java.security.Security;
-
-import org.apache.harmony.security.fortress.Engine;
-import org.apache.harmony.security.fortress.Services;
-
-/**
- * Support class for this package.
- */
-final class DefaultSSLContext {
-    private static SSLContext defaultSSLContext;
-
-     static synchronized SSLContext getContext() {
-        if (defaultSSLContext == null) {
-            defaultSSLContext = AccessController
-                    .doPrivileged(new PrivilegedAction<SSLContext>() {
-                        public SSLContext run() {
-                            return findDefault();
-                        }
-                    });
-        }
-        return defaultSSLContext;
-    }
-
-    private static SSLContext findDefault() {
-        // FIXME EXPORT CONTROL
-        for (Provider provider : Services.getProvidersList()) {
-            final Provider.Service service = Engine.door.getService(provider, "SSLContext");
-            if (service != null) {
-                try {
-                    SSLContext con = new SSLContext((SSLContextSpi) service.newInstance(null),
-                            service.getProvider(), service.getAlgorithm());
-
-                    /*
-                     * TODO
-                     * javax.net.ssl.keyStoreProvider,
-                     * javax.net.ssl.trustStoreProvider system property
-                     */
-
-                    // find KeyStore, KeyManagers
-                    KeyManager[] keyManagers = null;
-                    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
-                    String keystore = System.getProperty("javax.net.ssl.keyStore");
-                    String keystorepwd = System.getProperty("javax.net.ssl.keyStorePassword");
-                    char[] pwd = null;
-                    if (keystorepwd != null) {
-                        pwd = keystorepwd.toCharArray();
-                    }
-                    if (keystore != null) {
-                        FileInputStream fis = new FileInputStream(keystore);
-                        try {
-                            ks.load(fis, pwd);
-                        } finally {
-                            fis.close();
-                        }
-                        KeyManagerFactory kmf;
-                        String kmfAlg = Security.getProperty("ssl.KeyManagerFactory.algorithm");
-                        if (kmfAlg == null) {
-                            kmfAlg = "SunX509";
-                        }
-                        kmf = KeyManagerFactory.getInstance(kmfAlg);
-                        kmf.init(ks, pwd);
-                        keyManagers = kmf.getKeyManagers();
-                    }
-
-                    // find TrustStore, TrustManagers
-                    TrustManager[] trustManagers = null;
-                    keystore = System.getProperty("javax.net.ssl.trustStore");
-                    keystorepwd = System.getProperty("javax.net.ssl.trustStorePassword");
-                    pwd = null;
-                    if (keystorepwd != null) {
-                        pwd = keystorepwd.toCharArray();
-                    }
-                    // TODO Defaults: jssecacerts; cacerts
-                    if (keystore != null) {
-                        FileInputStream fis = new FileInputStream(keystore);
-                        try {
-                            ks.load(fis, pwd);
-                        } finally {
-                            fis.close();
-                        }
-                        TrustManagerFactory tmf;
-                        String tmfAlg = Security.getProperty("ssl.TrustManagerFactory.algorithm");
-                        if (tmfAlg == null) {
-                            tmfAlg = "PKIX";
-                        }
-                        tmf = TrustManagerFactory.getInstance(tmfAlg);
-                        tmf.init(ks);
-                        trustManagers = tmf.getTrustManagers();
-                    }
-
-                    con.init(keyManagers, trustManagers, null);
-                    return con;
-                } catch (Exception e) {
-                    // ignore and try another
-                }
-            }
-        }
-        return null;
-    }
-}
diff --git a/luni/src/main/java/javax/net/ssl/HandshakeCompletedEvent.java b/luni/src/main/java/javax/net/ssl/HandshakeCompletedEvent.java
index 4618280..4ff53f5 100644
--- a/luni/src/main/java/javax/net/ssl/HandshakeCompletedEvent.java
+++ b/luni/src/main/java/javax/net/ssl/HandshakeCompletedEvent.java
@@ -17,7 +17,6 @@
 
 package javax.net.ssl;
 
-import java.io.Serializable;
 import java.security.Principal;
 import java.security.cert.Certificate;
 import javax.security.cert.X509Certificate;
@@ -27,13 +26,7 @@
  * The event object encapsulating the information about a completed SSL
  * handshake on a SSL connection.
  */
-public class HandshakeCompletedEvent extends EventObject implements Serializable {
-
-    /**
-     * The 5.0 spec. doesn't declare this serialVersionUID field In order to be
-     * compatible it is explicitly declared here
-     */
-    private static final long serialVersionUID = 7914963744257769778L;
+public class HandshakeCompletedEvent extends EventObject {
 
     private transient SSLSession session;
 
diff --git a/luni/src/main/java/javax/net/ssl/KeyStoreBuilderParameters.java b/luni/src/main/java/javax/net/ssl/KeyStoreBuilderParameters.java
index 899da70..d92aa52 100644
--- a/luni/src/main/java/javax/net/ssl/KeyStoreBuilderParameters.java
+++ b/luni/src/main/java/javax/net/ssl/KeyStoreBuilderParameters.java
@@ -54,8 +54,7 @@
      * @throws IllegalArgumentException
      *             if the specified list is empty.
      */
-    @SuppressWarnings("unchecked")
-    public KeyStoreBuilderParameters(List parameters) {
+    public KeyStoreBuilderParameters(List<KeyStore.Builder> parameters) {
         super();
         if (parameters == null) {
             throw new NullPointerException("Builders list is null");
@@ -72,8 +71,7 @@
      *
      * @return the unmodifiable list of {@code KeyStore.Builder}s.
      */
-    @SuppressWarnings("unchecked")
-    public List getParameters() {
+    public List<KeyStore.Builder> getParameters() {
         return ksbuilders;
     }
 }
diff --git a/luni/src/main/java/javax/net/ssl/SSLContext.java b/luni/src/main/java/javax/net/ssl/SSLContext.java
index 8a0a157..7aae41f 100644
--- a/luni/src/main/java/javax/net/ssl/SSLContext.java
+++ b/luni/src/main/java/javax/net/ssl/SSLContext.java
@@ -36,7 +36,49 @@
     private static final String SERVICE = "SSLContext";
 
     // Used to access common engine functionality
-    private static Engine engine = new Engine(SERVICE);
+    private static final Engine ENGINE = new Engine(SERVICE);
+
+    /**
+     * Default SSLContext that can be replaced with SSLContext.setDefault()
+     */
+    private static SSLContext DEFAULT;
+
+    /**
+     * Returns the default SSLContext.
+     *
+     * The default SSL context can be set with {@link #setDefault}. If
+     * not, one will be created with {@code
+     * SSLContext.getInstance("Default")}, which will already be
+     * initialized.
+     *
+     * @throws NoSuchAlgorithmException if there is a problem creating
+     * the default instance.
+     * @since 1.6
+     */
+    public static SSLContext getDefault() throws NoSuchAlgorithmException {
+        synchronized (ENGINE) {
+            if (DEFAULT == null) {
+                DEFAULT = SSLContext.getInstance("Default");
+            }
+            return DEFAULT;
+        }
+    }
+
+    /**
+     * Sets the default SSLContext instance as returned by {@link
+     * #getDefault()} to a non-null initialized value.
+     *
+     * @throws NullPointerException on a null argument
+     * @since 1.6
+     */
+    public static void setDefault(SSLContext sslContext) {
+        if (sslContext == null) {
+            throw new NullPointerException("sslContext == null");
+        }
+        synchronized (ENGINE) {
+            DEFAULT = sslContext;
+        }
+    }
 
     /**
      * Creates a new {@code SSLContext} instance for the specified protocol.
@@ -54,9 +96,9 @@
         if (protocol == null) {
             throw new NullPointerException("protocol is null");
         }
-        synchronized (engine) {
-            engine.getInstance(protocol, null);
-            return new SSLContext((SSLContextSpi) engine.spi, engine.provider, protocol);
+        synchronized (ENGINE) {
+            ENGINE.getInstance(protocol, null);
+            return new SSLContext((SSLContextSpi) ENGINE.spi, ENGINE.provider, protocol);
         }
     }
 
@@ -117,9 +159,9 @@
         if (protocol == null) {
             throw new NullPointerException("protocol is null");
         }
-        synchronized (engine) {
-            engine.getInstance(protocol, provider, null);
-            return new SSLContext((SSLContextSpi) engine.spi, provider, protocol);
+        synchronized (ENGINE) {
+            ENGINE.getInstance(protocol, provider, null);
+            return new SSLContext((SSLContextSpi) ENGINE.spi, provider, protocol);
         }
     }
 
@@ -250,4 +292,26 @@
     public final SSLSessionContext getClientSessionContext() {
         return spiImpl.engineGetClientSessionContext();
     }
+
+    /**
+     * Returns the default SSL handshake parameters for SSLSockets
+     * created by this SSLContext.
+     *
+     * @throws UnsupportedOperationException
+     * @since 1.6
+     */
+    public final SSLParameters getDefaultSSLParameters() {
+        return spiImpl.engineGetDefaultSSLParameters();
+    }
+
+    /**
+     * Returns SSL handshake parameters for SSLSockets that includes
+     * all supported cipher suites and protocols.
+     *
+     * @throws UnsupportedOperationException
+     * @since 1.6
+     */
+    public final SSLParameters getSupportedSSLParameters() {
+        return spiImpl.engineGetSupportedSSLParameters();
+    }
 }
diff --git a/luni/src/main/java/javax/net/ssl/SSLContextSpi.java b/luni/src/main/java/javax/net/ssl/SSLContextSpi.java
index 44d2c59..20c763e 100644
--- a/luni/src/main/java/javax/net/ssl/SSLContextSpi.java
+++ b/luni/src/main/java/javax/net/ssl/SSLContextSpi.java
@@ -106,4 +106,27 @@
      */
     protected abstract SSLSessionContext engineGetClientSessionContext();
 
+
+    /**
+     * Returns a new SSLParameters instance that includes the default
+     * SSL handshake parameters values including cipher suites,
+     * protocols, and client authentication.
+     *
+     * The default implementation returns an SSLParameters with values
+     * based an SSLSocket created from this instances SocketFactory.
+     *
+     * @since 1.6
+     */
+    protected abstract SSLParameters engineGetDefaultSSLParameters();
+
+    /**
+     * Returns a new SSLParameters instance that includes all
+     * supported cipher suites and protocols.
+     *
+     * The default implementation returns an SSLParameters with values
+     * based an SSLSocket created from this instances SocketFactory.
+     *
+     * @since 1.6
+     */
+    protected abstract SSLParameters engineGetSupportedSSLParameters();
 }
diff --git a/luni/src/main/java/javax/net/ssl/SSLEngine.java b/luni/src/main/java/javax/net/ssl/SSLEngine.java
index 21a956c..f737e98 100644
--- a/luni/src/main/java/javax/net/ssl/SSLEngine.java
+++ b/luni/src/main/java/javax/net/ssl/SSLEngine.java
@@ -324,8 +324,10 @@
      *             if the engine does not have all the needed settings (e.g.
      *             client/server mode not set).
      */
-    public abstract SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts, int offset, int length)
-            throws SSLException;
+    public abstract SSLEngineResult unwrap(ByteBuffer src,
+                                           ByteBuffer[] dsts,
+                                           int offset,
+                                           int length) throws SSLException;
 
     /**
      * Encodes the outgoing application data buffers into the network data
@@ -461,4 +463,46 @@
     public SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
         return wrap(new ByteBuffer[] { src }, 0, 1, dst);
     }
+
+    /**
+     * Returns a new SSLParameters based on this SSLSocket's current
+     * cipher suites, protocols, and client authentication settings.
+     *
+     * @since 1.6
+     */
+    public SSLParameters getSSLParameters() {
+        SSLParameters p = new SSLParameters();
+        p.setCipherSuites(getEnabledCipherSuites());
+        p.setProtocols(getEnabledProtocols());
+        p.setNeedClientAuth(getNeedClientAuth());
+        p.setWantClientAuth(getWantClientAuth());
+        return p;
+    }
+
+    /**
+     * Sets various SSL handshake parameters based on the SSLParameter
+     * argument. Specifically, sets the SSLEngine's enabled cipher
+     * suites if the parameter's cipher suites are non-null. Similarly
+     * sets the enabled protocols. If the parameters specify the want
+     * or need for client authentication, those requirements are set
+     * on the SSLEngine, otherwise both are set to false.
+     * @since 1.6
+     */
+    public void setSSLParameters(SSLParameters p) {
+        String[] cipherSuites = p.getCipherSuites();
+        if (cipherSuites != null) {
+            setEnabledCipherSuites(cipherSuites);
+        }
+        String[] protocols = p.getProtocols();
+        if (protocols != null) {
+            setEnabledProtocols(protocols);
+        }
+        if (p.getNeedClientAuth()) {
+            setNeedClientAuth(true);
+        } else if (p.getWantClientAuth()) {
+            setWantClientAuth(true);
+        } else {
+            setWantClientAuth(false);
+        }
+    }
 }
diff --git a/luni/src/main/java/javax/net/ssl/SSLParameters.java b/luni/src/main/java/javax/net/ssl/SSLParameters.java
new file mode 100644
index 0000000..6694ef2
--- /dev/null
+++ b/luni/src/main/java/javax/net/ssl/SSLParameters.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2010 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 javax.net.ssl;
+
+/**
+ * SSL handshake parameters that include protocols, cipher suites, and
+ * client authentication requirements.
+ * @since 1.6
+ */
+public class SSLParameters {
+
+    private String[] cipherSuites;
+    private String[] protocols;
+    private boolean needClientAuth;
+    private boolean wantClientAuth;
+
+    /**
+     * The default SSLParameters constructor. Cipher suites and
+     * protocols are initialized to null and client authentication
+     * options are initialized to false.
+     */
+    public SSLParameters() {}
+
+    /**
+     * A SSLParameters constructor that allows the values for the
+     * initial cipher suites array to be provided. Other values
+     * default as specified in {@link #SSLParameters()}.
+     *
+     * @param cipherSuites An array of cipherSuites that is cloned for
+     * use within the SSLParameters, or null.
+     */
+    public SSLParameters(String[] cipherSuites) {
+        setCipherSuites(cipherSuites);
+    }
+
+    /**
+     * A SSLParameters constructor that allows the values for initial
+     * cipher suites and protocols arrays to be provided. Other values
+     * default as specified in {@link #SSLParameters()}.
+     *
+     * @param cipherSuites An array of cipher names that is cloned for
+     * use within the SSLParameters, or null.
+     * @param protocols An array of protocol names that is cloned for
+     * use within the SSLParameters, or null.
+     */
+    public SSLParameters(String[] cipherSuites,
+                         String[] protocols) {
+        setCipherSuites(cipherSuites);
+        setProtocols(protocols);
+    }
+
+    /**
+     * Returns a copy of the cipher suites, or null if none have been
+     * specified.
+     */
+    public String[] getCipherSuites() {
+        if (cipherSuites == null) {
+            return null;
+        }
+        return cipherSuites.clone();
+    }
+
+    /**
+     * Sets the cipher suites to a copy of the input, or null
+     */
+    public void setCipherSuites(String[] cipherSuites) {
+        this.cipherSuites = ((cipherSuites == null)
+                             ? null
+                             : cipherSuites.clone());
+    }
+
+    /**
+     * Returns a copy of the protocols, or null if none have been
+     * specified.
+     */
+    public String[] getProtocols() {
+        if (protocols == null) {
+            return null;
+        }
+        return protocols.clone();
+    }
+
+    /**
+     * Sets the protocols to a copy of the input, or null
+     */
+    public void setProtocols(String[] protocols) {
+        this.protocols = ((protocols == null)
+                             ? null
+                             : protocols.clone());
+    }
+
+    /**
+     * Returns true if a server requires authentication from a client
+     * during handshaking. If this returns true, {@link
+     * #getWantClientAuth} will return false.
+     */
+    public boolean getNeedClientAuth () {
+        return needClientAuth;
+    }
+
+    /**
+     * Sets whether or not to a server needs client authentication.
+     * After calling this, #getWantClientAuth() will return false.
+     */
+    public void setNeedClientAuth (boolean needClientAuth) {
+        this.needClientAuth = needClientAuth;
+        this.wantClientAuth = false;
+    }
+
+    /**
+     * Returns true if a server optionally wants to authenticate a
+     * client during handshaking. If this returns true, {@link
+     * #getNeedClientAuth} will return false.
+     */
+    public boolean getWantClientAuth () {
+        return wantClientAuth;
+    }
+
+    /**
+     * Sets whether or not to a server wants client authentication.
+     * After calling this, #getNeedClientAuth() will return false.
+     */
+    public void setWantClientAuth (boolean wantClientAuth) {
+        this.wantClientAuth = wantClientAuth;
+        this.needClientAuth = false;
+    }
+}
diff --git a/luni/src/main/java/javax/net/ssl/SSLServerSocketFactory.java b/luni/src/main/java/javax/net/ssl/SSLServerSocketFactory.java
index ccb2c5d..e8a7071 100644
--- a/luni/src/main/java/javax/net/ssl/SSLServerSocketFactory.java
+++ b/luni/src/main/java/javax/net/ssl/SSLServerSocketFactory.java
@@ -18,9 +18,9 @@
 package javax.net.ssl;
 
 import java.security.AccessController;
+import java.security.NoSuchAlgorithmException;
 import java.security.PrivilegedAction;
 import java.security.Security;
-
 import javax.net.ServerSocketFactory;
 
 /**
@@ -65,8 +65,12 @@
             });
         }
         if (defaultServerSocketFactory == null) {
-            // Try to find in providers
-            SSLContext context = DefaultSSLContext.getContext();
+            SSLContext context;
+            try {
+                context = SSLContext.getDefault();
+            } catch (NoSuchAlgorithmException e) {
+                context = null;
+            }
             if (context != null) {
                 defaultServerSocketFactory = context.getServerSocketFactory();
             }
diff --git a/luni/src/main/java/javax/net/ssl/SSLSessionBindingEvent.java b/luni/src/main/java/javax/net/ssl/SSLSessionBindingEvent.java
index 19ae835..705192d 100644
--- a/luni/src/main/java/javax/net/ssl/SSLSessionBindingEvent.java
+++ b/luni/src/main/java/javax/net/ssl/SSLSessionBindingEvent.java
@@ -17,7 +17,6 @@
 
 package javax.net.ssl;
 
-import java.io.Serializable;
 import java.util.EventObject;
 
 /**
@@ -25,17 +24,8 @@
  * object is bound ({@link SSLSession#putValue(String, Object)}) or unbound
  * ({@link SSLSession#removeValue(String)}) to an {@code SSLSession}.
  */
-public class SSLSessionBindingEvent extends EventObject implements Serializable {
+public class SSLSessionBindingEvent extends EventObject {
 
-    /**
-     * The 5.0 spec. doesn't declare this serialVersionUID field In order to be compatible it is
-     * explicitly declared here
-     */
-    private static final long serialVersionUID = 3989172637106345L;
-
-    /**
-     * @serial include
-     */
     private final String name;
 
     /**
diff --git a/luni/src/main/java/javax/net/ssl/SSLSessionContext.java b/luni/src/main/java/javax/net/ssl/SSLSessionContext.java
index 154376e..f393072 100644
--- a/luni/src/main/java/javax/net/ssl/SSLSessionContext.java
+++ b/luni/src/main/java/javax/net/ssl/SSLSessionContext.java
@@ -28,8 +28,7 @@
      *
      * @return an iterable of all session identifiers in this session context.
      */
-    @SuppressWarnings("unchecked")
-    public Enumeration getIds();
+    public Enumeration<byte[]> getIds();
 
     /**
      * Returns the session for the specified session identifier.
diff --git a/luni/src/main/java/javax/net/ssl/SSLSocket.java b/luni/src/main/java/javax/net/ssl/SSLSocket.java
index 4a70843..4539c3b 100644
--- a/luni/src/main/java/javax/net/ssl/SSLSocket.java
+++ b/luni/src/main/java/javax/net/ssl/SSLSocket.java
@@ -296,4 +296,45 @@
      */
     public abstract boolean getEnableSessionCreation();
 
+    /**
+     * Returns a new SSLParameters based on this SSLSocket's current
+     * cipher suites, protocols, and client authentication settings.
+     *
+     * @since 1.6
+     */
+    public SSLParameters getSSLParameters() {
+        SSLParameters p = new SSLParameters();
+        p.setCipherSuites(getEnabledCipherSuites());
+        p.setProtocols(getEnabledProtocols());
+        p.setNeedClientAuth(getNeedClientAuth());
+        p.setWantClientAuth(getWantClientAuth());
+        return p;
+    }
+
+    /**
+     * Sets various SSL handshake parameters based on the SSLParameter
+     * argument. Specifically, sets the SSLSocket's enabled cipher
+     * suites if the parameter's cipher suites are non-null. Similarly
+     * sets the enabled protocols. If the parameters specify the want
+     * or need for client authentication, those requirements are set
+     * on the SSLSocket, otherwise both are set to false.
+     * @since 1.6
+     */
+    public void setSSLParameters(SSLParameters p) {
+        String[] cipherSuites = p.getCipherSuites();
+        if (cipherSuites != null) {
+            setEnabledCipherSuites(cipherSuites);
+        }
+        String[] protocols = p.getProtocols();
+        if (protocols != null) {
+            setEnabledProtocols(protocols);
+        }
+        if (p.getNeedClientAuth()) {
+            setNeedClientAuth(true);
+        } else if (p.getWantClientAuth()) {
+            setWantClientAuth(true);
+        } else {
+            setWantClientAuth(false);
+        }
+    }
 }
diff --git a/luni/src/main/java/javax/net/ssl/SSLSocketFactory.java b/luni/src/main/java/javax/net/ssl/SSLSocketFactory.java
index b75c218..b31d4e2 100644
--- a/luni/src/main/java/javax/net/ssl/SSLSocketFactory.java
+++ b/luni/src/main/java/javax/net/ssl/SSLSocketFactory.java
@@ -20,13 +20,11 @@
 import java.io.IOException;
 import java.net.Socket;
 import java.security.AccessController;
+import java.security.NoSuchAlgorithmException;
 import java.security.PrivilegedAction;
 import java.security.Security;
-// BEGIN android-added
 import java.util.logging.Level;
 import java.util.logging.Logger;
-// END android-added
-
 import javax.net.SocketFactory;
 
 /**
@@ -77,8 +75,12 @@
         }
 
         if (defaultSocketFactory == null) {
-            // Try to find in providers
-            SSLContext context = DefaultSSLContext.getContext();
+            SSLContext context;
+            try {
+                context = SSLContext.getDefault();
+            } catch (NoSuchAlgorithmException e) {
+                context = null;
+            }
             if (context != null) {
                 defaultSocketFactory = context.getSocketFactory();
             }
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
index a6c2e4c..f6eef42 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
@@ -171,11 +171,11 @@
             CODE_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA);
 
     static final CipherSuite TLS_DH_DSS_WITH_DES_CBC_SHA = new CipherSuite(
-            "TLS_DH_DSS_WITH_DES_CBC_SHA", false, KEY_EXCHANGE_DH_DSS,
+            "SSL_DH_DSS_WITH_DES_CBC_SHA", false, KEY_EXCHANGE_DH_DSS,
             "DES_CBC", "SHA", CODE_TLS_DH_DSS_WITH_DES_CBC_SHA);
 
     static final CipherSuite TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
-            "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", false, KEY_EXCHANGE_DH_DSS,
+            "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", false, KEY_EXCHANGE_DH_DSS,
             "3DES_EDE_CBC", "SHA", CODE_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA);
 
     static final CipherSuite TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
@@ -184,11 +184,11 @@
             CODE_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA);
 
     static final CipherSuite TLS_DH_RSA_WITH_DES_CBC_SHA = new CipherSuite(
-            "TLS_DH_RSA_WITH_DES_CBC_SHA", false, KEY_EXCHANGE_DH_RSA,
+            "SSL_DH_RSA_WITH_DES_CBC_SHA", false, KEY_EXCHANGE_DH_RSA,
             "DES_CBC", "SHA", CODE_TLS_DH_RSA_WITH_DES_CBC_SHA);
 
     static final CipherSuite TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
-            "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", false, KEY_EXCHANGE_DH_RSA,
+            "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", false, KEY_EXCHANGE_DH_RSA,
             "3DES_EDE_CBC", "SHA", CODE_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA);
 
     static final CipherSuite TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
@@ -296,6 +296,9 @@
         int count = 0;
         SUITES_BY_NAME = new Hashtable<String, CipherSuite>();
         for (int i = 0; i < SUITES_BY_CODE.length; i++) {
+            if (SUITES_BY_CODE[i] == TLS_NULL_WITH_NULL_NULL) {
+                continue;
+            }
             SUITES_BY_NAME.put(SUITES_BY_CODE[i].getName(), SUITES_BY_CODE[i]);
             if (SUITES_BY_CODE[i].supported) {
                 count++;
@@ -305,6 +308,9 @@
         SUPPORTED_CIPHER_SUITE_NAMES = new String[count];
         count = 0;
         for (int i = 0; i < SUITES_BY_CODE.length; i++) {
+            if (SUITES_BY_CODE[i] == TLS_NULL_WITH_NULL_NULL) {
+                continue;
+            }
             if (SUITES_BY_CODE[i].supported) {
                 SUPPORTED_CIPHER_SUITES[count] = SUITES_BY_CODE[i];
                 SUPPORTED_CIPHER_SUITE_NAMES[count] = SUPPORTED_CIPHER_SUITES[count].getName();
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
index 0b297a3..97ededd 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
@@ -44,7 +44,12 @@
     }
 
     protected void sessionRemoved(SSLSession session) {
-        HostAndPort hostAndPortKey = new HostAndPort(session);
+        String host = session.getPeerHost();
+        int port = session.getPeerPort();
+        if (host == null) {
+            return;
+        }
+        HostAndPort hostAndPortKey = new HostAndPort(host, port);
         synchronized (sessionsByHostAndPort) {
             sessionsByHostAndPort.remove(hostAndPortKey);
         }
@@ -58,6 +63,9 @@
      * @return cached session or null if none found
      */
     public SSLSession getSession(String host, int port) {
+        if (host == null) {
+            return null;
+        }
         SSLSession session;
         HostAndPort hostAndPortKey = new HostAndPort(host, port);
         synchronized (sessionsByHostAndPort) {
@@ -89,7 +97,13 @@
     void putSession(SSLSession session) {
         super.putSession(session);
 
-        HostAndPort hostAndPortKey = new HostAndPort(session);
+        String host = session.getPeerHost();
+        int port = session.getPeerPort();
+        if (host == null) {
+            return;
+        }
+
+        HostAndPort hostAndPortKey = new HostAndPort(host, port);
         synchronized (sessionsByHostAndPort) {
             sessionsByHostAndPort.put(hostAndPortKey, session);
         }
@@ -107,10 +121,6 @@
         final String host;
         final int port;
 
-        HostAndPort(SSLSession session) {
-            this(session.getPeerHost(), session.getPeerPort());
-        }
-
         HostAndPort(String host, int port) {
             this.host = host;
             this.port = port;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java
new file mode 100644
index 0000000..609a448
--- /dev/null
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java
@@ -0,0 +1,138 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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 org.apache.harmony.xnet.provider.jsse;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.SecureRandom;
+import java.security.Security;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+
+/**
+ * Support class for this package.
+ */
+public final class DefaultSSLContextImpl extends SSLContextImpl {
+
+    /**
+     * Accessed by SSLContextImpl(DefaultSSLContextImpl) holding the
+     * DefaultSSLContextImpl.class monitor
+     */
+    private static KeyManager[] KEY_MANAGERS;
+
+    /**
+     * Accessed by SSLContextImpl(DefaultSSLContextImpl) holding the
+     * DefaultSSLContextImpl.class monitor
+     */
+    private static TrustManager[] TRUST_MANAGERS;
+
+    /**
+     * DefaultSSLContextImpl delegates the work to the super class
+     * since there is no way to put a synchronized around both the
+     * call to super and the rest of this constructor to guarantee
+     * that we don't have races in creating the state shared between
+     * all default SSLContexts.
+     */
+    public DefaultSSLContextImpl() throws GeneralSecurityException, IOException {
+        super(null);
+    }
+
+    // TODO javax.net.ssl.keyStoreProvider system property
+    KeyManager[] getKeyManagers () throws GeneralSecurityException, IOException {
+        if (KEY_MANAGERS != null) {
+            return KEY_MANAGERS;
+        }
+        // find KeyStore, KeyManagers
+        String keystore = System.getProperty("javax.net.ssl.keyStore");
+        if (keystore == null) {
+            return null;
+        }
+        String keystorepwd = System.getProperty("javax.net.ssl.keyStorePassword");
+        char[] pwd = (keystorepwd == null) ? null : keystorepwd.toCharArray();
+
+        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+        InputStream is = null;
+        try {
+            is = new BufferedInputStream(new FileInputStream(keystore));
+            ks.load(is, pwd);
+        } finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+
+        String kmfAlg = Security.getProperty("ssl.KeyManagerFactory.algorithm");
+        if (kmfAlg == null) {
+            kmfAlg = "SunX509";
+        }
+
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlg);
+        kmf.init(ks, pwd);
+        KEY_MANAGERS = kmf.getKeyManagers();
+        return KEY_MANAGERS;
+    }
+
+    // TODO javax.net.ssl.trustStoreProvider system property
+    TrustManager[] getTrustManagers() throws GeneralSecurityException, IOException {
+        if (TRUST_MANAGERS != null) {
+            return TRUST_MANAGERS;
+        }
+
+        // find TrustStore, TrustManagers
+        String keystore = System.getProperty("javax.net.ssl.trustStore");
+        if (keystore == null) {
+            return null;
+        }
+        String keystorepwd = System.getProperty("javax.net.ssl.trustStorePassword");
+        char[] pwd = (keystorepwd == null) ? null : keystorepwd.toCharArray();
+
+        // TODO Defaults: jssecacerts; cacerts
+        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+        InputStream is = null;
+        try {
+            is = new BufferedInputStream(new FileInputStream(keystore));
+            ks.load(is, pwd);
+        } finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+        String tmfAlg = Security.getProperty("ssl.TrustManagerFactory.algorithm");
+        if (tmfAlg == null) {
+            tmfAlg = "PKIX";
+        }
+
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlg);
+        tmf.init(ks);
+        TRUST_MANAGERS = tmf.getTrustManagers();
+        return TRUST_MANAGERS;
+    }
+
+    @Override
+    public void engineInit(KeyManager[] kms, TrustManager[] tms,
+            SecureRandom sr) throws KeyManagementException {
+        throw new KeyManagementException("Do not init() the default SSLContext ");
+    }
+}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
index 94b18ce..283deb6 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
@@ -388,7 +388,9 @@
             md5 = MessageDigest.getInstance("MD5");
             sha = MessageDigest.getInstance("SHA-1");
         } catch (Exception e) {
-            fatalAlert(AlertProtocol.INTERNAL_ERROR, "Could not initialize the Digest Algorithms.", e);
+            fatalAlert(AlertProtocol.INTERNAL_ERROR,
+                       "Could not initialize the Digest Algorithms.",
+                       e);
             return;
         }
         try {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
index 6d50756..cb7d6c9 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
@@ -115,6 +115,7 @@
                 put("KeyManagerFactory.X509", KeyManagerFactoryImpl.class.getName());
                 put("TrustManagerFactory.X509", TrustManagerFactoryImpl.class.getName());
                 // BEGIN android-added
+                put("SSLContext.Default", DefaultSSLContextImpl.class.getName());
                 put("SSLContext.SSL", SSLContextImpl.class.getName());
                 put("Alg.Alias.SSLContext.SSLv3", "SSL");
                 put("MessageDigest.SHA-1", "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA1");
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
index 75ca8ea..7e6723e 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
@@ -256,7 +256,7 @@
 
     public static native int SSL_new(int ssl_ctx) throws IOException;
 
-    public static final String[] KEY_TYPES = new String[] { "RSA", "DSA", "DH" };
+    public static final String[] KEY_TYPES = new String[] { "RSA", "DSA", "DH_RSA" , "DH_DSA" };
 
     public static native void SSL_use_certificate(int ssl, byte[] pemEncodedCertificate);
 
@@ -280,25 +280,13 @@
         return new String[] { SUPPORTED_PROTOCOL_SSLV3, SUPPORTED_PROTOCOL_TLSV1 };
     }
 
-    public static String[] getEnabledProtocols(int ssl) {
-        long options = SSL_get_options(ssl);
-        ArrayList<String> array = new ArrayList<String>();
-        if ((options & NativeCrypto.SSL_OP_NO_SSLv3) == 0) {
-            array.add(SUPPORTED_PROTOCOL_SSLV3);
-        }
-        if ((options & NativeCrypto.SSL_OP_NO_TLSv1) == 0) {
-            array.add(SUPPORTED_PROTOCOL_TLSV1);
-        }
-        return array.toArray(new String[array.size()]);
-    }
-
     public static void setEnabledProtocols(int ssl, String[] protocols) {
         if (protocols == null) {
             throw new IllegalArgumentException("protocols == null");
         }
 
         // openssl uses negative logic letting you disable protocols.
-        // so first, assume we need to set all (disable all ) and clear none (enable none).
+        // so first, assume we need to set all (disable all) and clear none (enable none).
         // in the loop, selectively move bits from set to clear (from disable to enable)
         long optionsToSet = (SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
         long optionsToClear = 0;
@@ -325,7 +313,7 @@
 
     public static String[] checkEnabledProtocols(String[] protocols) {
         if (protocols == null) {
-            throw new IllegalArgumentException("protocols parameter is null");
+            throw new IllegalArgumentException("protocols == null");
         }
         for (int i = 0; i < protocols.length; i++) {
             String protocol = protocols[i];
@@ -333,7 +321,7 @@
                 throw new IllegalArgumentException("protocols[" + i + "] == null");
             }
             if ((!protocol.equals(SUPPORTED_PROTOCOL_SSLV3))
-                && (!protocol.equals(SUPPORTED_PROTOCOL_TLSV1))) {
+                    && (!protocol.equals(SUPPORTED_PROTOCOL_TLSV1))) {
                 throw new IllegalArgumentException("protocol " + protocol +
                                                    " is not supported");
             }
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketFactoryImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketFactoryImpl.java
index f342457..f2126ad 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketFactoryImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketFactoryImpl.java
@@ -61,11 +61,17 @@
 
     public ServerSocket createServerSocket(int port, int backlog)
             throws IOException {
-        return new OpenSSLServerSocketImpl(port, backlog, (SSLParameters) sslParameters.clone());
+        return new OpenSSLServerSocketImpl(port,
+                                           backlog,
+                                           (SSLParameters) sslParameters.clone());
     }
 
-    public ServerSocket createServerSocket(int port, int backlog,
-            InetAddress iAddress) throws IOException {
-        return new OpenSSLServerSocketImpl(port, backlog, iAddress, (SSLParameters) sslParameters.clone());
+    public ServerSocket createServerSocket(int port,
+                                           int backlog,
+                                           InetAddress iAddress) throws IOException {
+        return new OpenSSLServerSocketImpl(port,
+                                           backlog,
+                                           iAddress,
+                                           (SSLParameters) sslParameters.clone());
     }
 }
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java
index 7b6d7c8..ed8861c 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java
@@ -66,19 +66,35 @@
 
     public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
             throws IOException, UnknownHostException {
-        return new OpenSSLSocketImpl(host, port, localHost, localPort, (SSLParameters) sslParameters.clone());
+        return new OpenSSLSocketImpl(host,
+                                     port,
+                                     localHost,
+                                     localPort,
+                                     (SSLParameters) sslParameters.clone());
     }
 
     public Socket createSocket(InetAddress host, int port) throws IOException {
         return new OpenSSLSocketImpl(host, port, (SSLParameters) sslParameters.clone());
     }
 
-    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
+    public Socket createSocket(InetAddress address,
+                               int port,
+                               InetAddress localAddress,
+                               int localPort)
             throws IOException {
-        return new OpenSSLSocketImpl(address, port, localAddress, localPort, (SSLParameters) sslParameters.clone());
+        return new OpenSSLSocketImpl(address,
+                                     port,
+                                     localAddress,
+                                     localPort,
+                                     (SSLParameters) sslParameters.clone());
     }
 
-    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
-        return new OpenSSLSocketImplWrapper(s, host, port, autoClose, (SSLParameters) sslParameters.clone());
+    public Socket createSocket(Socket s, String host, int port, boolean autoClose)
+            throws IOException {
+        return new OpenSSLSocketImplWrapper(s,
+                                            host,
+                                            port,
+                                            autoClose,
+                                            (SSLParameters) sslParameters.clone());
     }
 }
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
index 61c1bdc..b23f50e 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
@@ -22,7 +22,6 @@
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.net.InetAddress;
-import java.net.InetSocketAddress;
 import java.net.Socket;
 import java.net.SocketException;
 import java.security.PrivateKey;
@@ -122,8 +121,7 @@
      * @throws IOException if network fails
      * @throws java.net.UnknownHostException host not defined
      */
-    protected OpenSSLSocketImpl(String host, int port,
-            SSLParameters sslParameters)
+    protected OpenSSLSocketImpl(String host, int port, SSLParameters sslParameters)
         throws IOException {
         super(host, port);
         init(sslParameters);
@@ -135,8 +133,7 @@
      * @throws IOException if network fails
      * @throws java.net.UnknownHostException host not defined
      */
-    protected OpenSSLSocketImpl(InetAddress address, int port,
-            SSLParameters sslParameters)
+    protected OpenSSLSocketImpl(InetAddress address, int port, SSLParameters sslParameters)
         throws IOException {
         super(address, port);
         init(sslParameters);
@@ -149,8 +146,9 @@
      * @throws IOException if network fails
      * @throws java.net.UnknownHostException host not defined
      */
-    protected OpenSSLSocketImpl(String host, int port, InetAddress clientAddress,
-            int clientPort, SSLParameters sslParameters)
+    protected OpenSSLSocketImpl(String host, int port,
+                                InetAddress clientAddress, int clientPort,
+                                SSLParameters sslParameters)
         throws IOException {
         super(host, port, clientAddress, clientPort);
         init(sslParameters);
@@ -163,7 +161,8 @@
      * @throws java.net.UnknownHostException host not defined
      */
     protected OpenSSLSocketImpl(InetAddress address, int port,
-            InetAddress clientAddress, int clientPort, SSLParameters sslParameters)
+                                InetAddress clientAddress, int clientPort,
+                                SSLParameters sslParameters)
         throws IOException {
         super(address, port, clientAddress, clientPort);
         init(sslParameters);
@@ -422,7 +421,7 @@
                                                     wrappedHost, wrappedPort,
                                                     sessionContext);
             }
-            // putSession will be done later in handshakeCompleted() callback
+            // if not, putSession later in handshakeCompleted() callback
             if (handshakeCompleted) {
                 sessionContext.putSession(sslSession);
             }
@@ -437,7 +436,7 @@
         }
         // END android-added
 
-        // notifyHandshakeCompletedListeners will be done later in handshakeCompleted() callback
+        // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback
         if (handshakeCompleted) {
             notifyHandshakeCompletedListeners();
         }
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
index 81dc1a5..c67b151 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
@@ -17,22 +17,19 @@
 
 package org.apache.harmony.xnet.provider.jsse;
 
-import org.apache.harmony.xnet.provider.jsse.SSLEngineImpl;
-import org.apache.harmony.xnet.provider.jsse.SSLParameters;
-// BEGIN android-removed
-// import org.apache.harmony.xnet.provider.jsse.SSLServerSocketFactoryImpl;
-// END android-removed
-
+import java.io.IOException;
 import java.security.KeyManagementException;
 import java.security.SecureRandom;
-
+import java.security.GeneralSecurityException;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContextSpi;
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLServerSocketFactory;
 import javax.net.ssl.SSLSessionContext;
+import javax.net.ssl.SSLSocket;
 import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
+import org.apache.harmony.xnet.provider.jsse.SSLEngineImpl;
 
 // BEGIN android-note
 //  Modified heavily during SSLSessionContext refactoring. Added support for
@@ -44,16 +41,46 @@
  */
 public class SSLContextImpl extends SSLContextSpi {
 
+    /**
+     * The default SSLContextImpl for use with SSLContext.getInstance("Default").
+     * Protected by the DefaultSSLContextImpl.class monitor.
+     */
+    private static DefaultSSLContextImpl DEFAULT_SSL_CONTEXT_IMPL;
+
     /** Client session cache. */
-    private final ClientSessionContext clientSessionContext = new ClientSessionContext();
+    private final ClientSessionContext clientSessionContext;
 
     /** Server session cache. */
-    private final ServerSessionContext serverSessionContext = new ServerSessionContext();
+    private final ServerSessionContext serverSessionContext;
 
     protected SSLParameters sslParameters;
 
     public SSLContextImpl() {
-        super();
+        clientSessionContext = new ClientSessionContext();
+        serverSessionContext = new ServerSessionContext();
+    }
+    /**
+     * Constuctor for the DefaultSSLContextImpl.
+     * @param dummy is null, used to distinguish this case from the
+     * public SSLContextImpl() constructor.
+     */
+    protected SSLContextImpl(DefaultSSLContextImpl dummy)
+            throws GeneralSecurityException, IOException {
+        synchronized (DefaultSSLContextImpl.class) {
+            if (DEFAULT_SSL_CONTEXT_IMPL == null) {
+                clientSessionContext = new ClientSessionContext();
+                serverSessionContext = new ServerSessionContext();
+                DEFAULT_SSL_CONTEXT_IMPL = (DefaultSSLContextImpl)this;
+            } else {
+                clientSessionContext = DEFAULT_SSL_CONTEXT_IMPL.engineGetClientSessionContext();
+                serverSessionContext = DEFAULT_SSL_CONTEXT_IMPL.engineGetServerSessionContext();
+            }
+            sslParameters = new SSLParameters(DEFAULT_SSL_CONTEXT_IMPL.getKeyManagers(),
+                                              DEFAULT_SSL_CONTEXT_IMPL.getTrustManagers(),
+                                              null,
+                                              clientSessionContext,
+                                              serverSessionContext);
+        }
     }
 
     /**
@@ -88,7 +115,7 @@
 
     public SSLSocketFactory engineGetSocketFactory() {
         if (sslParameters == null) {
-            throw new IllegalStateException("SSLContext is not initiallized.");
+            throw new IllegalStateException("SSLContext is not initialized.");
         }
         return new OpenSSLSocketFactoryImpl(sslParameters);
     }
@@ -96,7 +123,7 @@
     @Override
     public SSLServerSocketFactory engineGetServerSocketFactory() {
         if (sslParameters == null) {
-            throw new IllegalStateException("SSLContext is not initiallized.");
+            throw new IllegalStateException("SSLContext is not initialized.");
         }
         return new OpenSSLServerSocketFactoryImpl(sslParameters);
     }
@@ -104,18 +131,21 @@
     @Override
     public SSLEngine engineCreateSSLEngine(String host, int port) {
         if (sslParameters == null) {
-            throw new IllegalStateException("SSLContext is not initiallized.");
+            throw new IllegalStateException("SSLContext is not initialized.");
         }
-        return new SSLEngineImpl(host, port,
-                (SSLParameters) sslParameters.clone());
+        SSLParameters p = (SSLParameters) sslParameters.clone();
+        p.setUseClientMode(false);
+        return new SSLEngineImpl(host, port, p);
     }
 
     @Override
     public SSLEngine engineCreateSSLEngine() {
         if (sslParameters == null) {
-            throw new IllegalStateException("SSLContext is not initiallized.");
+            throw new IllegalStateException("SSLContext is not initialized.");
         }
-        return new SSLEngineImpl((SSLParameters) sslParameters.clone());
+        SSLParameters p = (SSLParameters) sslParameters.clone();
+        p.setUseClientMode(false);
+        return new SSLEngineImpl(p);
     }
 
     @Override
@@ -127,4 +157,42 @@
     public ClientSessionContext engineGetClientSessionContext() {
         return clientSessionContext;
     }
+
+    @Override
+    public javax.net.ssl.SSLParameters engineGetDefaultSSLParameters() {
+        return createSSLParameters(false);
+    }
+
+    @Override
+    public javax.net.ssl.SSLParameters engineGetSupportedSSLParameters() {
+        return createSSLParameters(true);
+    }
+
+    private SSLParameters createSSLParameters (boolean supported) {
+        try {
+            SSLSocket s = (SSLSocket) engineGetSocketFactory().createSocket();
+            javax.net.ssl.SSLParameters p = new javax.net.ssl.SSLParameters();
+            String[] cipherSuites;
+            String[] protocols;
+            if (supported) {
+                cipherSuites = s.getSupportedCipherSuites();
+                protocols    = s.getSupportedProtocols();
+            } else {
+                cipherSuites = s.getEnabledCipherSuites();
+                protocols    = s.getEnabledProtocols();
+            }
+            p.setCipherSuites(cipherSuites);
+            p.setProtocols(protocols);
+            p.setNeedClientAuth(s.getNeedClientAuth());
+            p.setWantClientAuth(s.getWantClientAuth());
+            return p;
+        } catch (IOException e) {
+            /*
+             * SSLContext.getDefaultSSLParameters specifies to throw
+             * UnsupportedOperationException if there is a problem getting the
+             * parameters
+             */
+            throw new UnsupportedOperationException("Could not access supported SSL parameters");
+        }
+    }
 }
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java
index 4b2dd8d..f66b82f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java
@@ -17,19 +17,19 @@
 
 package org.apache.harmony.xnet.provider.jsse;
 
-import org.apache.harmony.xnet.provider.jsse.AlertException;
-import org.apache.harmony.xnet.provider.jsse.SSLSessionImpl;
-import org.apache.harmony.xnet.provider.jsse.SSLEngineDataStream;
 
 import java.io.IOException;
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 import java.nio.ReadOnlyBufferException;
 import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLHandshakeException;
 import javax.net.ssl.SSLEngineResult;
 import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLHandshakeException;
 import javax.net.ssl.SSLSession;
+import org.apache.harmony.xnet.provider.jsse.AlertException;
+import org.apache.harmony.xnet.provider.jsse.SSLEngineDataStream;
+import org.apache.harmony.xnet.provider.jsse.SSLSessionImpl;
 
 /**
  * Implementation of SSLEngine.
@@ -83,21 +83,11 @@
     // logger
     private Logger.Stream logger = Logger.getStream("engine");
 
-    /**
-     * Ctor
-     * @param   sslParameters:  SSLParameters
-     */
     protected SSLEngineImpl(SSLParameters sslParameters) {
         super();
         this.sslParameters = sslParameters;
     }
 
-    /**
-     * Ctor
-     * @param   host:   String
-     * @param   port:   int
-     * @param   sslParameters:  SSLParameters
-     */
     protected SSLEngineImpl(String host, int port, SSLParameters sslParameters) {
         super(host, port);
         this.sslParameters = sslParameters;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java
index dd94ea9..02a1fe5 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParameters.java
@@ -25,19 +25,13 @@
 import java.security.SecureRandom;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLException;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509KeyManager;
 import javax.net.ssl.X509TrustManager;
 
-import org.apache.harmony.security.provider.cert.X509CertImpl;
-
 /**
  * The instances of this class incapsulate all the info
  * about enabled cipher suites and protocols,
@@ -46,9 +40,7 @@
  * and controls whether new SSL sessions may be established by this
  * socket or not.
  */
-// BEGIN android-changed
 public class SSLParameters implements Cloneable {
-// END android-changed
 
     // default source of authentication keys
     private static X509KeyManager defaultKeyManager;
@@ -221,8 +213,11 @@
     protected static SSLParameters getDefault() throws KeyManagementException {
         if (defaultParameters == null) {
 // BEGIN android-changed
-            defaultParameters = new SSLParameters(null, null, null,
-                new ClientSessionContext(), new ServerSessionContext());
+            defaultParameters = new SSLParameters(null,
+                                                  null,
+                                                  null,
+                                                  new ClientSessionContext(),
+                                                  new ServerSessionContext());
 // END android-changed
         }
         return (SSLParameters) defaultParameters.clone();
@@ -310,14 +305,17 @@
      */
     protected void setEnabledCipherSuites(String[] suites) {
         if (suites == null) {
-            throw new IllegalArgumentException("Provided parameter is null");
+            throw new IllegalArgumentException("suites == null");
         }
         CipherSuite[] cipherSuites = new CipherSuite[suites.length];
         for (int i=0; i<suites.length; i++) {
-            cipherSuites[i] = CipherSuite.getByName(suites[i]);
+            String suite = suites[i];
+            if (suite == null) {
+                throw new IllegalArgumentException("suites[" + i + "] == null");
+            }
+            cipherSuites[i] = CipherSuite.getByName(suite);
             if (cipherSuites[i] == null || !cipherSuites[i].supported) {
-                throw new IllegalArgumentException(suites[i] +
-                        " is not supported.");
+                throw new IllegalArgumentException(suite + " is not supported.");
             }
         }
         enabledCipherSuites = cipherSuites;
@@ -337,12 +335,15 @@
      */
     protected void setEnabledProtocols(String[] protocols) {
         if (protocols == null) {
-            throw new IllegalArgumentException("Provided parameter is null");
+            throw new IllegalArgumentException("protocols == null");
         }
         for (int i=0; i<protocols.length; i++) {
-            if (!ProtocolVersion.isSupported(protocols[i])) {
-                throw new IllegalArgumentException("Protocol " + protocols[i] +
-                        " is not supported.");
+            String protocol = protocols[i];
+            if (protocol == null) {
+                throw new IllegalArgumentException("protocols[" + i + "] == null");
+            }
+            if (!ProtocolVersion.isSupported(protocol)) {
+                throw new IllegalArgumentException("Protocol " + protocol + " is not supported.");
             }
         }
         enabledProtocols = protocols;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
index 0352ef6..cb21be4 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
@@ -46,8 +46,7 @@
     protected void sessionRemoved(SSLSession session) {}
 
     @Override
-    public SSLSession getSession(byte[] sessionId) 
-    {
+    public SSLSession getSession(byte[] sessionId) {
         SSLSession session = super.getSession(sessionId);
         if (session != null) {
             return session;
diff --git a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
index 21489a2..b91c8e6 100644
--- a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
+++ b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
@@ -1421,6 +1421,11 @@
         JNI_TRACE("ssl=%p info_callback env error", ssl);
         return;
     }
+    if (env->ExceptionCheck()) {
+        JNI_TRACE("ssl=%p info_callback already pending exception", ssl);
+        return;
+    }
+
     jobject sslHandshakeCallbacks = appData->sslHandshakeCallbacks;
 
     jclass cls = env->GetObjectClass(sslHandshakeCallbacks);
diff --git a/luni/src/test/java/javax/net/ssl/AllTests.java b/luni/src/test/java/javax/net/ssl/AllTests.java
index 740b788..7638404 100644
--- a/luni/src/test/java/javax/net/ssl/AllTests.java
+++ b/luni/src/test/java/javax/net/ssl/AllTests.java
@@ -22,9 +22,11 @@
 public class AllTests {
     public static final Test suite() {
         TestSuite suite = new TestSuite();
-        suite.addTestSuite(SSLSocketFactoryTest.class);
+        suite.addTestSuite(SSLParametersTest.class);
         suite.addTestSuite(SSLContextTest.class);
+        suite.addTestSuite(SSLSocketFactoryTest.class);
         suite.addTestSuite(SSLSocketTest.class);
+        suite.addTestSuite(SSLEngineTest.class);
         suite.addTestSuite(SSLSessionTest.class);
         suite.addTestSuite(SSLSessionContextTest.class);
         return suite;
diff --git a/luni/src/test/java/javax/net/ssl/SSLContextTest.java b/luni/src/test/java/javax/net/ssl/SSLContextTest.java
index df4d556..f68b21f 100644
--- a/luni/src/test/java/javax/net/ssl/SSLContextTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLContextTest.java
@@ -16,6 +16,7 @@
 
 package javax.net.ssl;
 
+import java.security.KeyManagementException;
 import java.security.Provider;
 import javax.net.ServerSocketFactory;
 import javax.net.SocketFactory;
@@ -23,19 +24,45 @@
 
 public class SSLContextTest extends TestCase {
 
+    public void test_SSLContext_getDefault() throws Exception {
+        SSLContext sslContext = SSLContext.getDefault();
+        assertNotNull(sslContext);
+        try {
+            sslContext.init(null, null, null);
+        } catch (KeyManagementException expected) {
+        }
+    }
+
+    public void test_SSLContext_setDefault() throws Exception {
+        try {
+            SSLContext.setDefault(null);
+        } catch (NullPointerException expected) {
+        }
+
+        SSLContext defaultContext = SSLContext.getDefault();
+        for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+            SSLContext oldContext = SSLContext.getDefault();
+            assertNotNull(oldContext);
+            SSLContext newContext = SSLContext.getInstance(protocol);
+            assertNotNull(newContext);
+            assertNotSame(oldContext, newContext);
+            SSLContext.setDefault(newContext);
+            assertSame(newContext, SSLContext.getDefault());
+        }
+        SSLContext.setDefault(defaultContext);
+    }
+
     public void test_SSLContext_getInstance() throws Exception {
         try {
             SSLContext.getInstance(null);
             fail();
         } catch (NullPointerException expected) {
         }
-        assertNotNull(SSLContext.getInstance("SSL"));
-        assertNotNull(SSLContext.getInstance("SSLv3"));
-        assertNotNull(SSLContext.getInstance("TLS"));
-        assertNotNull(SSLContext.getInstance("TLSv1"));
-
-        assertNotSame(SSLContext.getInstance("TLS"),
-                      SSLContext.getInstance("TLS"));
+        for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+            assertNotNull(SSLContext.getInstance(protocol));
+            assertNotSame(SSLContext.getInstance(protocol),
+                          SSLContext.getInstance(protocol));
+        }
 
         try {
             SSLContext.getInstance(null, (String) null);
@@ -47,10 +74,12 @@
             fail();
         } catch (IllegalArgumentException expected) {
         }
-        try {
-            SSLContext.getInstance("TLS", (String) null);
-            fail();
-        } catch (IllegalArgumentException expected) {
+        for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+            try {
+                SSLContext.getInstance(protocol, (String) null);
+                fail();
+            } catch (IllegalArgumentException expected) {
+            }
         }
         try {
             SSLContext.getInstance(null, TestSSLContext.PROVIDER_NAME);
@@ -60,98 +89,197 @@
     }
 
     public void test_SSLContext_getProtocol() throws Exception {
-        assertProtocolExistsForName("SSL");
-        assertProtocolExistsForName("TLS");
-    }
-
-    private void assertProtocolExistsForName(String protocolName) throws Exception {
-        String protocol = SSLContext.getInstance(protocolName).getProtocol();
-        assertNotNull(protocol);
-        assertEquals(protocolName, protocol);
+        for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+            String protocolName = SSLContext.getInstance(protocol).getProtocol();
+            assertNotNull(protocolName);
+            assertTrue(protocol.startsWith(protocolName));
+        }
     }
 
     public void test_SSLContext_getProvider() throws Exception {
-        Provider provider = SSLContext.getInstance("TLS").getProvider();
+        Provider provider = SSLContext.getDefault().getProvider();
         assertNotNull(provider);
         assertEquals(TestSSLContext.PROVIDER_NAME, provider.getName());
     }
 
     public void test_SSLContext_init() throws Exception {
-        SSLContext sslContext = SSLContext.getInstance("TLS");
-        sslContext.init(null, null, null);
+        for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+            SSLContext sslContext = SSLContext.getInstance(protocol);
+            if (protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                try {
+                    sslContext.init(null, null, null);
+                } catch (KeyManagementException expected) {
+                }
+            } else {
+                sslContext.init(null, null, null);
+            }
+        }
     }
 
     public void test_SSLContext_getSocketFactory() throws Exception {
-        try {
-            SSLContext sslContext = SSLContext.getInstance("TLS");
-            sslContext.getSocketFactory();
-            fail();
-        } catch (IllegalStateException expected) {
+        for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+            if (protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                SSLContext.getInstance(protocol).getSocketFactory();
+            } else {
+                try {
+                    SSLContext.getInstance(protocol).getSocketFactory();
+                    fail();
+                } catch (IllegalStateException expected) {
+                }
+            }
+
+            SSLContext sslContext = SSLContext.getInstance(protocol);
+            if (!protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                sslContext.init(null, null, null);
+            }
+            SocketFactory sf = sslContext.getSocketFactory();
+            assertNotNull(sf);
+            assertTrue(SSLSocketFactory.class.isAssignableFrom(sf.getClass()));
         }
-        SSLContext sslContext = SSLContext.getInstance("TLS");
-        sslContext.init(null, null, null);
-        SocketFactory sf = sslContext.getSocketFactory();
-        assertNotNull(sf);
-        assertTrue(SSLSocketFactory.class.isAssignableFrom(sf.getClass()));
     }
 
     public void test_SSLContext_getServerSocketFactory() throws Exception {
-        try {
-            SSLContext sslContext = SSLContext.getInstance("TLS");
-            sslContext.getServerSocketFactory();
-            fail();
-        } catch (IllegalStateException expected) {
+        for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+            if (protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                SSLContext.getInstance(protocol).getServerSocketFactory();
+            } else {
+                try {
+                    SSLContext.getInstance(protocol).getServerSocketFactory();
+                    fail();
+                } catch (IllegalStateException expected) {
+                }
+            }
+
+            SSLContext sslContext = SSLContext.getInstance(protocol);
+            if (!protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                sslContext.init(null, null, null);
+            }
+            ServerSocketFactory ssf = sslContext.getServerSocketFactory();
+            assertNotNull(ssf);
+            assertTrue(SSLServerSocketFactory.class.isAssignableFrom(ssf.getClass()));
         }
-        SSLContext sslContext = SSLContext.getInstance("TLS");
-        sslContext.init(null, null, null);
-        ServerSocketFactory ssf = sslContext.getServerSocketFactory();
-        assertNotNull(ssf);
-        assertTrue(SSLServerSocketFactory.class.isAssignableFrom(ssf.getClass()));
     }
 
     public void test_SSLContext_createSSLEngine() throws Exception {
-        try {
-            SSLContext sslContext = SSLContext.getInstance("TLS");
-            sslContext.createSSLEngine();
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        try {
-            SSLContext sslContext = SSLContext.getInstance("TLS");
-            sslContext.createSSLEngine(null, -1);
-            fail();
-        } catch (IllegalStateException expected) {
-        }
-        {
-            SSLContext sslContext = SSLContext.getInstance("TLS");
-            sslContext.init(null, null, null);
-            SSLEngine se = sslContext.createSSLEngine();
-            assertNotNull(se);
-        }
-        {
-            SSLContext sslContext = SSLContext.getInstance("TLS");
-            sslContext.init(null, null, null);
-            SSLEngine se = sslContext.createSSLEngine(null, -1);
-            assertNotNull(se);
+        for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+
+            if (protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                SSLContext.getInstance(protocol).createSSLEngine();
+            } else {
+                try {
+                    SSLContext.getInstance(protocol).createSSLEngine();
+                    fail();
+                } catch (IllegalStateException expected) {
+                }
+            }
+
+            if (protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                SSLContext.getInstance(protocol).createSSLEngine(null, -1);
+            } else {
+                try {
+                    SSLContext.getInstance(protocol).createSSLEngine(null, -1);
+                    fail();
+                } catch (IllegalStateException expected) {
+                }
+            }
+
+            {
+                SSLContext sslContext = SSLContext.getInstance(protocol);
+                if (!protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                    sslContext.init(null, null, null);
+                }
+                SSLEngine se = sslContext.createSSLEngine();
+                assertNotNull(se);
+            }
+
+            {
+                SSLContext sslContext = SSLContext.getInstance(protocol);
+                if (!protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                    sslContext.init(null, null, null);
+                }
+                SSLEngine se = sslContext.createSSLEngine(null, -1);
+                assertNotNull(se);
+            }
         }
     }
 
     public void test_SSLContext_getServerSessionContext() throws Exception {
-        SSLContext sslContext = SSLContext.getInstance("TLS");
-        SSLSessionContext sessionContext = sslContext.getServerSessionContext();
-        assertNotNull(sessionContext);
+        for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+            SSLContext sslContext = SSLContext.getInstance(protocol);
+            SSLSessionContext sessionContext = sslContext.getServerSessionContext();
+            assertNotNull(sessionContext);
 
-        assertNotSame(SSLContext.getInstance("TLS").getServerSessionContext(),
-                      sessionContext);
+            if (protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                assertSame(SSLContext.getInstance(protocol).getServerSessionContext(),
+                           sessionContext);
+            } else {
+                assertNotSame(SSLContext.getInstance(protocol).getServerSessionContext(),
+                              sessionContext);
+            }
+        }
     }
 
     public void test_SSLContext_getClientSessionContext() throws Exception {
-        SSLContext sslContext = SSLContext.getInstance("TLS");
-        SSLSessionContext sessionContext = sslContext.getClientSessionContext();
-        assertNotNull(sessionContext);
+        for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+            SSLContext sslContext = SSLContext.getInstance(protocol);
+            SSLSessionContext sessionContext = sslContext.getClientSessionContext();
+            assertNotNull(sessionContext);
 
-        assertNotSame(SSLContext.getInstance("TLS").getClientSessionContext(),
-                      sessionContext);
+            if (protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                assertSame(SSLContext.getInstance(protocol).getClientSessionContext(),
+                           sessionContext);
+            } else {
+                assertNotSame(SSLContext.getInstance(protocol).getClientSessionContext(),
+                              sessionContext);
+            }
+        }
+    }
+
+    public void test_SSLContext_getDefaultSSLParameters() throws Exception {
+        for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+            SSLContext sslContext = SSLContext.getInstance(protocol);
+            if (!protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                sslContext.init(null, null, null);
+            }
+
+            SSLParameters p = sslContext.getDefaultSSLParameters();
+            assertNotNull(p);
+
+            String[] cipherSuites = p.getCipherSuites();
+            assertNotNull(cipherSuites);
+            StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
+
+            String[] protocols = p.getProtocols();
+            assertNotNull(protocols);
+            StandardNames.assertValidCipherSuites(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
+
+            assertFalse(p.getWantClientAuth());
+            assertFalse(p.getNeedClientAuth());
+        }
+    }
+
+    public void test_SSLContext_getSupportedSSLParameters() throws Exception {
+        for (String protocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
+            SSLContext sslContext = SSLContext.getInstance(protocol);
+            if (!protocol.equals(StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT)) {
+                sslContext.init(null, null, null);
+            }
+
+            SSLParameters p = sslContext.getSupportedSSLParameters();
+            assertNotNull(p);
+
+            String[] cipherSuites = p.getCipherSuites();
+            assertNotNull(cipherSuites);
+            StandardNames.assertSupportedCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
+
+            String[] protocols = p.getProtocols();
+            assertNotNull(protocols);
+            StandardNames.assertSupportedProtocols(StandardNames.SSL_SOCKET_PROTOCOLS,
+                                                   protocols);
+
+            assertFalse(p.getWantClientAuth());
+            assertFalse(p.getNeedClientAuth());
+        }
     }
 
     public void test_SSLContextTest_TestSSLContext_create() {
diff --git a/luni/src/test/java/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/javax/net/ssl/SSLEngineTest.java
new file mode 100644
index 0000000..75f04a0
--- /dev/null
+++ b/luni/src/test/java/javax/net/ssl/SSLEngineTest.java
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2010 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 javax.net.ssl;
+
+import dalvik.annotation.KnownFailure;
+import java.util.Arrays;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import junit.framework.TestCase;
+
+public class SSLEngineTest extends TestCase {
+
+    public void assertConnected(TestSSLEnginePair e) {
+        assertConnected(e.client, e.server);
+    }
+
+    public void assertNotConnected(TestSSLEnginePair e) {
+        assertNotConnected(e.client, e.server);
+    }
+
+    public void assertConnected(SSLEngine a, SSLEngine b) {
+        assertTrue(connected(a, b));
+    }
+
+    public void assertNotConnected(SSLEngine a, SSLEngine b) {
+        assertFalse(connected(a, b));
+    }
+
+    public boolean connected(SSLEngine a, SSLEngine b) {
+        return (a.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING
+                && b.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING
+                && a.getSession() != null
+                && b.getSession() != null
+                && !a.isInboundDone()
+                && !b.isInboundDone()
+                && !a.isOutboundDone()
+                && !b.isOutboundDone());
+    }
+
+    public void test_SSLEngine_getSupportedCipherSuites_names() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+        SSLEngine e = c.sslContext.createSSLEngine();
+        String[] cipherSuites = e.getSupportedCipherSuites();
+        StandardNames.assertSupportedCipherSuites(StandardNames.CIPHER_SUITES_SSLENGINE,
+                                                  cipherSuites);
+        assertNotSame(cipherSuites, e.getSupportedCipherSuites());
+    }
+
+    @KnownFailure("No *_WITH_NULL_* ciphers work because of 'Invalid transformation: null'")
+    public void test_SSLEngine_getSupportedCipherSuites_connect() throws Exception {
+        String[] cipherSuites
+                = SSLContext.getDefault().createSSLEngine().getSupportedCipherSuites();
+        for (String cipherSuite : cipherSuites) {
+            /*
+             * Kerberos cipher suites require external setup. See "Kerberos Requirements" in
+             * https://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#KRBRequire
+             */
+            if (cipherSuite.startsWith("TLS_KRB5_")) {
+                continue;
+            }
+            System.out.println("Trying to connect cipher suite " + cipherSuite);
+            final String[] cipherSuiteArray = new String[] { cipherSuite };
+            assertConnected(TestSSLEnginePair.create(new TestSSLEnginePair.Hooks() {
+                @Override
+                void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
+                    client.setEnabledCipherSuites(cipherSuiteArray);
+                    server.setEnabledCipherSuites(cipherSuiteArray);
+                }
+            }));
+        }
+    }
+
+    public void test_SSLEngine_getEnabledCipherSuites() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+        SSLEngine e = c.sslContext.createSSLEngine();
+        String[] cipherSuites = e.getEnabledCipherSuites();
+        StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES_SSLENGINE,
+                                              cipherSuites);
+        assertNotSame(cipherSuites, e.getEnabledCipherSuites());
+    }
+
+    public void test_SSLEngine_setEnabledCipherSuites() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+        SSLEngine e = c.sslContext.createSSLEngine();
+
+        try {
+            e.setEnabledCipherSuites(null);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            e.setEnabledCipherSuites(new String[1]);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            e.setEnabledCipherSuites(new String[] { "Bogus" } );
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+
+        e.setEnabledCipherSuites(new String[0]);
+        e.setEnabledCipherSuites(e.getEnabledCipherSuites());
+        e.setEnabledCipherSuites(e.getSupportedCipherSuites());
+    }
+
+    public void test_SSLEngine_getSupportedProtocols() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+        SSLEngine e = c.sslContext.createSSLEngine();
+        String[] protocols = e.getSupportedProtocols();
+        StandardNames.assertSupportedProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
+        assertNotSame(protocols, e.getSupportedProtocols());
+    }
+
+    public void test_SSLEngine_getEnabledProtocols() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+        SSLEngine e = c.sslContext.createSSLEngine();
+        String[] protocols = e.getEnabledProtocols();
+        StandardNames.assertValidProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
+        assertNotSame(protocols, e.getEnabledProtocols());
+    }
+
+    public void test_SSLEngine_setEnabledProtocols() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+        SSLEngine e = c.sslContext.createSSLEngine();
+
+        try {
+            e.setEnabledProtocols(null);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            e.setEnabledProtocols(new String[1]);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            e.setEnabledProtocols(new String[] { "Bogus" } );
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        e.setEnabledProtocols(new String[0]);
+        e.setEnabledProtocols(e.getEnabledProtocols());
+        e.setEnabledProtocols(e.getSupportedProtocols());
+    }
+
+    public void test_SSLEngine_getSession() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+        SSLEngine e = c.sslContext.createSSLEngine();
+        SSLSession session = e.getSession();
+        assertNotNull(session);
+        assertFalse(session.isValid());
+    }
+
+    public void test_SSLEngine_beginHandshake() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+
+        try {
+            c.sslContext.createSSLEngine().beginHandshake();
+            fail();
+        } catch (IllegalStateException expected) {
+        }
+
+        assertConnected(TestSSLEnginePair.create(null));
+    }
+
+    @KnownFailure("NO SERVER CERTIFICATE FOUND")
+    public void test_SSLEngine_beginHandshake_noKeyStore() throws Exception {
+        TestSSLContext c = TestSSLContext.create(null, null);
+        try {
+            // TODO Fix KnownFailure AlertException "NO SERVER CERTIFICATE FOUND"
+            // ServerHandshakeImpl.selectSuite should not select a suite without a required cert
+            TestSSLEnginePair.connect(c, c, null);
+            fail();
+        } catch (SSLHandshakeException expected) {
+        }
+    }
+
+    public void test_SSLEngine_beginHandshake_noClientCertificate() throws Exception {
+        TestSSLContext serverContext = TestSSLContext.create();
+        TestSSLContext clientContext = TestSSLContext.createClient(serverContext);
+        SSLEngine[] engines = TestSSLEnginePair.connect(clientContext, serverContext, null);
+        assertConnected(engines[0], engines[1]);
+    }
+
+    public void test_SSLEngine_getUseClientMode() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+        assertFalse(c.sslContext.createSSLEngine().getUseClientMode());
+        assertFalse(c.sslContext.createSSLEngine(null, -1).getUseClientMode());
+    }
+
+    @KnownFailure("SSLHandshakeException instead assertNotConnected")
+    public void test_SSLEngine_setUseClientMode() throws Exception {
+        // client is client, server is server
+        assertConnected(test_SSLEngine_setUseClientMode(true, false));
+
+        // client is server, server is client
+        assertConnected(test_SSLEngine_setUseClientMode(false, true));
+
+        // both are client
+        assertNotConnected(test_SSLEngine_setUseClientMode(true, true));
+
+        // both are server
+        assertNotConnected(test_SSLEngine_setUseClientMode(false, false));
+    }
+
+    private TestSSLEnginePair test_SSLEngine_setUseClientMode(final boolean clientClientMode,
+                                                              final boolean serverClientMode)
+            throws Exception {
+        return TestSSLEnginePair.create(new TestSSLEnginePair.Hooks() {
+            @Override
+            void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
+                client.setUseClientMode(clientClientMode);
+                server.setUseClientMode(serverClientMode);
+            }
+        });
+    }
+
+    @KnownFailure("init - invalid private key")
+    public void test_SSLEngine_clientAuth() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+        SSLEngine e = c.sslContext.createSSLEngine();
+
+        assertFalse(e.getWantClientAuth());
+        assertFalse(e.getNeedClientAuth());
+
+        // confirm turning one on by itself
+        e.setWantClientAuth(true);
+        assertTrue(e.getWantClientAuth());
+        assertFalse(e.getNeedClientAuth());
+
+        // confirm turning setting on toggles the other
+        e.setNeedClientAuth(true);
+        assertFalse(e.getWantClientAuth());
+        assertTrue(e.getNeedClientAuth());
+
+        // confirm toggling back
+        e.setWantClientAuth(true);
+        assertTrue(e.getWantClientAuth());
+        assertFalse(e.getNeedClientAuth());
+
+        // TODO Fix KnownFailure "init - invalid private key"
+        TestSSLEnginePair p = TestSSLEnginePair.create(new TestSSLEnginePair.Hooks() {
+            @Override
+            void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
+                server.setWantClientAuth(true);
+            }
+        });
+        assertConnected(p);
+        assertNotNull(p.client.getSession().getLocalCertificates());
+        assertEquals(1, p.client.getSession().getLocalCertificates().length);
+    }
+
+    public void test_SSLEngine_getEnableSessionCreation() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+        SSLEngine e = c.sslContext.createSSLEngine();
+        assertTrue(e.getEnableSessionCreation());
+    }
+
+    @KnownFailure("SSLException instead assertNotConnected")
+    public void test_SSLEngine_setEnableSessionCreation_server() throws Exception {
+        TestSSLEnginePair p = TestSSLEnginePair.create(new TestSSLEnginePair.Hooks() {
+            @Override
+            void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
+                server.setEnableSessionCreation(false);
+            }
+        });
+        assertNotConnected(p);
+    }
+
+    @KnownFailure("AlertException instead of SSLException")
+    public void test_SSLEngine_setEnableSessionCreation_client() throws Exception {
+        try {
+            TestSSLEnginePair.create(new TestSSLEnginePair.Hooks() {
+                @Override
+                void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
+                    client.setEnableSessionCreation(false);
+                }
+            });
+            fail();
+        } catch (SSLException expected) {
+        }
+    }
+
+    public void test_SSLEngine_getSSLParameters() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+        SSLEngine e = c.sslContext.createSSLEngine();
+
+        SSLParameters p = e.getSSLParameters();
+        assertNotNull(p);
+
+        String[] cipherSuites = p.getCipherSuites();
+        StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES_SSLENGINE,
+                                              cipherSuites);
+        assertNotSame(cipherSuites, e.getEnabledCipherSuites());
+        assertEquals(Arrays.asList(cipherSuites), Arrays.asList(e.getEnabledCipherSuites()));
+
+        String[] protocols = p.getProtocols();
+        StandardNames.assertValidProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
+        assertNotSame(protocols, e.getEnabledProtocols());
+        assertEquals(Arrays.asList(protocols), Arrays.asList(e.getEnabledProtocols()));
+
+        assertEquals(p.getWantClientAuth(), e.getWantClientAuth());
+        assertEquals(p.getNeedClientAuth(), e.getNeedClientAuth());
+    }
+
+    public void test_SSLEngine_setSSLParameters() throws Exception {
+        TestSSLContext c = TestSSLContext.create();
+        SSLEngine e = c.sslContext.createSSLEngine();
+        String[] defaultCipherSuites = e.getEnabledCipherSuites();
+        String[] defaultProtocols = e.getEnabledProtocols();
+        String[] supportedCipherSuites = e.getSupportedCipherSuites();
+        String[] supportedProtocols = e.getSupportedProtocols();
+
+        {
+            SSLParameters p = new SSLParameters();
+            e.setSSLParameters(p);
+            assertEquals(Arrays.asList(defaultCipherSuites),
+                         Arrays.asList(e.getEnabledCipherSuites()));
+            assertEquals(Arrays.asList(defaultProtocols),
+                         Arrays.asList(e.getEnabledProtocols()));
+        }
+
+        {
+            SSLParameters p = new SSLParameters(supportedCipherSuites,
+                                                supportedProtocols);
+            e.setSSLParameters(p);
+            assertEquals(Arrays.asList(supportedCipherSuites),
+                         Arrays.asList(e.getEnabledCipherSuites()));
+            assertEquals(Arrays.asList(supportedProtocols),
+                         Arrays.asList(e.getEnabledProtocols()));
+        }
+        {
+            SSLParameters p = new SSLParameters();
+
+            p.setNeedClientAuth(true);
+            assertFalse(e.getNeedClientAuth());
+            assertFalse(e.getWantClientAuth());
+            e.setSSLParameters(p);
+            assertTrue(e.getNeedClientAuth());
+            assertFalse(e.getWantClientAuth());
+
+            p.setWantClientAuth(true);
+            assertTrue(e.getNeedClientAuth());
+            assertFalse(e.getWantClientAuth());
+            e.setSSLParameters(p);
+            assertFalse(e.getNeedClientAuth());
+            assertTrue(e.getWantClientAuth());
+
+            p.setWantClientAuth(false);
+            assertFalse(e.getNeedClientAuth());
+            assertTrue(e.getWantClientAuth());
+            e.setSSLParameters(p);
+            assertFalse(e.getNeedClientAuth());
+            assertFalse(e.getWantClientAuth());
+        }
+    }
+
+    public void test_TestSSLEnginePair_create() throws Exception {
+        TestSSLEnginePair test = TestSSLEnginePair.create(null);
+        assertNotNull(test.c);
+        assertNotNull(test.server);
+        assertNotNull(test.client);
+        assertConnected(test);
+    }
+}
diff --git a/luni/src/test/java/javax/net/ssl/SSLParametersTest.java b/luni/src/test/java/javax/net/ssl/SSLParametersTest.java
new file mode 100644
index 0000000..7259ba5
--- /dev/null
+++ b/luni/src/test/java/javax/net/ssl/SSLParametersTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2010 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 javax.net.ssl;
+
+import java.util.Arrays;
+import junit.framework.TestCase;
+
+public class SSLParametersTest extends TestCase {
+
+    public void test_SSLParameters_emptyConstructor() {
+        SSLParameters p = new SSLParameters();
+        assertNull(p.getCipherSuites());
+        assertNull(p.getProtocols());
+        assertFalse(p.getWantClientAuth());
+        assertFalse(p.getNeedClientAuth());
+    }
+
+    public void test_SSLParameters_cipherSuitesConstructor() {
+        String[] cipherSuites = new String[] { "foo", null, "bar" };
+        SSLParameters p = new SSLParameters(cipherSuites);
+        assertNotNull(p.getCipherSuites());
+        assertNotSame(cipherSuites, p.getCipherSuites());
+        assertEquals(Arrays.asList(cipherSuites), Arrays.asList(p.getCipherSuites()));
+        assertNull(p.getProtocols());
+        assertFalse(p.getWantClientAuth());
+        assertFalse(p.getNeedClientAuth());
+    }
+
+    public void test_SSLParameters_cpherSuitesProtocolsConstructor() {
+        String[] cipherSuites = new String[] { "foo", null, "bar" };
+        String[] protocols = new String[] { "baz", null, "qux" };
+        SSLParameters p = new SSLParameters(cipherSuites, protocols);
+        assertNotNull(p.getCipherSuites());
+        assertNotNull(p.getProtocols());
+        assertNotSame(cipherSuites, p.getCipherSuites());
+        assertNotSame(protocols, p.getProtocols());
+        assertEquals(Arrays.asList(cipherSuites), Arrays.asList(p.getCipherSuites()));
+        assertEquals(Arrays.asList(protocols), Arrays.asList(p.getProtocols()));
+        assertFalse(p.getWantClientAuth());
+        assertFalse(p.getNeedClientAuth());
+    }
+
+    public void test_SSLParameters_CipherSuites() {
+        SSLParameters p = new SSLParameters();
+        assertNull(p.getCipherSuites());
+
+        // confirm clone on input
+        String[] cipherSuites = new String[] { "fnord" };
+        String[] copy = cipherSuites.clone();
+        p.setCipherSuites(copy);
+        copy[0] = null;
+        assertEquals(Arrays.asList(cipherSuites), Arrays.asList(p.getCipherSuites()));
+
+        // confirm clone on output
+        assertNotSame(p.getCipherSuites(), p.getCipherSuites());
+    }
+
+    public void test_SSLParameters_Protocols() {
+        SSLParameters p = new SSLParameters();
+        assertNull(p.getProtocols());
+
+        // confirm clone on input
+        String[] protocols = new String[] { "fnord" };
+        String[] copy = protocols.clone();
+        p.setProtocols(copy);
+        copy[0] = null;
+        assertEquals(Arrays.asList(protocols), Arrays.asList(p.getProtocols()));
+
+        // confirm clone on output
+        assertNotSame(p.getProtocols(), p.getProtocols());
+    }
+
+    public void test_SSLParameters_ClientAuth() {
+        SSLParameters p = new SSLParameters();
+        assertFalse(p.getWantClientAuth());
+        assertFalse(p.getNeedClientAuth());
+
+        // confirm turning one on by itself
+        p.setWantClientAuth(true);
+        assertTrue(p.getWantClientAuth());
+        assertFalse(p.getNeedClientAuth());
+
+        // confirm turning setting on toggles the other
+        p.setNeedClientAuth(true);
+        assertFalse(p.getWantClientAuth());
+        assertTrue(p.getNeedClientAuth());
+
+        // confirm toggling back
+        p.setWantClientAuth(true);
+        assertTrue(p.getWantClientAuth());
+        assertFalse(p.getNeedClientAuth());
+    }
+}
diff --git a/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java b/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java
index ffa9bc0..7e2cbd0 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSessionContextTest.java
@@ -21,7 +21,6 @@
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.List;
 import junit.framework.TestCase;
 
 public class SSLSessionContextTest extends TestCase {
diff --git a/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java b/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java
index 6c7c99b..a91d07a 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSocketFactoryTest.java
@@ -16,14 +16,11 @@
 
 package javax.net.ssl;
 
-import java.net.Socket;
-import java.net.SocketException;
-import java.net.ServerSocket;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
-import java.util.Collections;
-import java.util.Set;
-import java.util.HashSet;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
 import javax.net.ServerSocketFactory;
 import javax.net.SocketFactory;
 import junit.framework.TestCase;
@@ -38,43 +35,15 @@
     public void test_SSLSocketFactory_getDefaultCipherSuites() {
         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
         String[] cipherSuites = sf.getDefaultCipherSuites();
-        assertNotNull(cipherSuites);
-        assertTrue(cipherSuites.length != 0);
-
-        // Make sure modifying the result is not observable
-        String savedCipherSuite = cipherSuites[0];
-        assertNotNull(savedCipherSuite);
-        cipherSuites[0] = null;
-        assertNotNull(sf.getSupportedCipherSuites()[0]);
-        cipherSuites[0] = savedCipherSuite;
-
-        // Make sure all cipherSuites names are expected
-        for (String cipherSuite : cipherSuites) {
-            assertTrue(StandardNames.CIPHER_SUITES.contains(cipherSuite));
-        }
+        StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
+        assertNotSame(cipherSuites, sf.getDefaultCipherSuites());
     }
 
     public void test_SSLSocketFactory_getSupportedCipherSuites() {
         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
         String[] cipherSuites = sf.getSupportedCipherSuites();
-        assertNotNull(cipherSuites);
-        assertTrue(cipherSuites.length != 0);
-
-        // Make sure modifying the result is not observable
-        String savedCipherSuite = cipherSuites[0];
-        assertNotNull(savedCipherSuite);
-        cipherSuites[0] = null;
-        assertNotNull(sf.getSupportedCipherSuites()[0]);
-        cipherSuites[0] = savedCipherSuite;
-
-        // Make sure all cipherSuites names are expected
-        Set remainingCipherSuites = new HashSet<String>(StandardNames.CIPHER_SUITES);
-        for (String cipherSuite : cipherSuites) {
-            assertTrue(remainingCipherSuites.remove(cipherSuite));
-        }
-        assertEquals(Collections.EMPTY_SET, remainingCipherSuites);
-
-        assertEquals(StandardNames.CIPHER_SUITES.size(), cipherSuites.length);
+        StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
+        assertNotSame(cipherSuites, sf.getSupportedCipherSuites());
     }
 
     public void test_SSLSocketFactory_createSocket() throws Exception {
diff --git a/luni/src/test/java/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/javax/net/ssl/SSLSocketTest.java
index a83035c..fae21bf 100644
--- a/luni/src/test/java/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/javax/net/ssl/SSLSocketTest.java
@@ -16,19 +16,12 @@
 
 package javax.net.ssl;
 
-import java.net.ServerSocket;
 import java.net.Socket;
 import java.net.SocketTimeoutException;
-import java.security.Key;
-import java.security.KeyStore;
 import java.security.Principal;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Set;
 import junit.framework.TestCase;
 
 public class SSLSocketTest extends TestCase {
@@ -37,25 +30,19 @@
         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
         SSLSocket ssl = (SSLSocket) sf.createSocket();
         String[] cipherSuites = ssl.getSupportedCipherSuites();
-        assertNotNull(cipherSuites);
-        assertTrue(cipherSuites.length != 0);
-        Set remainingCipherSuites = new HashSet<String>(StandardNames.CIPHER_SUITES);
-        for (String cipherSuite : cipherSuites) {
-            assertTrue(remainingCipherSuites.remove(cipherSuite));
-        }
-        assertEquals(Collections.EMPTY_SET, remainingCipherSuites);
-        assertEquals(StandardNames.CIPHER_SUITES.size(), cipherSuites.length);
+        StandardNames.assertSupportedCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
+        assertNotSame(cipherSuites, ssl.getSupportedCipherSuites());
     }
 
     public void test_SSLSocket_getSupportedCipherSuites_connect() throws Exception {
         TestSSLContext c = TestSSLContext.create();
         String[] cipherSuites = c.sslContext.getSocketFactory().getSupportedCipherSuites();
         for (String cipherSuite : cipherSuites) {
+            /*
+             * Kerberos cipher suites require external setup. See "Kerberos Requirements" in
+             * https://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#KRBRequire
+             */
             if (cipherSuite.startsWith("TLS_KRB5_")) {
-                /*
-                 * Kerberos cipher suites require external setup. See "Kerberos Requirements" in
-                 * https://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#KRBRequire
-                 */
                 continue;
             }
             // System.out.println("Trying to connect cipher suite " + cipherSuite);
@@ -68,20 +55,8 @@
         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
         SSLSocket ssl = (SSLSocket) sf.createSocket();
         String[] cipherSuites = ssl.getEnabledCipherSuites();
-        assertNotNull(cipherSuites);
-        assertTrue(cipherSuites.length != 0);
-
-        // Make sure modifying the result is not observable
-        String savedCipherSuite = cipherSuites[0];
-        assertNotNull(savedCipherSuite);
-        cipherSuites[0] = null;
-        assertNotNull(ssl.getEnabledCipherSuites()[0]);
-        cipherSuites[0] = savedCipherSuite;
-
-        // Make sure all cipherSuites names are expected
-        for (String cipherSuite : cipherSuites) {
-            assertTrue(StandardNames.CIPHER_SUITES.contains(cipherSuite));
-        }
+        StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
+        assertNotSame(cipherSuites, ssl.getEnabledCipherSuites());
     }
 
     public void test_SSLSocket_setEnabledCipherSuites() throws Exception {
@@ -113,40 +88,16 @@
         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
         SSLSocket ssl = (SSLSocket) sf.createSocket();
         String[] protocols = ssl.getSupportedProtocols();
-        assertNotNull(protocols);
-        assertTrue(protocols.length != 0);
-
-        // Make sure modifying the result is not observable
-        String savedProtocol = protocols[0];
-        assertNotNull(savedProtocol);
-        protocols[0] = null;
-        assertNotNull(ssl.getSupportedProtocols()[0]);
-        protocols[0] = savedProtocol;
-
-        // Make sure all protocol names are expected
-        for (String protocol : protocols) {
-            assertNotNull(StandardNames.SSL_SOCKET_PROTOCOLS.contains(protocol));
-        }
+        StandardNames.assertSupportedProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
+        assertNotSame(protocols, ssl.getSupportedProtocols());
     }
 
     public void test_SSLSocket_getEnabledProtocols() throws Exception {
         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
         SSLSocket ssl = (SSLSocket) sf.createSocket();
         String[] protocols = ssl.getEnabledProtocols();
-        assertNotNull(protocols);
-        assertTrue(protocols.length != 0);
-
-        // Make sure modifying the result is not observable
-        String savedProtocol = protocols[0];
-        assertNotNull(savedProtocol);
-        protocols[0] = null;
-        assertNotNull(ssl.getEnabledProtocols()[0]);
-        protocols[0] = savedProtocol;
-
-        // Make sure all protocol names are expected
-        for (String protocol : protocols) {
-            assertNotNull(StandardNames.SSL_SOCKET_PROTOCOLS.contains(protocol));
-        }
+        StandardNames.assertValidProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
+        assertNotSame(protocols, ssl.getEnabledProtocols());
     }
 
     public void test_SSLSocket_setEnabledProtocols() throws Exception {
@@ -299,9 +250,6 @@
                     assertNotNull(id);
                     assertEquals(32, id.length);
                     assertNotNull(c.sslContext.getClientSessionContext().getSession(id));
-                    if (!TestSSLContext.sslServerSocketSupportsSessionTickets()) {
-                        assertNotNull(c.sslContext.getServerSessionContext().getSession(id));
-                    }
 
                     assertNotNull(cipherSuite);
                     assertTrue(Arrays.asList(
@@ -344,6 +292,10 @@
         });
         client.startHandshake();
         thread.join();
+        if (!TestSSLContext.sslServerSocketSupportsSessionTickets()) {
+            assertNotNull(c.sslContext.getServerSessionContext().getSession(
+                    client.getSession().getId()));
+        }
         synchronized (handshakeCompletedListenerCalled) {
             while (!handshakeCompletedListenerCalled[0]) {
                 handshakeCompletedListenerCalled.wait();
@@ -555,7 +507,80 @@
         thread.join();
     }
 
-    public void test_SSLSocketTest_Test_create() {
+    public void test_SSLSocket_getSSLParameters() throws Exception {
+        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket ssl = (SSLSocket) sf.createSocket();
+
+        SSLParameters p = ssl.getSSLParameters();
+        assertNotNull(p);
+
+        String[] cipherSuites = p.getCipherSuites();
+        StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
+        assertNotSame(cipherSuites, ssl.getEnabledCipherSuites());
+        assertEquals(Arrays.asList(cipherSuites), Arrays.asList(ssl.getEnabledCipherSuites()));
+
+        String[] protocols = p.getProtocols();
+        StandardNames.assertValidProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
+        assertNotSame(protocols, ssl.getEnabledProtocols());
+        assertEquals(Arrays.asList(protocols), Arrays.asList(ssl.getEnabledProtocols()));
+
+        assertEquals(p.getWantClientAuth(), ssl.getWantClientAuth());
+        assertEquals(p.getNeedClientAuth(), ssl.getNeedClientAuth());
+    }
+
+    public void test_SSLSocket_setSSLParameters() throws Exception {
+        SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
+        SSLSocket ssl = (SSLSocket) sf.createSocket();
+        String[] defaultCipherSuites = ssl.getEnabledCipherSuites();
+        String[] defaultProtocols = ssl.getEnabledProtocols();
+        String[] supportedCipherSuites = ssl.getSupportedCipherSuites();
+        String[] supportedProtocols = ssl.getSupportedProtocols();
+
+        {
+            SSLParameters p = new SSLParameters();
+            ssl.setSSLParameters(p);
+            assertEquals(Arrays.asList(defaultCipherSuites),
+                         Arrays.asList(ssl.getEnabledCipherSuites()));
+            assertEquals(Arrays.asList(defaultProtocols),
+                         Arrays.asList(ssl.getEnabledProtocols()));
+        }
+
+        {
+            SSLParameters p = new SSLParameters(supportedCipherSuites,
+                                                supportedProtocols);
+            ssl.setSSLParameters(p);
+            assertEquals(Arrays.asList(supportedCipherSuites),
+                         Arrays.asList(ssl.getEnabledCipherSuites()));
+            assertEquals(Arrays.asList(supportedProtocols),
+                         Arrays.asList(ssl.getEnabledProtocols()));
+        }
+        {
+            SSLParameters p = new SSLParameters();
+
+            p.setNeedClientAuth(true);
+            assertFalse(ssl.getNeedClientAuth());
+            assertFalse(ssl.getWantClientAuth());
+            ssl.setSSLParameters(p);
+            assertTrue(ssl.getNeedClientAuth());
+            assertFalse(ssl.getWantClientAuth());
+
+            p.setWantClientAuth(true);
+            assertTrue(ssl.getNeedClientAuth());
+            assertFalse(ssl.getWantClientAuth());
+            ssl.setSSLParameters(p);
+            assertFalse(ssl.getNeedClientAuth());
+            assertTrue(ssl.getWantClientAuth());
+
+            p.setWantClientAuth(false);
+            assertFalse(ssl.getNeedClientAuth());
+            assertTrue(ssl.getWantClientAuth());
+            ssl.setSSLParameters(p);
+            assertFalse(ssl.getNeedClientAuth());
+            assertFalse(ssl.getWantClientAuth());
+        }
+    }
+
+    public void test_TestSSLSocketPair_create() {
         TestSSLSocketPair test = TestSSLSocketPair.create();
         assertNotNull(test.c);
         assertNotNull(test.server);
@@ -564,13 +589,15 @@
         assertTrue(test.client.isConnected());
         assertNotNull(test.server.getSession());
         assertNotNull(test.client.getSession());
+        assertTrue(test.server.getSession().isValid());
+        assertTrue(test.client.getSession().isValid());
     }
 
     /**
      * Not run by default by JUnit, but can be run by Vogar by
      * specifying it explictly (or with main method below)
      */
-    public void stress_test_SSLSocketTest_Test_create() {
+    public void stress_test_TestSSLSocketPair_create() {
         final boolean verbose = true;
         while (true) {
             TestSSLSocketPair test = TestSSLSocketPair.create();
@@ -584,6 +611,6 @@
     }
 
     public static final void main (String[] args) {
-        new SSLSocketTest().stress_test_SSLSocketTest_Test_create();
+        new SSLSocketTest().stress_test_TestSSLSocketPair_create();
     }
 }
diff --git a/luni/src/test/java/tests/api/javax/net/ssl/KeyStoreBuilderParametersTest.java b/luni/src/test/java/tests/api/javax/net/ssl/KeyStoreBuilderParametersTest.java
index acbbd30..8e2e093 100644
--- a/luni/src/test/java/tests/api/javax/net/ssl/KeyStoreBuilderParametersTest.java
+++ b/luni/src/test/java/tests/api/javax/net/ssl/KeyStoreBuilderParametersTest.java
@@ -75,16 +75,15 @@
     public void test_Constructor02() {
 
         //Null parameter
-        List<String> ls = null;
         try {
-            KeyStoreBuilderParameters ksp = new KeyStoreBuilderParameters(ls);
+            KeyStoreBuilderParameters ksp = new KeyStoreBuilderParameters(null);
             fail("NullPointerException should be thrown");
         } catch (NullPointerException npe) {
             //expected
         }
 
         //Empty parameter
-        List<String> lsEmpty = new ArrayList<String>();
+        List lsEmpty = new ArrayList<String>();
         try {
             KeyStoreBuilderParameters ksp = new KeyStoreBuilderParameters(lsEmpty);
             fail("IllegalArgumentException should be thrown");
@@ -93,7 +92,7 @@
         }
 
         //Not null parameter
-        List<String> lsFiled = new ArrayList<String>();;
+        List lsFiled = new ArrayList<String>();
         lsFiled.add("Parameter1");
         lsFiled.add("Parameter2");
         try {
@@ -116,13 +115,13 @@
     )
     public void test_getParameters() {
         String[] param = {"Parameter1", "Parameter2", "Parameter3"};
-        List<String> ls = new ArrayList<String>();
+        List ls = new ArrayList<String>();
         for (int i = 0; i < param.length; i++) {
             ls.add(param[i]);
         }
         KeyStoreBuilderParameters ksp = new KeyStoreBuilderParameters(ls);
         try {
-            List<String> res_list = ksp.getParameters();
+            List res_list = ksp.getParameters();
             try {
                 res_list.add("test");
             } catch (UnsupportedOperationException e) {
diff --git a/support/src/test/java/javax/net/ssl/StandardNames.java b/support/src/test/java/javax/net/ssl/StandardNames.java
index debc047..58a552b 100644
--- a/support/src/test/java/javax/net/ssl/StandardNames.java
+++ b/support/src/test/java/javax/net/ssl/StandardNames.java
@@ -17,12 +17,15 @@
 package javax.net.ssl;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Set;
+import junit.framework.Assert;
 
 /**
- * This class defines expected string names for protocols, key types, client and server auth types, cipher suites.
+ * This class defines expected string names for protocols, key types,
+ * client and server auth types, cipher suites.
  *
  * Initially based on "Appendix A: Standard Names" of
  * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#AppA">
@@ -34,14 +37,17 @@
  * Java Cryptography Architecture Sun Providers Documentation for JavaTM Platform Standard Edition 6
  * </a>
  */
-public final class StandardNames {
+public final class StandardNames extends Assert {
 
+    public static final String SSL_CONTEXT_PROTOCOLS_DEFAULT = "Default";
     public static final Set<String> SSL_CONTEXT_PROTOCOLS = new HashSet<String>(Arrays.asList(
+        SSL_CONTEXT_PROTOCOLS_DEFAULT,
         "SSL",
-        "SSLv2",
+        // "SSLv2",
         "SSLv3",
         "TLS",
         "TLSv1"));
+    public static final String SSL_CONTEXT_PROTOCOL_DEFAULT = "TLS";
 
     public static final Set<String> KEY_TYPES = new HashSet<String>(Arrays.asList(
         "RSA",
@@ -50,10 +56,20 @@
         "DH_DSA"));
 
     public static final Set<String> SSL_SOCKET_PROTOCOLS = new HashSet<String>(Arrays.asList(
-        "SSLv2",
+        // "SSLv2",
         "SSLv3",
-        "TLSv1",
-        "SSLv2Hello"));
+        "TLSv1"));
+    static {
+        if (TestSSLContext.IS_RI) {
+            /* Even though we use OpenSSL's SSLv23_method which
+             * supports sending SSLv2 client hello messages, the
+             * OpenSSL implementation in s23_client_hello disables
+             * this if SSL_OP_NO_SSLv2 is specified, which we always
+             * do to disable general use of SSLv2.
+             */
+            SSL_SOCKET_PROTOCOLS.add("SSLv2Hello");
+        }
+    }
 
     public static final Set<String> CLIENT_AUTH_TYPES = new HashSet<String>(KEY_TYPES);
 
@@ -182,4 +198,107 @@
 
         CIPHER_SUITES = (TestSSLContext.IS_RI) ? CIPHER_SUITES_RI : CIPHER_SUITES_OPENSSL;
     }
+
+    public static final Set<String> CIPHER_SUITES_SSLENGINE = new HashSet<String>(CIPHER_SUITES);
+    static {
+        if (!TestSSLContext.IS_RI) {
+            // Android does not include Java versions of RC4 and IDEA
+            // Java crypto implementations so these fail to work for
+            // the SSLEngine implementation.
+            CIPHER_SUITES_SSLENGINE.remove("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5");
+            CIPHER_SUITES_SSLENGINE.remove("SSL_DH_anon_WITH_RC4_128_MD5");
+            CIPHER_SUITES_SSLENGINE.remove("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5");
+            CIPHER_SUITES_SSLENGINE.remove("SSL_RSA_EXPORT_WITH_RC4_40_MD5");
+            CIPHER_SUITES_SSLENGINE.remove("SSL_RSA_WITH_RC4_128_MD5");
+            CIPHER_SUITES_SSLENGINE.remove("SSL_RSA_WITH_RC4_128_SHA");
+            CIPHER_SUITES_SSLENGINE.remove("TLS_RSA_WITH_IDEA_CBC_SHA");
+            // Harmony SSLEngine does not support AES cipher suites
+            // that are supported by the OpenSSL based SSLSocket
+            // implementations
+            CIPHER_SUITES_SSLENGINE.remove("TLS_DHE_DSS_WITH_AES_128_CBC_SHA");
+            CIPHER_SUITES_SSLENGINE.remove("TLS_DHE_DSS_WITH_AES_256_CBC_SHA");
+            CIPHER_SUITES_SSLENGINE.remove("TLS_DHE_RSA_WITH_AES_128_CBC_SHA");
+            CIPHER_SUITES_SSLENGINE.remove("TLS_DHE_RSA_WITH_AES_256_CBC_SHA");
+            CIPHER_SUITES_SSLENGINE.remove("TLS_DH_anon_WITH_AES_128_CBC_SHA");
+            CIPHER_SUITES_SSLENGINE.remove("TLS_DH_anon_WITH_AES_256_CBC_SHA");
+            CIPHER_SUITES_SSLENGINE.remove("TLS_RSA_WITH_AES_128_CBC_SHA");
+            CIPHER_SUITES_SSLENGINE.remove("TLS_RSA_WITH_AES_256_CBC_SHA");
+            // Harmony SSLEngine supports has some older cipher suites
+            CIPHER_SUITES_SSLENGINE.add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA");
+            CIPHER_SUITES_SSLENGINE.add("SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA");
+            CIPHER_SUITES_SSLENGINE.add("SSL_DH_DSS_WITH_DES_CBC_SHA");
+            CIPHER_SUITES_SSLENGINE.add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA");
+            CIPHER_SUITES_SSLENGINE.add("SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA");
+            CIPHER_SUITES_SSLENGINE.add("SSL_DH_RSA_WITH_DES_CBC_SHA");
+        }
+    }
+
+    /**
+     * Asserts that the cipher suites array is non-null and that it
+     * all of its contents are cipher suites known to this
+     * implementation. As a convenience, returns any unenabled cipher
+     * suites in a test for those that want to verify separately that
+     * all cipher suites were included.
+     */
+    public static Set<String> assertValidCipherSuites(Set<String> expected, String[] cipherSuites) {
+        assertNotNull(cipherSuites);
+        assertTrue(cipherSuites.length != 0);
+
+        // Make sure all cipherSuites names are expected
+        Set remainingCipherSuites = new HashSet<String>(expected);
+        Set unknownCipherSuites = new HashSet<String>();
+        for (String cipherSuite : cipherSuites) {
+            boolean removed = remainingCipherSuites.remove(cipherSuite);
+            if (!removed) {
+                unknownCipherSuites.add(cipherSuite);
+            }
+        }
+        assertEquals(Collections.EMPTY_SET, unknownCipherSuites);
+        return remainingCipherSuites;
+    }
+
+    /**
+     * After using assertValidCipherSuites on cipherSuites,
+     * assertSupportedCipherSuites additionally verifies that all
+     * supported cipher suites where in the input array.
+     */
+    public static void assertSupportedCipherSuites(Set<String> expected, String[] cipherSuites) {
+        Set<String> remainingCipherSuites = assertValidCipherSuites(expected, cipherSuites);
+        assertEquals(Collections.EMPTY_SET, remainingCipherSuites);
+        assertEquals(expected.size(), cipherSuites.length);
+    }
+
+    /**
+     * Asserts that the protocols array is non-null and that it all of
+     * its contents are protocols known to this implementation. As a
+     * convenience, returns any unenabled protocols in a test for
+     * those that want to verify separately that all protocols were
+     * included.
+     */
+    public static Set<String> assertValidProtocols(Set<String> expected, String[] protocols) {
+        assertNotNull(protocols);
+        assertTrue(protocols.length != 0);
+
+        // Make sure all protocols names are expected
+        Set remainingProtocols = new HashSet<String>(StandardNames.SSL_SOCKET_PROTOCOLS);
+        Set unknownProtocols = new HashSet<String>();
+        for (String protocol : protocols) {
+            if (!remainingProtocols.remove(protocol)) {
+                unknownProtocols.add(protocol);
+            }
+        }
+        assertEquals(Collections.EMPTY_SET, unknownProtocols);
+        return remainingProtocols;
+    }
+
+    /**
+     * After using assertValidProtocols on protocols,
+     * assertSupportedProtocols additionally verifies that all
+     * supported protocols where in the input array.
+     */
+    public static void assertSupportedProtocols(Set<String> expected, String[] protocols) {
+        Set<String> remainingProtocols = assertValidProtocols(expected, protocols);
+        assertEquals(Collections.EMPTY_SET, remainingProtocols);
+        assertEquals(expected.size(), protocols.length);
+    }
 }
diff --git a/support/src/test/java/javax/net/ssl/TestKeyStore.java b/support/src/test/java/javax/net/ssl/TestKeyStore.java
index 97b5c23..9ef2bdd 100644
--- a/support/src/test/java/javax/net/ssl/TestKeyStore.java
+++ b/support/src/test/java/javax/net/ssl/TestKeyStore.java
@@ -106,9 +106,7 @@
                                       char[] keyStorePassword,
                                       String keyAlgorithm,
                                       String publicAlias,
-                                      String privateAlias)
-        throws Exception {
-
+                                      String privateAlias) throws Exception {
         PrivateKey privateKey;
         X509Certificate x509c;
         if (publicAlias == null && privateAlias == null) {
diff --git a/support/src/test/java/javax/net/ssl/TestSSLContext.java b/support/src/test/java/javax/net/ssl/TestSSLContext.java
index 5ec040c..3492a28 100644
--- a/support/src/test/java/javax/net/ssl/TestSSLContext.java
+++ b/support/src/test/java/javax/net/ssl/TestSSLContext.java
@@ -25,7 +25,7 @@
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.Collections;
-import junit.framework.AssertionFailedError;
+import junit.framework.Assert;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 
 /**
@@ -33,9 +33,10 @@
  * want a canned SSLContext and related state for testing so they
  * don't have to duplicate the logic.
  */
-public final class TestSSLContext {
+public final class TestSSLContext extends Assert {
 
-    public static final boolean IS_RI = !"Dalvik Core Library".equals(System.getProperty("java.specification.name"));
+    public static final boolean IS_RI
+            = !"Dalvik Core Library".equals(System.getProperty("java.specification.name"));
     public static final String PROVIDER_NAME = (IS_RI) ? "SunJSSE" : "HarmonyJSSE";
 
     /*
@@ -68,7 +69,9 @@
      * results appropriately.
      */
     public static boolean sslServerSocketSupportsSessionTickets () {
-        return !IS_RI;
+        // Disabled session tickets for better compatability b/2682876
+        // return !IS_RI;
+        return false;
     }
 
     public final KeyStore keyStore;
@@ -164,7 +167,8 @@
      * certificate chain from the given KeyStore and a TrustManager
      * using the certificates authorities from the same KeyStore.
      */
-    public static final SSLContext createSSLContext(final KeyStore keyStore, final char[] keyStorePassword)
+    public static final SSLContext createSSLContext(final KeyStore keyStore,
+                                                    final char[] keyStorePassword)
         throws Exception {
         String kmfa = KeyManagerFactory.getDefaultAlgorithm();
         KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfa);
@@ -193,9 +197,7 @@
                 break;
             }
         }
-        if (!found) {
-            throw new AssertionFailedError("Could not find princial " + principal + " in key store");
-        }
+        assertTrue(found);
     }
 
     public static void assertCertificateInKeyStore(Certificate certificate,
@@ -211,8 +213,6 @@
                 break;
             }
         }
-        if (!found) {
-            throw new AssertionFailedError("Could not find certificate " + certificate + " in key store");
-        }
+        assertTrue(found);
     }
 }
diff --git a/support/src/test/java/javax/net/ssl/TestSSLEnginePair.java b/support/src/test/java/javax/net/ssl/TestSSLEnginePair.java
new file mode 100644
index 0000000..f3250e6
--- /dev/null
+++ b/support/src/test/java/javax/net/ssl/TestSSLEnginePair.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2010 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 javax.net.ssl;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
+import junit.framework.Assert;
+
+/**
+ * TestSSLEnginePair is a convenience class for other tests that want
+ * a pair of connected and handshaked client and server SSLEngines for
+ * testing.
+ */
+public final class TestSSLEnginePair extends Assert {
+    public final TestSSLContext c;
+    public final SSLEngine server;
+    public final SSLEngine client;
+
+    private TestSSLEnginePair(TestSSLContext c,
+                              SSLEngine server,
+                              SSLEngine client) {
+        this.c = c;
+        this.server = server;
+        this.client = client;
+    }
+
+    public static TestSSLEnginePair create(Hooks hooks) throws IOException {
+        TestSSLContext c = TestSSLContext.create();
+        SSLEngine[] engines = connect(c, c, hooks);
+        return new TestSSLEnginePair(c, engines[0], engines[1]);
+    }
+
+    /**
+     * Create a new connected server/client engine pair within a
+     * existing SSLContext. Optionally specify clientCipherSuites to
+     * allow forcing new SSLSession to test SSLSessionContext
+     * caching. Optionally specify serverCipherSuites for testing
+     * cipher suite negotiation.
+     */
+    public static SSLEngine[] connect(final TestSSLContext clientContext,
+                                      final TestSSLContext serverContext,
+                                      Hooks hooks) throws IOException {
+        if (hooks == null) {
+            hooks = new Hooks();
+        }
+
+        SSLSession session = clientContext.sslContext.createSSLEngine().getSession();
+
+        int packetBufferSize = session.getPacketBufferSize();
+        ByteBuffer clientToServer = ByteBuffer.allocate(packetBufferSize);
+        ByteBuffer serverToClient = ByteBuffer.allocate(packetBufferSize);
+
+        int applicationBufferSize = session.getApplicationBufferSize();
+        ByteBuffer scratch = ByteBuffer.allocate(applicationBufferSize);
+
+        SSLEngine client = clientContext.sslContext.createSSLEngine();
+        SSLEngine server = serverContext.sslContext.createSSLEngine();
+        client.setUseClientMode(true);
+        server.setUseClientMode(false);
+        hooks.beforeBeginHandshake(client, server);
+        client.beginHandshake();
+        server.beginHandshake();
+
+        while (true) {
+            boolean clientDone = client.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING;
+            boolean serverDone = server.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING;
+            if (clientDone && serverDone) {
+                break;
+            }
+
+            boolean progress = false;
+            if (!clientDone) {
+                progress |= handshakeCompleted(client,
+                                               clientToServer,
+                                               serverToClient,
+                                               scratch);
+            }
+            if (!serverDone) {
+                progress |= handshakeCompleted(server,
+                                               serverToClient,
+                                               clientToServer,
+                                               scratch);
+            }
+            if (!progress) {
+                // let caller detect the problem, but don't just hang here
+                break;
+            }
+        }
+
+        return new SSLEngine[] { server, client };
+    }
+
+    public static class Hooks {
+        void beforeBeginHandshake(SSLEngine client, SSLEngine server) {}
+    }
+
+    private static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocate(0);
+
+    private static boolean handshakeCompleted(SSLEngine engine,
+                                              ByteBuffer output,
+                                              ByteBuffer input,
+                                              ByteBuffer scratch) throws IOException {
+        try {
+            // make the other side's output into our input
+            input.flip();
+
+            HandshakeStatus status = engine.getHandshakeStatus();
+            switch (status) {
+
+                case NEED_TASK:
+                    boolean progress = false;
+                    while (true) {
+                        Runnable runnable = engine.getDelegatedTask();
+                        if (runnable == null) {
+                            return progress;
+                        }
+                        runnable.run();
+                        progress = true;
+                    }
+
+                case NEED_UNWRAP:
+                    // avoid underflow
+                    if (input.remaining() == 0) {
+                        return false;
+                    }
+                    SSLEngineResult unwrapResult = engine.unwrap(input, scratch);
+                    assertEquals(SSLEngineResult.Status.OK, unwrapResult.getStatus());
+                    assertEquals(0, scratch.position());
+                    return true;
+
+                case NEED_WRAP:
+                    // avoid possible overflow
+                    if (output.remaining() != output.capacity()) {
+                        return false;
+                    }
+                    SSLEngineResult wrapResult = engine.wrap(EMPTY_BYTE_BUFFER, output);
+                    assertEquals(SSLEngineResult.Status.OK, wrapResult.getStatus());
+                    return true;
+
+                case NOT_HANDSHAKING:
+                    // should have been checked by caller before calling
+                case FINISHED:
+                    // only returned by wrap/unrap status, not getHandshakeStatus
+                    throw new IllegalStateException("Unexpected HandshakeStatus = " + status);
+                default:
+                    throw new IllegalStateException("Unknown HandshakeStatus = " + status);
+            }
+        } finally {
+            // shift consumed input, restore to output mode
+            input.compact();
+        }
+    }
+}
diff --git a/support/src/test/java/org/apache/harmony/security/tests/support/MySSLContextSpi.java b/support/src/test/java/org/apache/harmony/security/tests/support/MySSLContextSpi.java
index 30df601..9da7a6f 100644
--- a/support/src/test/java/org/apache/harmony/security/tests/support/MySSLContextSpi.java
+++ b/support/src/test/java/org/apache/harmony/security/tests/support/MySSLContextSpi.java
@@ -20,15 +20,15 @@
 import java.nio.ByteBuffer;
 import java.security.KeyManagementException;
 import java.security.SecureRandom;
-
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContextSpi;
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLEngineResult;
 import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLServerSocketFactory;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.SSLSessionContext;
-import javax.net.ssl.SSLServerSocketFactory;
 import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
 
@@ -79,6 +79,16 @@
         return null;
     }
 
+    protected SSLParameters engineGetDefaultSSLParameters() {
+        engineGetSocketFactory();
+        return null;
+    }
+
+    protected SSLParameters engineGetSupportedSSLParameters() {
+        engineGetSocketFactory();
+        return null;
+    }
+
     /*
      * FIXME: add these methods
      */
diff --git a/support/src/test/java/org/apache/harmony/xnet/tests/support/MySSLContextSpi.java b/support/src/test/java/org/apache/harmony/xnet/tests/support/MySSLContextSpi.java
index 489273c..54e2a03 100644
--- a/support/src/test/java/org/apache/harmony/xnet/tests/support/MySSLContextSpi.java
+++ b/support/src/test/java/org/apache/harmony/xnet/tests/support/MySSLContextSpi.java
@@ -20,15 +20,15 @@
 import java.nio.ByteBuffer;
 import java.security.KeyManagementException;
 import java.security.SecureRandom;
-
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContextSpi;
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLEngineResult;
 import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLServerSocketFactory;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.SSLSessionContext;
-import javax.net.ssl.SSLServerSocketFactory;
 import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
 
@@ -77,6 +77,16 @@
         return null;
     }
 
+    protected SSLParameters engineGetDefaultSSLParameters() {
+        engineGetSocketFactory();
+        return null;
+    }
+
+    protected SSLParameters engineGetSupportedSSLParameters() {
+        engineGetSocketFactory();
+        return null;
+    }
+
     /*
      * FIXME: add these methods
      */
@@ -142,4 +152,4 @@
             return null;
         }
     }
-}
\ No newline at end of file
+}