Handle competing IKE Requests in MobikeLocalInfo.

This CL updates IkeSessionStateMachine to handle competing IKE Requests
when in the MobikeLocalInfo state. Delete requests will be respected,
but all other peer requests will receive a temporary failure response
(to allow the UPDATE_SA_ADDRESSES exchange to proceed).

Bug: 172013873
Test: atest FrameworksIkeTests
Change-Id: I6b961e5cab6b31508cf69fa61fc35edb19d4773e
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 aff9fe8..43896f4 100644
--- a/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java
+++ b/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java
@@ -5090,7 +5090,18 @@
         @Override
         public void handleRequestIkeMessage(
                 IkeMessage msg, int ikeExchangeSubType, Message message) {
-            // TODO(b/172014224): handle competing IKE req (Delete or otherwise)
+            switch (ikeExchangeSubType) {
+                case IKE_EXCHANGE_SUBTYPE_DELETE_IKE:
+                    handleDeleteSessionRequest(msg);
+                    break;
+
+                default:
+                    // Send a temporary failure for all non-DELETE_IKE requests
+                    buildAndSendErrorNotificationResponse(
+                            mCurrentIkeSaRecord,
+                            msg.ikeHeader.messageId,
+                            ERROR_TYPE_TEMPORARY_FAILURE);
+            }
         }
 
         @Override
diff --git a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java
index 9b0724c..e4f4919 100644
--- a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java
+++ b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java
@@ -1316,6 +1316,10 @@
                 .encryptAndEncode(any(), any(), any(), any(), anyBoolean(), anyInt());
     }
 
+    private void resetSpyUserCbExecutor() {
+        reset(mSpyUserCbExecutor);
+    }
+
     @Test
     public void testQuit() {
         mIkeSessionStateMachine.quit();
@@ -4424,6 +4428,11 @@
     @Test
     public void testDeleteIkeRemoteDelete() throws Exception {
         setupIdleStateMachine();
+
+        verifyIkeDeleteRequestHandled();
+    }
+
+    private void verifyIkeDeleteRequestHandled() throws Exception {
         mIkeSessionStateMachine.sendMessage(
                 IkeSessionStateMachine.CMD_RECEIVE_IKE_PACKET,
                 makeDeleteIkeRequest(mSpyCurrentIkeSaRecord));
@@ -5823,4 +5832,48 @@
         verify(mMockIkeNattKeepalive).stop();
         assertNull(mIkeSessionStateMachine.mIkeNattKeepalive);
     }
+
+    @Test
+    public void testMobikeLocalInfoHandlesDeleteRequest() throws Exception {
+        setupIdleStateMachineWithMobike();
+
+        mIkeSessionStateMachine.sendMessage(
+                CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mMobikeLocalInfo);
+        mLooper.dispatchAll();
+
+        // Reset to ignore UPDATE_SA_ADDRESSES req sent when entering MobikeLocalInfo
+        resetMockIkeMessageHelper();
+
+        // Reset to ignore IkeSessionCallback#onOpened from setting up the state machine
+        resetSpyUserCbExecutor();
+
+        verifyIkeDeleteRequestHandled();
+    }
+
+    @Test
+    public void testMobikeLocalInfoHandlesNonDeleteRequest() throws Exception {
+        setupIdleStateMachineWithMobike();
+
+        mIkeSessionStateMachine.sendMessage(
+                CMD_FORCE_TRANSITION, mIkeSessionStateMachine.mMobikeLocalInfo);
+        mLooper.dispatchAll();
+
+        // Reset to ignore UPDATE_SA_ADDRESSES req sent when entering MobikeLocalInfo
+        resetMockIkeMessageHelper();
+
+        mIkeSessionStateMachine.sendMessage(
+                CMD_RECEIVE_IKE_PACKET, makeRoutabilityCheckIkeRequest());
+        mLooper.dispatchAll();
+
+        verifyIncrementRemoteReqMsgId();
+
+        List<IkePayload> respPayloads = verifyOutInfoMsgHeaderAndGetPayloads(true /* isResp */);
+        assertEquals(1, respPayloads.size());
+        IkeNotifyPayload notifyPayload = (IkeNotifyPayload) respPayloads.get(0);
+        assertEquals(ERROR_TYPE_TEMPORARY_FAILURE, notifyPayload.notifyType);
+
+        assertEquals(
+                mIkeSessionStateMachine.mMobikeLocalInfo,
+                mIkeSessionStateMachine.getCurrentState());
+    }
 }