Merge "Cleanup of IkeSessionPskTest"
diff --git a/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeSessionPskTest.java b/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeSessionPskTest.java
index 336d12d..fb93398 100644
--- a/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeSessionPskTest.java
+++ b/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeSessionPskTest.java
@@ -99,19 +99,17 @@
                     .addInternalAddressRequest(AF_INET6)
                     .build();
 
-    private IkeSessionParams createIkeSessionParams(InetAddress mRemoteAddress) {
-        return new IkeSessionParams.Builder(sContext)
-                .setNetwork(mTunNetwork)
-                .setServerHostname(mRemoteAddress.getHostAddress())
-                .addSaProposal(SaProposalTest.buildIkeSaProposalWithNormalModeCipher())
-                .addSaProposal(SaProposalTest.buildIkeSaProposalWithCombinedModeCipher())
-                .setLocalIdentification(new IkeFqdnIdentification(LOCAL_HOSTNAME))
-                .setRemoteIdentification(new IkeFqdnIdentification(REMOTE_HOSTNAME))
-                .setAuthPsk(IKE_PSK)
-                .build();
-    }
-
-    private IkeSession openIkeSession(IkeSessionParams ikeParams) {
+    private IkeSession openIkeSessionWithRemoteAddress(InetAddress remoteAddress) {
+        IkeSessionParams ikeParams =
+                new IkeSessionParams.Builder(sContext)
+                        .setNetwork(mTunNetwork)
+                        .setServerHostname(remoteAddress.getHostAddress())
+                        .addSaProposal(SaProposalTest.buildIkeSaProposalWithNormalModeCipher())
+                        .addSaProposal(SaProposalTest.buildIkeSaProposalWithCombinedModeCipher())
+                        .setLocalIdentification(new IkeFqdnIdentification(LOCAL_HOSTNAME))
+                        .setRemoteIdentification(new IkeFqdnIdentification(REMOTE_HOSTNAME))
+                        .setAuthPsk(IKE_PSK)
+                        .build();
         return new IkeSession(
                 sContext,
                 ikeParams,
@@ -126,7 +124,7 @@
         if (!hasTunnelsFeature()) return;
 
         // Open IKE Session
-        IkeSession ikeSession = openIkeSession(createIkeSessionParams(mRemoteAddress));
+        IkeSession ikeSession = openIkeSessionWithRemoteAddress(mRemoteAddress);
         int expectedMsgId = 0;
         mTunUtils.awaitReqAndInjectResp(
                 IKE_INIT_SPI,
@@ -167,6 +165,9 @@
         assertTrue(firstChildConfig.getInternalDnsServers().isEmpty());
         assertTrue(firstChildConfig.getInternalDhcpServers().isEmpty());
 
+        assertNotNull(mFirstChildSessionCallback.awaitNextCreatedIpSecTransform());
+        assertNotNull(mFirstChildSessionCallback.awaitNextCreatedIpSecTransform());
+
         // Open additional Child Session
         TestChildSessionCallback additionalChildCb = new TestChildSessionCallback();
         ikeSession.openChildSession(CHILD_PARAMS, additionalChildCb);
@@ -183,9 +184,12 @@
                 Arrays.asList(EXPECTED_INBOUND_TS), firstChildConfig.getInboundTrafficSelectors());
         assertEquals(Arrays.asList(DEFAULT_V4_TS), firstChildConfig.getOutboundTrafficSelectors());
         assertTrue(additionalChildConfig.getInternalAddresses().isEmpty());
-        assertTrue(firstChildConfig.getInternalSubnets().isEmpty());
-        assertTrue(firstChildConfig.getInternalDnsServers().isEmpty());
-        assertTrue(firstChildConfig.getInternalDhcpServers().isEmpty());
+        assertTrue(additionalChildConfig.getInternalSubnets().isEmpty());
+        assertTrue(additionalChildConfig.getInternalDnsServers().isEmpty());
+        assertTrue(additionalChildConfig.getInternalDhcpServers().isEmpty());
+
+        assertNotNull(additionalChildCb.awaitNextCreatedIpSecTransform());
+        assertNotNull(additionalChildCb.awaitNextCreatedIpSecTransform());
 
         // Close additional Child Session
         ikeSession.closeChildSession(additionalChildCb);
@@ -195,6 +199,8 @@
                 true /* expectedUseEncap */,
                 hexStringToByteArray(SUCCESS_DELETE_CHILD_RESP));
 
+        assertNotNull(additionalChildCb.awaitNextDeletedIpSecTransform());
+        assertNotNull(additionalChildCb.awaitNextDeletedIpSecTransform());
         additionalChildCb.awaitOnClosed();
 
         // Close IKE Session
@@ -205,10 +211,12 @@
                 true /* expectedUseEncap */,
                 hexStringToByteArray(SUCCESS_DELETE_IKE_RESP));
 
+        assertNotNull(mFirstChildSessionCallback.awaitNextDeletedIpSecTransform());
+        assertNotNull(mFirstChildSessionCallback.awaitNextDeletedIpSecTransform());
         mFirstChildSessionCallback.awaitOnClosed();
         mIkeSessionCallback.awaitOnClosed();
 
-        // TODO: verify IpSecTransform pair is created and deleted
+        // TODO: verify created and deleted IpSecTransform pair and their directions
     }
 
     @Test
@@ -216,7 +224,7 @@
         if (!hasTunnelsFeature()) return;
 
         // Open IKE Session
-        IkeSession ikeSession = openIkeSession(createIkeSessionParams(mRemoteAddress));
+        IkeSession ikeSession = openIkeSessionWithRemoteAddress(mRemoteAddress);
         int expectedMsgId = 0;
         mTunUtils.awaitReqAndInjectResp(
                 IKE_INIT_SPI,
@@ -231,7 +239,6 @@
                 hexStringToByteArray(SUCCESS_IKE_AUTH_RESP));
 
         ikeSession.kill();
-
         mFirstChildSessionCallback.awaitOnClosed();
         mIkeSessionCallback.awaitOnClosed();
     }
@@ -242,7 +249,7 @@
                 "46B8ECA1E0D72A180000000000000000292022200000000000000024000000080000000E";
 
         // Open IKE Session
-        IkeSession ikeSession = openIkeSession(createIkeSessionParams(mRemoteAddress));
+        IkeSession ikeSession = openIkeSessionWithRemoteAddress(mRemoteAddress);
         int expectedMsgId = 0;
         mTunUtils.awaitReqAndInjectResp(
                 IKE_INIT_SPI,
@@ -250,6 +257,8 @@
                 false /* expectedUseEncap */,
                 hexStringToByteArray(ikeInitFailRespHex));
 
+        mFirstChildSessionCallback.awaitOnClosed();
+
         IkeException exception = mIkeSessionCallback.awaitOnClosedException();
         assertNotNull(exception);
         assertTrue(exception instanceof IkeProtocolException);
diff --git a/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeSessionTestBase.java b/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeSessionTestBase.java
index 1c1ffc9..279d088 100644
--- a/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeSessionTestBase.java
+++ b/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeSessionTestBase.java
@@ -40,7 +40,6 @@
 import android.os.Binder;
 import android.os.ParcelFileDescriptor;
 import android.platform.test.annotations.AppModeFull;
-import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -66,6 +65,13 @@
  *
  * <p>Subclasses MUST explicitly call #setUpTestNetwork and #tearDownTestNetwork to be able to use
  * the test network
+ *
+ * <p>All IKE Sessions running in test mode will generate SPIs deterministically. That is to say
+ * each IKE Session will always generate the same IKE INIT SPI and test vectors are generated based
+ * on this deterministic IKE SPI. Each test will use different local and remote addresses to avoid
+ * the case that the next test try to allocate the same SPI before the previous test has released
+ * it, since SPI resources are not released in testing thread. Similarly, each test MUST use
+ * different Network instances to avoid sharing the same IkeSocket and hitting IKE SPI collision.
  */
 @RunWith(AndroidJUnit4.class)
 @AppModeFull(reason = "MANAGE_TEST_NETWORKS permission can't be granted to instant apps")
@@ -117,7 +123,7 @@
         InstrumentationRegistry.getInstrumentation()
                 .getUiAutomation()
                 .adoptShellPermissionIdentity();
-        sTNM = (TestNetworkManager) sContext.getSystemService(Context.TEST_NETWORK_SERVICE);
+        sTNM = sContext.getSystemService(TestNetworkManager.class);
 
         // Under normal circumstances, the MANAGE_IPSEC_TUNNELS appop would be auto-granted, and
         // a standard permission is insufficient. So we shell out the appop, to give us the
@@ -150,10 +156,6 @@
     @After
     public void tearDown() throws Exception {
         tearDownTestNetwork();
-
-        resetNextAvailableAddress(NEXT_AVAILABLE_IP4_ADDR_LOCAL, INITIAL_AVAILABLE_IP4_ADDR_LOCAL);
-        resetNextAvailableAddress(
-                NEXT_AVAILABLE_IP4_ADDR_REMOTE, INITIAL_AVAILABLE_IP4_ADDR_REMOTE);
     }
 
     void setUpTestNetwork(InetAddress localAddr) throws Exception {
@@ -186,9 +188,8 @@
                             pkg, // Package name
                             opName, // Appop
                             (allow ? "allow" : "deny")); // Action
-            Log.d("IKE", "CTS setAppOp cmd " + cmd);
 
-            String result = SystemUtil.runShellCommand(cmd);
+            SystemUtil.runShellCommand(cmd);
         }
     }
 
@@ -230,6 +231,7 @@
         }
     }
 
+    /** Testing callback that allows caller to block current thread until a method get called */
     static class TestIkeSessionCallback implements IkeSessionCallback {
         private CompletableFuture<IkeSessionConfiguration> mFutureIkeConfig =
                 new CompletableFuture<>();
@@ -283,6 +285,7 @@
         }
     }
 
+    /** Testing callback that allows caller to block current thread until a method get called */
     static class TestChildSessionCallback implements ChildSessionCallback {
         private CompletableFuture<ChildSessionConfiguration> mFutureChildConfig =
                 new CompletableFuture<>();
diff --git a/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeTunUtils.java b/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeTunUtils.java
index 5a8258d..f52b88b 100644
--- a/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeTunUtils.java
+++ b/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeTunUtils.java
@@ -121,7 +121,9 @@
                             + " and message ID "
                             + expectedMsgId);
         }
-        return null;
+
+        throw new IllegalStateException(
+                "Hit an impossible case where fail() didn't throw an exception");
     }
 
     private static boolean isIke(