Merge "API Council feedback for IKE 3GPP support."
diff --git a/api/current.txt b/api/current.txt
index b150294..f47f205 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7,6 +7,7 @@
     method @NonNull public byte[] getEapIdentity();
     method @Nullable public android.net.eap.EapSessionConfig.EapMsChapV2Config getEapMsChapV2Config();
     method @Nullable public android.net.eap.EapSessionConfig.EapSimConfig getEapSimConfig();
+    method @Nullable public android.net.eap.EapSessionConfig.EapTtlsConfig getEapTtlsConfig();
   }
 
   public static final class EapSessionConfig.Builder {
@@ -17,6 +18,7 @@
     method @NonNull public android.net.eap.EapSessionConfig.Builder setEapIdentity(@NonNull byte[]);
     method @NonNull public android.net.eap.EapSessionConfig.Builder setEapMsChapV2Config(@NonNull String, @NonNull String);
     method @NonNull public android.net.eap.EapSessionConfig.Builder setEapSimConfig(int, int);
+    method @NonNull public android.net.eap.EapSessionConfig.Builder setEapTtlsConfig(@Nullable java.security.cert.X509Certificate, @NonNull android.net.eap.EapSessionConfig);
   }
 
   public static class EapSessionConfig.EapAkaConfig extends android.net.eap.EapSessionConfig.EapMethodConfig {
@@ -43,6 +45,11 @@
     method public int getSubId();
   }
 
+  public static class EapSessionConfig.EapTtlsConfig extends android.net.eap.EapSessionConfig.EapMethodConfig {
+    method @NonNull public android.net.eap.EapSessionConfig getInnerEapSessionConfig();
+    method @Nullable public java.security.cert.X509Certificate getServerCaCert();
+  }
+
 }
 
 package android.net.ipsec.ike {
diff --git a/src/java/android/net/eap/EapSessionConfig.java b/src/java/android/net/eap/EapSessionConfig.java
index cfa2fcc..7342dd1 100644
--- a/src/java/android/net/eap/EapSessionConfig.java
+++ b/src/java/android/net/eap/EapSessionConfig.java
@@ -194,7 +194,6 @@
      * Retrieves configuration for EAP-TTLS
      *
      * @return the configuration for EAP-TTLS, or null if it was not set
-     * @hide
      */
     @Nullable
     public EapTtlsConfig getEapTtlsConfig() {
@@ -308,9 +307,11 @@
         }
 
         /**
-         * Sets the configuration for EAP-TTLS
+         * Sets the configuration for EAP-TTLS.
          *
-         * <p>Nested tunnel authentications are disallowed.
+         * <p>Tunneled EAP-TTLS authentications are disallowed, as running multiple layers of
+         * EAP-TTLS increases the data footprint but has no discernible benefits over a single
+         * EAP-TTLS session with a non EAP-TTLS method nested inside it.
          *
          * @param serverCaCert the CA certificate for validating the received server certificate(s).
          *     If a certificate is provided, it MUST be the root CA used by the server, or
@@ -318,7 +319,6 @@
          *     truststore is considered acceptable.
          * @param innerEapSessionConfig represents the configuration for the inner EAP instance
          * @return Builder this, to facilitate chaining
-         * @hide
          */
         @NonNull
         public Builder setEapTtlsConfig(
@@ -762,8 +762,6 @@
 
     /**
      * EapTtlsConfig represents the configs needed for an EAP-TTLS session.
-     *
-     * @hide
      */
     public static class EapTtlsConfig extends EapMethodConfig {
         private static final String TRUST_CERT_KEY = "TRUST_CERT_KEY";
@@ -854,7 +852,6 @@
          *
          * @return the CA certificate for validating the received server certificate or null if the
          *     system default is preferred
-         * @hide
          */
         @Nullable
         public X509Certificate getServerCaCert() {
@@ -865,7 +862,6 @@
          * Retrieves the inner EAP session config
          *
          * @return an EapSessionConfig representing the config for tunneled EAP authentication
-         * @hide
          */
         @NonNull
         public EapSessionConfig getInnerEapSessionConfig() {
diff --git a/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java b/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java
index c3c648d..132c519 100644
--- a/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java
+++ b/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java
@@ -1491,7 +1491,7 @@
         intent.putExtras(bundle);
 
         return PendingIntent.getBroadcast(
-                context, 0 /*requestCode unused*/, intent, 0 /*default flags*/);
+                context, 0 /* requestCode; unused */, intent, PendingIntent.FLAG_IMMUTABLE);
     }
 
     /**
diff --git a/tests/cts/src/android/eap/cts/EapSessionConfigTest.java b/tests/cts/src/android/eap/cts/EapSessionConfigTest.java
index b0a257a..784e4f3 100644
--- a/tests/cts/src/android/eap/cts/EapSessionConfigTest.java
+++ b/tests/cts/src/android/eap/cts/EapSessionConfigTest.java
@@ -28,18 +28,25 @@
 import android.net.eap.EapSessionConfig.EapAkaPrimeConfig;
 import android.net.eap.EapSessionConfig.EapMsChapV2Config;
 import android.net.eap.EapSessionConfig.EapSimConfig;
+import android.net.eap.EapSessionConfig.EapTtlsConfig;
 import android.net.eap.EapSessionConfig.EapUiccConfig;
 
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.net.ipsec.ike.testutils.CertUtils;
+
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.security.cert.X509Certificate;
+
 @RunWith(AndroidJUnit4.class)
 public class EapSessionConfigTest {
     // These constants are IANA-defined values and are copies of hidden constants in
     // frameworks/opt/net/ike/src/java/com/android/internal/net/eap/message/EapData.java.
     private static final int EAP_TYPE_SIM = 18;
+    private static final int EAP_TYPE_TTLS = 21;
     private static final int EAP_TYPE_AKA = 23;
     private static final int EAP_TYPE_MSCHAP_V2 = 26;
     private static final int EAP_TYPE_AKA_PRIME = 50;
@@ -50,6 +57,19 @@
     private static final String EAP_MSCHAPV2_USERNAME = "username";
     private static final String EAP_MSCHAPV2_PASSWORD = "password";
 
+    private static final EapSessionConfig INNER_EAP_SESSION_CONFIG =
+            new EapSessionConfig.Builder()
+                    .setEapIdentity(EAP_IDENTITY)
+                    .setEapMsChapV2Config(EAP_MSCHAPV2_USERNAME, EAP_MSCHAPV2_PASSWORD)
+                    .build();
+
+    private X509Certificate mServerCaCert;
+
+    @Before
+    public void setUp() throws Exception {
+        mServerCaCert = CertUtils.createCertFromPemFile("server-a-self-signed-ca.pem");
+    }
+
     @Test
     public void testBuildWithAllEapMethods() {
         EapSessionConfig result =
@@ -63,6 +83,7 @@
                                 NETWORK_NAME,
                                 true /* allowMismatchedNetworkNames */)
                         .setEapMsChapV2Config(EAP_MSCHAPV2_USERNAME, EAP_MSCHAPV2_PASSWORD)
+                        .setEapTtlsConfig(mServerCaCert, INNER_EAP_SESSION_CONFIG)
                         .build();
 
         assertArrayEquals(EAP_IDENTITY, result.getEapIdentity());
@@ -89,6 +110,12 @@
         assertEquals(EAP_TYPE_MSCHAP_V2, eapMsChapV2Config.getMethodType());
         assertEquals(EAP_MSCHAPV2_USERNAME, eapMsChapV2Config.getUsername());
         assertEquals(EAP_MSCHAPV2_PASSWORD, eapMsChapV2Config.getPassword());
+
+        EapTtlsConfig eapTtlsConfig = result.getEapTtlsConfig();
+        assertNotNull(eapTtlsConfig);
+        assertEquals(EAP_TYPE_TTLS, eapTtlsConfig.getMethodType());
+        assertEquals(mServerCaCert, eapTtlsConfig.getServerCaCert());
+        assertEquals(INNER_EAP_SESSION_CONFIG, eapTtlsConfig.getInnerEapSessionConfig());
     }
 
     private void verifyEapUiccConfigCommon(EapUiccConfig config) {