Merge changes Id4b6122a,Ibac47013

* changes:
  Switch to port 4500 if both NAT-T and MOBIKE are supported
  Support injecting ConnectivityManager to IkeNattKeepalive
diff --git a/src/java/com/android/internal/net/eap/message/simaka/EapAkaPrimeTypeData.java b/src/java/com/android/internal/net/eap/message/simaka/EapAkaPrimeTypeData.java
index 23dcd02..2c15996 100644
--- a/src/java/com/android/internal/net/eap/message/simaka/EapAkaPrimeTypeData.java
+++ b/src/java/com/android/internal/net/eap/message/simaka/EapAkaPrimeTypeData.java
@@ -34,11 +34,17 @@
             new EapAkaPrimeTypeDataDecoder();
 
     @VisibleForTesting
-    EapAkaPrimeTypeData(
-            int eapSubType, LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap) {
+    EapAkaPrimeTypeData(int eapSubType, LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap) {
         super(eapSubType, attributeMap);
     }
 
+    private EapAkaPrimeTypeData(
+            int eapSubType,
+            LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap,
+            byte[] reservedBytes) {
+        super(eapSubType, attributeMap, reservedBytes);
+    }
+
     /**
      * Creates and returns an EapAkaPrimeTypeData instance with the given subtype and attributes.
      *
@@ -88,8 +94,10 @@
 
         @Override
         protected EapAkaPrimeTypeData getInstance(
-                int eapSubtype, LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap) {
-            return new EapAkaPrimeTypeData(eapSubtype, attributeMap);
+                int eapSubtype,
+                LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap,
+                byte[] reservedBytes) {
+            return new EapAkaPrimeTypeData(eapSubtype, attributeMap, reservedBytes);
         }
     }
 }
diff --git a/src/java/com/android/internal/net/eap/message/simaka/EapAkaTypeData.java b/src/java/com/android/internal/net/eap/message/simaka/EapAkaTypeData.java
index e3ce817..0fb2aa4 100644
--- a/src/java/com/android/internal/net/eap/message/simaka/EapAkaTypeData.java
+++ b/src/java/com/android/internal/net/eap/message/simaka/EapAkaTypeData.java
@@ -73,6 +73,13 @@
         super(eapSubType, attributeMap);
     }
 
+    protected EapAkaTypeData(
+            int eapSubType,
+            LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap,
+            byte[] reservedBytes) {
+        super(eapSubType, attributeMap, reservedBytes);
+    }
+
     /**
      * Creates and returns an EapAkaTypeData instance with the given subtype and attributes.
      *
@@ -130,8 +137,9 @@
         @Override
         protected EapAkaTypeData getInstance(
                 int eapSubtype,
-                LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap) {
-            return new EapAkaTypeData(eapSubtype, attributeMap);
+                LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap,
+                byte[] reservedBytes) {
+            return new EapAkaTypeData(eapSubtype, attributeMap, reservedBytes);
         }
     }
 }
diff --git a/src/java/com/android/internal/net/eap/message/simaka/EapSimAkaAttribute.java b/src/java/com/android/internal/net/eap/message/simaka/EapSimAkaAttribute.java
index 73d6752..cd41287 100644
--- a/src/java/com/android/internal/net/eap/message/simaka/EapSimAkaAttribute.java
+++ b/src/java/com/android/internal/net/eap/message/simaka/EapSimAkaAttribute.java
@@ -23,6 +23,7 @@
 import com.android.internal.net.eap.exceptions.simaka.EapSimAkaInvalidAttributeException;
 import com.android.internal.net.eap.exceptions.simaka.EapSimInvalidAtRandException;
 
+import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -132,6 +133,64 @@
      */
     public abstract void encode(ByteBuffer byteBuffer);
 
+    /**
+     * EapSimAkaReservedBytesAttribute represents any EAP-SIM/AKA attribute that is of the format:
+     *
+     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     * |  Attribute Type (1B)  |  Length (1B)  |  Reserved (2B)  |
+     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     * |  Value...
+     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     *
+     * <p>Note: This Attribute type ignores (but preserves) the Reserved bytes. This is needed for
+     * calculating MACs in EAP-SIM/AKA.
+     */
+    protected abstract static class EapSimAkaReservedBytesAttribute extends EapSimAkaAttribute {
+        protected static final int RESERVED_BYTES_LEN = 2;
+
+        @VisibleForTesting public final byte[] reservedBytes = new byte[RESERVED_BYTES_LEN];
+
+        protected EapSimAkaReservedBytesAttribute(
+                int attributeType, int lengthInBytes, ByteBuffer buffer)
+                throws EapSimAkaInvalidAttributeException {
+            super(attributeType, lengthInBytes);
+
+            try {
+                buffer.get(reservedBytes);
+            } catch (BufferUnderflowException e) {
+                throw new EapSimAkaInvalidAttributeException("Invalid attribute length", e);
+            }
+        }
+
+        protected EapSimAkaReservedBytesAttribute(int attributeType, int lengthInBytes)
+                throws EapSimAkaInvalidAttributeException {
+            super(attributeType, lengthInBytes);
+        }
+
+        protected EapSimAkaReservedBytesAttribute(
+                int attributeType, int lengthInBytes, byte[] reservedBytes)
+                throws EapSimAkaInvalidAttributeException {
+            this(attributeType, lengthInBytes);
+
+            if (reservedBytes.length != RESERVED_BYTES_LEN) {
+                throw new EapSimAkaInvalidAttributeException("Invalid attribute length");
+            }
+            System.arraycopy(
+                    reservedBytes,
+                    0 /* srcPos */,
+                    this.reservedBytes,
+                    0 /* destPos */,
+                    RESERVED_BYTES_LEN);
+        }
+
+        @Override
+        public void encode(ByteBuffer buffer) {
+            encodeAttributeHeader(buffer);
+
+            buffer.put(reservedBytes);
+        }
+    }
+
     protected void encodeAttributeHeader(ByteBuffer byteBuffer) {
         byteBuffer.put((byte) attributeType);
         byteBuffer.put((byte) (lengthInBytes / LENGTH_SCALING));
@@ -286,9 +345,8 @@
     /**
      * AtNonceMt represents the AT_NONCE_MT attribute defined in RFC 4186#10.4
      */
-    public static class AtNonceMt extends EapSimAkaAttribute {
+    public static class AtNonceMt extends EapSimAkaReservedBytesAttribute {
         private static final int LENGTH = 5 * LENGTH_SCALING;
-        private static final int RESERVED_BYTES = 2;
 
         public static final int NONCE_MT_LENGTH = 16;
 
@@ -296,13 +354,11 @@
 
         public AtNonceMt(int lengthInBytes, ByteBuffer byteBuffer)
                 throws EapSimAkaInvalidAttributeException {
-            super(EAP_AT_NONCE_MT, LENGTH);
+            super(EAP_AT_NONCE_MT, LENGTH, byteBuffer);
             if (lengthInBytes != LENGTH) {
                 throw new EapSimAkaInvalidAttributeException("Invalid Length specified");
             }
 
-            // next two bytes are reserved (RFC 4186 Section 10.4)
-            byteBuffer.get(new byte[RESERVED_BYTES]);
             byteBuffer.get(nonceMt);
         }
 
@@ -318,38 +374,28 @@
 
         @Override
         public void encode(ByteBuffer byteBuffer) {
-            encodeAttributeHeader(byteBuffer);
-            byteBuffer.put(new byte[RESERVED_BYTES]);
+            super.encode(byteBuffer);
+
             byteBuffer.put(nonceMt);
         }
     }
 
-    private abstract static class AtIdReq extends EapSimAkaAttribute {
+    private abstract static class AtIdReq extends EapSimAkaReservedBytesAttribute {
         private static final int ATTR_LENGTH = LENGTH_SCALING;
-        private static final int RESERVED_BYTES = 2;
 
         protected AtIdReq(int lengthInBytes, int attributeType, ByteBuffer byteBuffer)
                 throws EapSimAkaInvalidAttributeException {
-            super(attributeType, ATTR_LENGTH);
+            super(attributeType, ATTR_LENGTH, byteBuffer);
 
             if (lengthInBytes != ATTR_LENGTH) {
                 throw new EapSimAkaInvalidAttributeException("Invalid Length specified");
             }
-
-            // next two bytes are reserved (RFC 4186 Section 10.5-10.7)
-            byteBuffer.get(new byte[RESERVED_BYTES]);
         }
 
         @VisibleForTesting
         protected AtIdReq(int attributeType) throws EapSimAkaInvalidAttributeException {
             super(attributeType, ATTR_LENGTH);
         }
-
-        @Override
-        public void encode(ByteBuffer byteBuffer) {
-            encodeAttributeHeader(byteBuffer);
-            byteBuffer.put(new byte[RESERVED_BYTES]);
-        }
     }
 
     /**
@@ -454,9 +500,8 @@
     /**
      * AtRandSim represents the AT_RAND attribute for EAP-SIM defined in RFC 4186#10.9
      */
-    public static class AtRandSim extends EapSimAkaAttribute {
+    public static class AtRandSim extends EapSimAkaReservedBytesAttribute {
         private static final int RAND_LENGTH = 16;
-        private static final int RESERVED_BYTES = 2;
         private static final int MIN_RANDS = 2;
         private static final int MAX_RANDS = 3;
 
@@ -464,10 +509,7 @@
 
         public AtRandSim(int lengthInBytes, ByteBuffer byteBuffer)
                 throws EapSimAkaInvalidAttributeException {
-            super(EAP_AT_RAND, lengthInBytes);
-
-            // next two bytes are reserved (RFC 4186 Section 10.9)
-            byteBuffer.get(new byte[RESERVED_BYTES]);
+            super(EAP_AT_RAND, lengthInBytes, byteBuffer);
 
             int numRands = (lengthInBytes - MIN_ATTR_LENGTH) / RAND_LENGTH;
             if (!isValidNumRands(numRands)) {
@@ -510,8 +552,7 @@
 
         @Override
         public void encode(ByteBuffer byteBuffer) {
-            encodeAttributeHeader(byteBuffer);
-            byteBuffer.put(new byte[RESERVED_BYTES]);
+            super.encode(byteBuffer);
 
             for (byte[] rand : rands) {
                 byteBuffer.put(rand);
@@ -522,24 +563,20 @@
     /**
      * AtRandAka represents the AT_RAND attribute for EAP-AKA defined in RFC 4187#10.6
      */
-    public static class AtRandAka extends EapSimAkaAttribute {
+    public static class AtRandAka extends EapSimAkaReservedBytesAttribute {
         private static final int ATTR_LENGTH = 5 * LENGTH_SCALING;
         private static final int RAND_LENGTH = 16;
-        private static final int RESERVED_BYTES = 2;
 
         public final byte[] rand = new byte[RAND_LENGTH];
 
         public AtRandAka(int lengthInBytes, ByteBuffer byteBuffer)
                 throws EapSimAkaInvalidAttributeException {
-            super(EAP_AT_RAND, lengthInBytes);
+            super(EAP_AT_RAND, lengthInBytes, byteBuffer);
 
             if (lengthInBytes != ATTR_LENGTH) {
                 throw new EapSimAkaInvalidAttributeException("Length must be 20B");
             }
 
-            // next two bytes are reserved (RFC 4187#10.6)
-            byteBuffer.get(new byte[RESERVED_BYTES]);
-
             byteBuffer.get(rand);
         }
 
@@ -557,8 +594,8 @@
 
         @Override
         public void encode(ByteBuffer byteBuffer) {
-            encodeAttributeHeader(byteBuffer);
-            byteBuffer.put(new byte[RESERVED_BYTES]);
+            super.encode(byteBuffer);
+
             byteBuffer.put(rand);
         }
     }
@@ -598,9 +635,8 @@
     /**
      * AtMac represents the AT_MAC attribute defined in RFC 4186#10.14 and RFC 4187#10.15
      */
-    public static class AtMac extends EapSimAkaAttribute {
+    public static class AtMac extends EapSimAkaReservedBytesAttribute {
         private static final int ATTR_LENGTH = 5 * LENGTH_SCALING;
-        private static final int RESERVED_BYTES = 2;
 
         public static final int MAC_LENGTH = 4 * LENGTH_SCALING;
 
@@ -608,41 +644,52 @@
 
         public AtMac(int lengthInBytes, ByteBuffer byteBuffer)
                 throws EapSimAkaInvalidAttributeException {
-            super(EAP_AT_MAC, lengthInBytes);
+            super(EAP_AT_MAC, lengthInBytes, byteBuffer);
 
             if (lengthInBytes != ATTR_LENGTH) {
                 throw new EapSimAkaInvalidAttributeException("Invalid Length specified");
             }
 
-            // next two bytes are reserved (RFC 4186 Section 10.14)
-            byteBuffer.get(new byte[RESERVED_BYTES]);
-
             mac = new byte[MAC_LENGTH];
             byteBuffer.get(mac);
         }
 
-        // Used for calculating MACs. Per RFC 4186 Section 10.14, the MAC should be calculated over
-        // the entire packet, with the value field of the MAC attribute set to zero.
+        // Constructs an AtMac with an empty MAC and empty RESERVED bytes. Should only be used for
+        // calculating MACs in outbound messages.
         public AtMac() throws EapSimAkaInvalidAttributeException {
-            super(EAP_AT_MAC, ATTR_LENGTH);
-            mac = new byte[MAC_LENGTH];
+            this(new byte[MAC_LENGTH]);
         }
 
         public AtMac(byte[] mac) throws EapSimAkaInvalidAttributeException {
-            super(EAP_AT_MAC, ATTR_LENGTH);
-            this.mac = mac;
+            this(new byte[RESERVED_BYTES_LEN], mac);
+        }
+
+        @VisibleForTesting
+        public AtMac(byte[] reservedBytes, byte[] mac) throws EapSimAkaInvalidAttributeException {
+            super(EAP_AT_MAC, ATTR_LENGTH, reservedBytes);
 
             if (mac.length != MAC_LENGTH) {
                 throw new EapSimAkaInvalidAttributeException("Invalid length for MAC");
             }
+            this.mac = mac;
         }
 
         @Override
         public void encode(ByteBuffer byteBuffer) {
-            encodeAttributeHeader(byteBuffer);
-            byteBuffer.put(new byte[RESERVED_BYTES]);
+            super.encode(byteBuffer);
+
             byteBuffer.put(mac);
         }
+
+        /**
+         * Returns a copy of this AtMac with the MAC cleared (and the reserved bytes preserved).
+         *
+         * <p>Per RFC 4186 Section 10.14, the MAC should be calculated over the entire packet, with
+         * the value field of the MAC attribute set to zero.
+         */
+        public AtMac getAtMacWithMacCleared() throws EapSimAkaInvalidAttributeException {
+            return new AtMac(reservedBytes, new byte[MAC_LENGTH]);
+        }
     }
 
     /**
@@ -712,23 +759,20 @@
      *
      * <p>This Nonce is generated by the server and used for fast re-authentication only.
      */
-    public static class AtNonceS extends EapSimAkaAttribute {
+    public static class AtNonceS extends EapSimAkaReservedBytesAttribute {
         private static final int ATTR_LENGTH = 5 * LENGTH_SCALING;
         private static final int NONCE_S_LENGTH = 4 * LENGTH_SCALING;
-        private static final int RESERVED_BYTES = 2;
 
         public final byte[] nonceS = new byte[NONCE_S_LENGTH];
 
         public AtNonceS(int lengthInBytes, ByteBuffer byteBuffer)
                 throws EapSimAkaInvalidAttributeException {
-            super(EAP_AT_NONCE_S, lengthInBytes);
+            super(EAP_AT_NONCE_S, lengthInBytes, byteBuffer);
 
             if (lengthInBytes != ATTR_LENGTH) {
                 throw new EapSimAkaInvalidAttributeException("Invalid Length specified");
             }
 
-            // next two bytes are reserved (RFC 4186 Section 10.17)
-            byteBuffer.get(new byte[RESERVED_BYTES]);
             byteBuffer.get(nonceS);
         }
 
@@ -745,8 +789,8 @@
 
         @Override
         public void encode(ByteBuffer byteBuffer) {
-            encodeAttributeHeader(byteBuffer);
-            byteBuffer.put(new byte[RESERVED_BYTES]);
+            super.encode(byteBuffer);
+
             byteBuffer.put(nonceS);
         }
     }
@@ -888,24 +932,20 @@
     /**
      * AtAutn represents the AT_AUTN attribute defined in RFC 4187#10.7
      */
-    public static class AtAutn extends EapSimAkaAttribute {
+    public static class AtAutn extends EapSimAkaReservedBytesAttribute {
         private static final int ATTR_LENGTH = 5 * LENGTH_SCALING;
         private static final int AUTN_LENGTH = 16;
-        private static final int RESERVED_BYTES = 2;
 
         public final byte[] autn = new byte[AUTN_LENGTH];
 
         public AtAutn(int lengthInBytes, ByteBuffer byteBuffer)
                 throws EapSimAkaInvalidAttributeException {
-            super(EAP_AT_AUTN, lengthInBytes);
+            super(EAP_AT_AUTN, lengthInBytes, byteBuffer);
 
             if (lengthInBytes != ATTR_LENGTH) {
                 throw new EapSimAkaInvalidAttributeException("Length must be 20B");
             }
 
-            // next two bytes are reserved (RFC 4187#10.7)
-            byteBuffer.get(new byte[RESERVED_BYTES]);
-
             byteBuffer.get(autn);
         }
 
@@ -922,8 +962,8 @@
 
         @Override
         public void encode(ByteBuffer byteBuffer) {
-            encodeAttributeHeader(byteBuffer);
-            byteBuffer.put(new byte[RESERVED_BYTES]);
+            super.encode(byteBuffer);
+
             byteBuffer.put(autn);
         }
     }
diff --git a/src/java/com/android/internal/net/eap/message/simaka/EapSimAkaTypeData.java b/src/java/com/android/internal/net/eap/message/simaka/EapSimAkaTypeData.java
index 56d2447..b90cd0b 100644
--- a/src/java/com/android/internal/net/eap/message/simaka/EapSimAkaTypeData.java
+++ b/src/java/com/android/internal/net/eap/message/simaka/EapSimAkaTypeData.java
@@ -39,19 +39,30 @@
  */
 public abstract class EapSimAkaTypeData {
     private static final int MIN_LEN_BYTES = 3; // subtype (1B) + reserved bytes (2B)
-    private static final int RESERVED_BYTES = 2; // RFC 4186#8.1, RFC 4187#8.1
+    private static final int RESERVED_BYTES_LEN = 2; // RFC 4186#8.1, RFC 4187#8.1
 
     public final int eapSubtype;
 
+    /** Save (but ignore) the 2B reserved section after EAP-Type and EAP-SIM/AKA subtype. */
+    final byte[] mReservedBytes;
+
     // LinkedHashMap used to preserve encoded ordering of attributes. This is necessary for checking
     // the MAC value for the message
     public final LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap;
 
+    protected EapSimAkaTypeData(
+            int eapSubType, LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap) {
+        this(eapSubType, attributeMap, new byte[RESERVED_BYTES_LEN]);
+    }
+
     public EapSimAkaTypeData(
             int eapSubType,
-            LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap) {
+            LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap,
+            byte[] reservedBytes) {
         this.eapSubtype = eapSubType;
         this.attributeMap = attributeMap;
+
+        mReservedBytes = reservedBytes.clone();
     }
 
     /**
@@ -69,7 +80,7 @@
         output.put((byte) eapSubtype);
 
         // two reserved bytes (RFC 4186#8.1, RFC 4187#8.1)
-        output.put(new byte[RESERVED_BYTES]);
+        output.put(mReservedBytes);
 
         for (EapSimAkaAttribute attribute : attributeMap.values()) {
             attribute.encode(output);
@@ -118,7 +129,8 @@
                 }
 
                 // next two bytes are reserved (RFC 4186#8.1, RFC 4187#8.1)
-                byteBuffer.get(new byte[RESERVED_BYTES]);
+                byte[] reservedBytes = new byte[RESERVED_BYTES_LEN];
+                byteBuffer.get(reservedBytes);
 
                 // read attributes
                 LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap = new LinkedHashMap<>();
@@ -138,7 +150,7 @@
                     attributeMap.put(attribute.attributeType, attribute);
                 }
 
-                T eapSimAkaTypeData = getInstance(eapSubType, attributeMap);
+                T eapSimAkaTypeData = getInstance(eapSubType, attributeMap, reservedBytes);
 
                 logDecodedEapSimAkaTypeData(eapSimAkaTypeData);
 
@@ -157,7 +169,8 @@
 
         protected abstract T getInstance(
                 int eapSubType,
-                LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap);
+                LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap,
+                byte[] reservedBytes);
 
         private void logDecodedEapSimAkaTypeData(EapSimAkaTypeData eapSimAkaTypeData) {
             StringBuilder msg = new StringBuilder();
diff --git a/src/java/com/android/internal/net/eap/message/simaka/EapSimTypeData.java b/src/java/com/android/internal/net/eap/message/simaka/EapSimTypeData.java
index ff1be60..09e03c7 100644
--- a/src/java/com/android/internal/net/eap/message/simaka/EapSimTypeData.java
+++ b/src/java/com/android/internal/net/eap/message/simaka/EapSimTypeData.java
@@ -67,6 +67,13 @@
         super(eapSubType, attributeMap);
     }
 
+    private EapSimTypeData(
+            int eapSubType,
+            LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap,
+            byte[] reservedBytes) {
+        super(eapSubType, attributeMap, reservedBytes);
+    }
+
     public EapSimTypeData(int eapSubtype, List<EapSimAkaAttribute> attributes) {
         super(eapSubtype, new LinkedHashMap<>());
 
@@ -118,8 +125,9 @@
         @Override
         protected EapSimTypeData getInstance(
                 int eapSubtype,
-                LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap) {
-            return new EapSimTypeData(eapSubtype, attributeMap);
+                LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap,
+                byte[] reservedBytes) {
+            return new EapSimTypeData(eapSubtype, attributeMap, reservedBytes);
         }
     }
 }
diff --git a/src/java/com/android/internal/net/eap/statemachine/EapSimAkaMethodStateMachine.java b/src/java/com/android/internal/net/eap/statemachine/EapSimAkaMethodStateMachine.java
index b2459ab..8089ea7 100644
--- a/src/java/com/android/internal/net/eap/statemachine/EapSimAkaMethodStateMachine.java
+++ b/src/java/com/android/internal/net/eap/statemachine/EapSimAkaMethodStateMachine.java
@@ -243,7 +243,7 @@
 
         // cache original Mac so it can be restored after calculating the Mac
         AtMac originalMac = (AtMac) typeData.attributeMap.get(EAP_AT_MAC);
-        typeData.attributeMap.put(EAP_AT_MAC, new AtMac());
+        typeData.attributeMap.put(EAP_AT_MAC, originalMac.getAtMacWithMacCleared());
 
         byte[] typeDataWithEmptyMac = typeData.encode();
         EapData eapData = new EapData(getEapMethod(), typeDataWithEmptyMac);
diff --git a/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapAkaPrimeTypeDataTest.java b/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapAkaPrimeTypeDataTest.java
index 6a9e517..d5aa9d1 100644
--- a/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapAkaPrimeTypeDataTest.java
+++ b/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapAkaPrimeTypeDataTest.java
@@ -56,14 +56,25 @@
     private static final byte[] AUTN_BYTES = hexStringToByteArray(AUTN);
     private static final String MAC = "95FEB9E70427F34B4FAC8F2C7A65A302";
     private static final byte[] MAC_BYTES = hexStringToByteArray(MAC);
+
     private static final byte[] EAP_AKA_PRIME_CHALLENGE_REQUEST =
             hexStringToByteArray(
+                    "010A0B" // Challenge | 2B padding
+                            + "01051A1B" + RAND // AT_RAND attribute
+                            + "02052A2B" + AUTN // AT_AUTN attribute
+                            + "1704000B" + NETWORK_NAME_HEX + "00" // AT_KDF_INPUT
+                            + "18010001" // AT_KDF
+                            + "0B053A3B" + MAC); // AT_MAC attribute
+
+    private static final byte[] EAP_AKA_PRIME_CHALLENGE_REQUEST_EMPTY_RESERVED =
+            hexStringToByteArray(
                     "010000" // Challenge | 2B padding
                             + "01050000" + RAND // AT_RAND attribute
                             + "02050000" + AUTN // AT_AUTN attribute
                             + "1704000B" + NETWORK_NAME_HEX + "00" // AT_KDF_INPUT
                             + "18010001" // AT_KDF
                             + "0B050000" + MAC); // AT_MAC attribute
+
     private static final byte[] EAP_AKA_PRIME_MULTIPLE_AT_KDF =
             hexStringToByteArray(
                     "010000" // Challenge | 2B padding
@@ -117,6 +128,15 @@
     }
 
     @Test
+    public void testDecodeEncode() {
+        DecodeResult<EapAkaTypeData> result =
+                mTypeDataDecoder.decode(EAP_AKA_PRIME_CHALLENGE_REQUEST);
+        assertTrue(result.isSuccessfulDecode());
+
+        assertArrayEquals(EAP_AKA_PRIME_CHALLENGE_REQUEST, result.eapTypeData.encode());
+    }
+
+    @Test
     public void testDecodeMultipleAtKdfAttributes() {
         DecodeResult<EapAkaTypeData> result =
                 mTypeDataDecoder.decode(EAP_AKA_PRIME_MULTIPLE_AT_KDF);
@@ -137,6 +157,6 @@
                 new EapAkaPrimeTypeData(EAP_AKA_CHALLENGE, attributes);
 
         byte[] result = eapAkaPrimeTypeData.encode();
-        assertArrayEquals(EAP_AKA_PRIME_CHALLENGE_REQUEST, result);
+        assertArrayEquals(EAP_AKA_PRIME_CHALLENGE_REQUEST_EMPTY_RESERVED, result);
     }
 }
diff --git a/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapAkaTypeDataTest.java b/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapAkaTypeDataTest.java
index b2d89d1..cb27cd1 100644
--- a/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapAkaTypeDataTest.java
+++ b/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapAkaTypeDataTest.java
@@ -68,12 +68,12 @@
     private static final byte[] MAC_BYTES = hexStringToByteArray(MAC);
     private static final byte[] EAP_AKA_REQUEST =
             hexStringToByteArray(
-                    "010000" // Challenge | 2B padding
-                            + "01050000" + RAND // AT_RAND attribute
-                            + "02050000" + AUTN // AT_AUTN attribute
+                    "010A0B" // Challenge | 2B reserved
+                            + "01051A1B" + RAND // AT_RAND attribute
+                            + "02052A2B" + AUTN // AT_AUTN attribute
                             + "8B010002" // AT_RESULT_IND attribute (TS 124 302#8.2.3.1)
-                            + "0B050000" + MAC // AT_MAC attribute
-                            + "86010000"); // AT_CHECKCODE attribute
+                            + "0B053A3B" + MAC // AT_MAC attribute
+                            + "86014A4B"); // AT_CHECKCODE attribute
 
     private EapAkaTypeDataDecoder mEapAkaTypeDataDecoder;
 
@@ -106,6 +106,14 @@
     }
 
     @Test
+    public void testDecodeEncode() {
+        DecodeResult<EapAkaTypeData> result = mEapAkaTypeDataDecoder.decode(EAP_AKA_REQUEST);
+        assertTrue(result.isSuccessfulDecode());
+
+        assertArrayEquals(EAP_AKA_REQUEST, result.eapTypeData.encode());
+    }
+
+    @Test
     public void testDecodeWithOptionalAttributes() {
         DecodeResult<EapAkaTypeData> result = mEapAkaTypeDataDecoder.decode(EAP_AKA_REQUEST);
 
diff --git a/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapSimTypeDataTest.java b/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapSimTypeDataTest.java
index 678a812..bd6352a 100644
--- a/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapSimTypeDataTest.java
+++ b/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/EapSimTypeDataTest.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.net.eap.message.simaka;
 
+import static com.android.internal.net.TestUtils.hexStringToByteArray;
 import static com.android.internal.net.eap.message.EapTestMessageDefinitions.EAP_SIM_START_DUPLICATE_ATTRIBUTES;
 import static com.android.internal.net.eap.message.EapTestMessageDefinitions.EAP_SIM_START_SUBTYPE;
 import static com.android.internal.net.eap.message.EapTestMessageDefinitions.INVALID_SUBTYPE;
@@ -24,6 +25,8 @@
 import static com.android.internal.net.eap.message.EapTestMessageDefinitions.TYPE_DATA_INVALID_AT_RAND;
 import static com.android.internal.net.eap.message.simaka.EapSimAkaAttribute.EAP_AT_PERMANENT_ID_REQ;
 import static com.android.internal.net.eap.message.simaka.EapSimAkaAttribute.EAP_AT_VERSION_LIST;
+import static com.android.internal.net.eap.message.simaka.attributes.EapTestAttributeDefinitions.RAND_1;
+import static com.android.internal.net.eap.message.simaka.attributes.EapTestAttributeDefinitions.RAND_2;
 
 import static junit.framework.TestCase.fail;
 
@@ -52,6 +55,12 @@
     private static final int EAP_SIM_START = 10;
     private static final int INVALID_SUBTYPE_INT = -1;
 
+    private static final byte[] EAP_SIM_CHALLENGE_REQUEST =
+            hexStringToByteArray(
+                    "0b0A0B" // Challenge | 2B padding
+                            + "01091A1B" + RAND_1 + RAND_2 // EAP-SIM AT_RAND attribute
+                            + "0B052A2BFFEEDDCCBBAA998877665544332211FF"); // AT_MAC attribute
+
     private EapSimTypeDataDecoder mEapSimTypeDataDecoder;
 
     @Before
@@ -100,6 +109,15 @@
     }
 
     @Test
+    public void testDecodeEncode() {
+        DecodeResult<EapSimTypeData> result =
+                mEapSimTypeDataDecoder.decode(EAP_SIM_CHALLENGE_REQUEST);
+        assertTrue(result.isSuccessfulDecode());
+
+        assertArrayEquals(EAP_SIM_CHALLENGE_REQUEST, result.eapTypeData.encode());
+    }
+
+    @Test
     public void testDecodeNullTypeData() {
         DecodeResult<EapSimTypeData> result = mEapSimTypeDataDecoder.decode(null);
         assertFalse(result.isSuccessfulDecode());
diff --git a/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtMacTest.java b/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtMacTest.java
index 82b066d..042519a 100644
--- a/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtMacTest.java
+++ b/tests/iketests/src/java/com/android/internal/net/eap/message/simaka/attributes/AtMacTest.java
@@ -43,6 +43,7 @@
     private static final int MAC_LENGTH = 16;
     private static final byte[] MAC_BYTES = hexStringToByteArray(MAC);
     private static final byte[] INVALID_MAC = {(byte) 1, (byte) 2, (byte) 3};
+    private static final byte[] RESERVED_BYTES = {(byte) 0x0A, (byte) 0x0B};
 
     private EapSimAkaAttributeFactory mAttributeFactory;
 
@@ -107,4 +108,13 @@
         atMac.encode(result);
         assertArrayEquals(AT_MAC, result.array());
     }
+
+    @Test
+    public void testGetAtMacWithMacCleared() throws Exception {
+        AtMac original = new AtMac(RESERVED_BYTES, MAC_BYTES);
+
+        AtMac clearedMac = original.getAtMacWithMacCleared();
+        assertArrayEquals(RESERVED_BYTES, clearedMac.reservedBytes);
+        assertArrayEquals(new byte[MAC_LENGTH], clearedMac.mac);
+    }
 }