Merge "Implement EapAkaTypeData."
diff --git a/src/java/com/android/ike/eap/message/simaka/EapAkaTypeData.java b/src/java/com/android/ike/eap/message/simaka/EapAkaTypeData.java
new file mode 100644
index 0000000..ad310a3
--- /dev/null
+++ b/src/java/com/android/ike/eap/message/simaka/EapAkaTypeData.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ike.eap.message.simaka;
+
+import android.annotation.NonNull;
+
+import com.android.ike.eap.message.EapMessage;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * EapAkaTypeData represents the Type Data for an {@link EapMessage} during an EAP-AKA session.
+ */
+public class EapAkaTypeData extends EapSimAkaTypeData {
+    // EAP-AKA Subtype values defined by IANA
+    // https://www.iana.org/assignments/eapsimaka-numbers/eapsimaka-numbers.xhtml
+    public static final int EAP_AKA_CHALLENGE = 1;
+    public static final int EAP_AKA_AUTHENTICATION_REJECT = 2;
+    public static final int EAP_AKA_SYNCHRONIZATION_FAILURE = 4;
+    public static final int EAP_AKA_IDENTITY = 5;
+    public static final int EAP_AKA_NOTIFICATION = 12;
+    public static final int EAP_AKA_REAUTHENTICATION = 13;
+    public static final int EAP_AKA_CLIENT_ERROR = 14;
+
+    public static final Map<Integer, String> EAP_AKA_SUBTYPE_STRING = new HashMap<>();
+    static {
+        EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_CHALLENGE, "Challenge");
+        EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_AUTHENTICATION_REJECT, "Authentication-Reject");
+        EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_SYNCHRONIZATION_FAILURE, "Synchronization-Failure");
+        EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_IDENTITY, "Identity");
+        EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_NOTIFICATION, "Notification");
+        EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_REAUTHENTICATION, "Re-authentication");
+        EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_CLIENT_ERROR, "Client-Error");
+    }
+
+    private static final Set<Integer> SUPPORTED_SUBTYPES = new HashSet<>();
+    static {
+        SUPPORTED_SUBTYPES.add(EAP_AKA_CHALLENGE);
+        SUPPORTED_SUBTYPES.add(EAP_AKA_AUTHENTICATION_REJECT);
+        SUPPORTED_SUBTYPES.add(EAP_AKA_SYNCHRONIZATION_FAILURE);
+        SUPPORTED_SUBTYPES.add(EAP_AKA_IDENTITY);
+        SUPPORTED_SUBTYPES.add(EAP_AKA_NOTIFICATION);
+        SUPPORTED_SUBTYPES.add(EAP_AKA_REAUTHENTICATION);
+        SUPPORTED_SUBTYPES.add(EAP_AKA_CLIENT_ERROR);
+    }
+
+    private static final EapAkaTypeDataDecoder sTypeDataDecoder = new EapAkaTypeDataDecoder();
+
+    @VisibleForTesting
+    public EapAkaTypeData(int eapSubType, LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap) {
+        super(eapSubType, attributeMap);
+    }
+
+    /**
+     * Creates and returns an EapAkaTypeData instance with the given subtype and attributes.
+     *
+     * @param eapSubtype the subtype for the EAP-AKA type data
+     * @param attributes the List of EapSimAkaAttributes to be included in this type data
+     */
+    public EapAkaTypeData(int eapSubtype, List<EapSimAkaAttribute> attributes) {
+        super(eapSubtype, new LinkedHashMap<>());
+
+        for (EapSimAkaAttribute attribute : attributes) {
+            // TODO(b/139805493): check for duplicate attributes
+            attributeMap.put(attribute.attributeType, attribute);
+        }
+    }
+
+    public static EapAkaTypeDataDecoder getEapAkaTypeDataDecoder() {
+        return sTypeDataDecoder;
+    }
+
+    /**
+     * EapSimTypeDataDecoder will be used for decoding {@link EapAkaTypeData} objects.
+     */
+    public static class EapAkaTypeDataDecoder extends EapSimAkaTypeDataDecoder<EapAkaTypeData> {
+        private static final String TAG = EapAkaTypeDataDecoder.class.getSimpleName();
+        private static final String EAP_METHOD = "EAP-AKA";
+
+        protected EapAkaTypeDataDecoder() {
+            super(
+                    TAG,
+                    EAP_METHOD,
+                    SUPPORTED_SUBTYPES,
+                    EapSimAttributeFactory.getInstance(),
+                    EAP_AKA_SUBTYPE_STRING);
+        }
+
+        /**
+         * Decodes the given byte-array into a DecodeResult object.
+         *
+         * @param typeData the byte-encoding of the EapSimTypeData to be parsed
+         * @return a DecodeResult object. If the decoding is successful, this will encapsulate an
+         *         EapAkaTypeData instance representing the data stored in typeData. Otherwise, it
+         *         will contain the relevant AtClientErrorCode for the decoding error.
+         */
+        public DecodeResult<EapAkaTypeData> decode(@NonNull byte[] typeData) {
+            return super.decode(typeData);
+        }
+
+        @Override
+        protected EapAkaTypeData getInstance(
+                int eapSubtype,
+                LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap) {
+            return new EapAkaTypeData(eapSubtype, attributeMap);
+        }
+    }
+}
diff --git a/tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java b/tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java
index 835c143..516ff8c 100644
--- a/tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java
+++ b/tests/iketests/src/java/com/android/ike/eap/message/EapTestMessageDefinitions.java
@@ -36,11 +36,13 @@
     public static final int ID_INT = Integer.parseInt(ID, 16 /* radix */);
 
     // EAP-AKA Identity request
-    public static final String EAP_REQUEST_TYPE_DATA = "050C010000";
+    public static final String EAP_REQUEST_TYPE_DATA = "0500000D010000";
+    public static final byte[] EAP_AKA_IDENTITY_REQUEST =
+            hexStringToByteArray(EAP_REQUEST_TYPE_DATA);
     public static final byte[] EAP_REQUEST_AKA_IDENTITY_PACKET =
             hexStringToByteArray("01" + ID + "000A17" + EAP_REQUEST_TYPE_DATA);
     public static final byte[] EAP_REQUEST_IDENTITY_PACKET =
-            hexStringToByteArray(("01" + ID + "000501"));
+            hexStringToByteArray("01" + ID + "000501");
 
     // EAP-Identity: hex for ASCII in "test@android.net"
     public static final String EAP_IDENTITY_STRING = "7465737440616E64726F69642E6E6574";
diff --git a/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapAkaTypeDataTest.java b/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapAkaTypeDataTest.java
new file mode 100644
index 0000000..837e2c6
--- /dev/null
+++ b/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapAkaTypeDataTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ike.eap.message.simaka;
+
+import static com.android.ike.eap.message.EapTestMessageDefinitions.EAP_AKA_IDENTITY_REQUEST;
+import static com.android.ike.eap.message.EapTestMessageDefinitions.INVALID_SUBTYPE;
+import static com.android.ike.eap.message.simaka.EapAkaTypeData.EAP_AKA_IDENTITY;
+import static com.android.ike.eap.message.simaka.EapSimAkaAttribute.EAP_AT_ANY_ID_REQ;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import com.android.ike.eap.message.simaka.EapAkaTypeData.EapAkaTypeDataDecoder;
+import com.android.ike.eap.message.simaka.EapSimAkaAttribute.AtAnyIdReq;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.LinkedHashMap;
+
+public class EapAkaTypeDataTest {
+    private static final int UNABLE_TO_PROCESS_CODE = 0;
+
+    private EapAkaTypeDataDecoder mEapAkaTypeDataDecoder;
+
+    @Before
+    public void setUp() {
+        mEapAkaTypeDataDecoder = EapAkaTypeData.getEapAkaTypeDataDecoder();
+    }
+
+    @Test
+    public void testDecode() {
+
+    }
+
+    @Test
+    public void testDecodeInvalidSubtype() {
+        EapSimAkaTypeData.DecodeResult<EapAkaTypeData> result =
+                mEapAkaTypeDataDecoder.decode(INVALID_SUBTYPE);
+        assertFalse(result.isSuccessfulDecode());
+        assertEquals(UNABLE_TO_PROCESS_CODE, result.atClientErrorCode.errorCode);
+    }
+
+    @Test
+    public void testEncode() throws Exception {
+        LinkedHashMap<Integer, EapSimAkaAttribute> attributes = new LinkedHashMap<>();
+        attributes.put(EAP_AT_ANY_ID_REQ, new AtAnyIdReq());
+        EapAkaTypeData eapAkaTypeData = new EapAkaTypeData(EAP_AKA_IDENTITY, attributes);
+
+        byte[] result = eapAkaTypeData.encode();
+        assertArrayEquals(EAP_AKA_IDENTITY_REQUEST, result);
+    }
+}
diff --git a/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapSimTypeDataTest.java b/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapSimTypeDataTest.java
index c4c8ae9..23437d7 100644
--- a/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapSimTypeDataTest.java
+++ b/tests/iketests/src/java/com/android/ike/eap/message/simaka/EapSimTypeDataTest.java
@@ -108,7 +108,6 @@
         DecodeResult<EapSimTypeData> result = mEapSimTypeDataDecoder.decode(INVALID_SUBTYPE);
         assertFalse(result.isSuccessfulDecode());
         assertEquals(UNABLE_TO_PROCESS_CODE, result.atClientErrorCode.errorCode);
-
     }
 
     @Test
@@ -124,7 +123,6 @@
         DecodeResult<EapSimTypeData> result = mEapSimTypeDataDecoder.decode(SHORT_TYPE_DATA);
         assertFalse(result.isSuccessfulDecode());
         assertEquals(UNABLE_TO_PROCESS_CODE, result.atClientErrorCode.errorCode);
-
     }
 
     @Test