• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package android.ipsec.ike.cts;
17 
18 import static android.net.ipsec.ike.IkeSessionConfiguration.EXTENSION_TYPE_FRAGMENTATION;
19 import static android.system.OsConstants.AF_INET;
20 import static android.system.OsConstants.AF_INET6;
21 
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertNotNull;
24 import static org.junit.Assert.assertTrue;
25 
26 import android.annotation.NonNull;
27 import android.app.AppOpsManager;
28 import android.content.pm.PackageManager;
29 import android.ipsec.ike.cts.IkeTunUtils.PortPair;
30 import android.net.InetAddresses;
31 import android.net.IpSecManager;
32 import android.net.IpSecTransform;
33 import android.net.LinkAddress;
34 import android.net.ipsec.ike.ChildSessionCallback;
35 import android.net.ipsec.ike.ChildSessionConfiguration;
36 import android.net.ipsec.ike.IkeSessionCallback;
37 import android.net.ipsec.ike.IkeSessionConfiguration;
38 import android.net.ipsec.ike.IkeSessionConnectionInfo;
39 import android.net.ipsec.ike.IkeTrafficSelector;
40 import android.net.ipsec.ike.TransportModeChildSessionParams;
41 import android.net.ipsec.ike.TunnelModeChildSessionParams;
42 import android.net.ipsec.ike.exceptions.IkeException;
43 import android.os.UserHandle;
44 import android.platform.test.annotations.AppModeFull;
45 
46 import androidx.test.ext.junit.runners.AndroidJUnit4;
47 
48 import com.android.compatibility.common.util.SystemUtil;
49 import com.android.internal.net.annotations.PolicyDirection;
50 import com.android.net.module.util.ArrayTrackRecord;
51 
52 import org.junit.After;
53 import org.junit.Before;
54 import org.junit.runner.RunWith;
55 
56 import java.net.Inet4Address;
57 import java.net.Inet6Address;
58 import java.net.InetAddress;
59 import java.util.ArrayList;
60 import java.util.HashSet;
61 import java.util.List;
62 import java.util.Objects;
63 import java.util.Set;
64 import java.util.concurrent.CompletableFuture;
65 import java.util.concurrent.Executor;
66 import java.util.concurrent.Executors;
67 import java.util.concurrent.TimeUnit;
68 
69 /**
70  * Package private base class for testing IkeSessionParams and IKE exchanges.
71  *
72  * <p>Subclasses MUST explicitly call #setUpTestNetwork and #tearDownTestNetwork to be able to use
73  * the test network
74  *
75  * <p>All IKE Sessions running in test mode will generate SPIs deterministically. That is to say
76  * each IKE Session will always generate the same IKE INIT SPI and test vectors are generated based
77  * on this deterministic IKE SPI. Each test will use different local and remote addresses to avoid
78  * the case that the next test try to allocate the same SPI before the previous test has released
79  * it, since SPI resources are not released in testing thread. Similarly, each test MUST use
80  * different Network instances to avoid sharing the same IkeSocket and hitting IKE SPI collision.
81  */
82 @RunWith(AndroidJUnit4.class)
83 @AppModeFull(reason = "MANAGE_TEST_NETWORKS permission can't be granted to instant apps")
84 abstract class IkeSessionTestBase extends IkeTestNetworkBase {
85     // Package-wide common expected results that will be shared by all IKE/Child SA creation tests
86     static final String EXPECTED_REMOTE_APP_VERSION_EMPTY = "";
87     static final byte[] EXPECTED_PROTOCOL_ERROR_DATA_NONE = new byte[0];
88 
89     static final InetAddress EXPECTED_DNS_SERVERS_ONE =
90             InetAddresses.parseNumericAddress("8.8.8.8");
91     static final InetAddress EXPECTED_DNS_SERVERS_TWO =
92             InetAddresses.parseNumericAddress("8.8.4.4");
93 
94     static final InetAddress EXPECTED_INTERNAL_ADDR =
95             InetAddresses.parseNumericAddress("198.51.100.10");
96     static final LinkAddress EXPECTED_INTERNAL_LINK_ADDR =
97             new LinkAddress(EXPECTED_INTERNAL_ADDR, IP4_PREFIX_LEN);
98     static final InetAddress EXPECTED_INTERNAL_ADDR_V6 =
99             InetAddresses.parseNumericAddress("2001:db8::2");
100     static final LinkAddress EXPECTED_INTERNAL_LINK_ADDR_V6 =
101             new LinkAddress(EXPECTED_INTERNAL_ADDR_V6, IP6_PREFIX_LEN);
102 
103     static final IkeTrafficSelector TUNNEL_MODE_INBOUND_TS =
104             new IkeTrafficSelector(
105                     MIN_PORT, MAX_PORT, EXPECTED_INTERNAL_ADDR, EXPECTED_INTERNAL_ADDR);
106     static final IkeTrafficSelector TUNNEL_MODE_OUTBOUND_TS = DEFAULT_V4_TS;
107     static final IkeTrafficSelector TUNNEL_MODE_INBOUND_TS_V6 =
108             new IkeTrafficSelector(
109                     MIN_PORT, MAX_PORT, EXPECTED_INTERNAL_ADDR_V6, EXPECTED_INTERNAL_ADDR_V6);
110     static final IkeTrafficSelector TUNNEL_MODE_OUTBOUND_TS_V6 = DEFAULT_V6_TS;
111 
112     // This value is align with the test vectors hex that are generated in an IPv4 environment
113     static final IkeTrafficSelector TRANSPORT_MODE_OUTBOUND_TS =
114             new IkeTrafficSelector(
115                     MIN_PORT,
116                     MAX_PORT,
117                     InetAddresses.parseNumericAddress("10.138.0.2"),
118                     InetAddresses.parseNumericAddress("10.138.0.2"));
119 
120     static final long IKE_DETERMINISTIC_INITIATOR_SPI = Long.parseLong("46B8ECA1E0D72A18", 16);
121 
122     private static final int TIMEOUT_MS = 2000;
123 
124     // Constants to be used for providing different IP addresses for each tests
125     private static final byte IP_ADDR_LAST_BYTE_MAX = (byte) 100;
126     private static final byte[] INITIAL_AVAILABLE_IP4_ADDR_LOCAL =
127             InetAddresses.parseNumericAddress("192.0.2.1").getAddress();
128     private static final byte[] INITIAL_AVAILABLE_IP4_ADDR_REMOTE =
129             InetAddresses.parseNumericAddress("198.51.100.1").getAddress();
130     private static final byte[] NEXT_AVAILABLE_IP4_ADDR_LOCAL = INITIAL_AVAILABLE_IP4_ADDR_LOCAL;
131     private static final byte[] NEXT_AVAILABLE_IP4_ADDR_REMOTE = INITIAL_AVAILABLE_IP4_ADDR_REMOTE;
132 
133     private static final byte[] INITIAL_AVAILABLE_IP6_ADDR_LOCAL =
134             InetAddresses.parseNumericAddress("2a00:1000::0").getAddress();
135     private static final byte[] INITIAL_AVAILABLE_IP6_ADDR_REMOTE =
136             InetAddresses.parseNumericAddress("2404:6800:4004:820::2004").getAddress();
137     private static final byte[] NEXT_AVAILABLE_IP6_ADDR_LOCAL = INITIAL_AVAILABLE_IP6_ADDR_LOCAL;
138     private static final byte[] NEXT_AVAILABLE_IP6_ADDR_REMOTE = INITIAL_AVAILABLE_IP6_ADDR_REMOTE;
139 
140     TunNetworkContext mTunNetworkContext;
141 
142     InetAddress mLocalAddress;
143     InetAddress mRemoteAddress;
144 
145     Executor mUserCbExecutor;
146     TestIkeSessionCallback mIkeSessionCallback;
147     TestChildSessionCallback mFirstChildSessionCallback;
148 
149     @Before
setUp()150     public void setUp() throws Exception {
151         mLocalAddress = getNextAvailableIpv4AddressLocal();
152         mRemoteAddress = getNextAvailableIpv4AddressRemote();
153         mTunNetworkContext = new TunNetworkContext(mLocalAddress);
154 
155         mUserCbExecutor = Executors.newSingleThreadExecutor();
156         mIkeSessionCallback = new DefaultTestIkeSessionCallback();
157         mFirstChildSessionCallback = new DefaultTestChildSessionCallback();
158     }
159 
160     @After
tearDown()161     public void tearDown() throws Exception {
162         if (mTunNetworkContext != null) {
163             mTunNetworkContext.close();
164         }
165     }
166 
setAppOp(int appop, boolean allow)167     static void setAppOp(int appop, boolean allow) {
168         String opName = AppOpsManager.opToName(appop);
169         for (String pkg : new String[] {"com.android.shell", sContext.getPackageName()}) {
170             String cmd =
171                     String.format(
172                             "appops set --user %d %s %s %s",
173                             UserHandle.myUserId(), // user id
174                             pkg, // Package name
175                             opName, // Appop
176                             (allow ? "allow" : "deny")); // Action
177 
178             SystemUtil.runShellCommand(cmd);
179         }
180     }
181 
getNextAvailableIpv4AddressLocal()182     Inet4Address getNextAvailableIpv4AddressLocal() throws Exception {
183         return (Inet4Address)
184                 getNextAvailableAddress(
185                         NEXT_AVAILABLE_IP4_ADDR_LOCAL,
186                         INITIAL_AVAILABLE_IP4_ADDR_LOCAL,
187                         false /* isIp6 */);
188     }
189 
getNextAvailableIpv4AddressRemote()190     Inet4Address getNextAvailableIpv4AddressRemote() throws Exception {
191         return (Inet4Address)
192                 getNextAvailableAddress(
193                         NEXT_AVAILABLE_IP4_ADDR_REMOTE,
194                         INITIAL_AVAILABLE_IP4_ADDR_REMOTE,
195                         false /* isIp6 */);
196     }
197 
getNextAvailableIpv6AddressLocal()198     Inet6Address getNextAvailableIpv6AddressLocal() throws Exception {
199         return (Inet6Address)
200                 getNextAvailableAddress(
201                         NEXT_AVAILABLE_IP6_ADDR_LOCAL,
202                         INITIAL_AVAILABLE_IP6_ADDR_LOCAL,
203                         true /* isIp6 */);
204     }
205 
getNextAvailableIpv6AddressRemote()206     Inet6Address getNextAvailableIpv6AddressRemote() throws Exception {
207         return (Inet6Address)
208                 getNextAvailableAddress(
209                         NEXT_AVAILABLE_IP6_ADDR_REMOTE,
210                         INITIAL_AVAILABLE_IP6_ADDR_REMOTE,
211                         true /* isIp6 */);
212     }
213 
getNextAvailableAddress( byte[] nextAddressBytes, byte[] initialAddressBytes, boolean isIp6)214     InetAddress getNextAvailableAddress(
215             byte[] nextAddressBytes, byte[] initialAddressBytes, boolean isIp6) throws Exception {
216         int addressLen = isIp6 ? IP6_ADDRESS_LEN : IP4_ADDRESS_LEN;
217 
218         synchronized (nextAddressBytes) {
219             if (nextAddressBytes[addressLen - 1] == IP_ADDR_LAST_BYTE_MAX) {
220                 resetNextAvailableAddress(nextAddressBytes, initialAddressBytes);
221             }
222 
223             InetAddress address = InetAddress.getByAddress(nextAddressBytes);
224             nextAddressBytes[addressLen - 1]++;
225             return address;
226         }
227     }
228 
resetNextAvailableAddress(byte[] nextAddressBytes, byte[] initialAddressBytes)229     private void resetNextAvailableAddress(byte[] nextAddressBytes, byte[] initialAddressBytes) {
230         synchronized (nextAddressBytes) {
231             System.arraycopy(
232                     nextAddressBytes, 0, initialAddressBytes, 0, initialAddressBytes.length);
233         }
234     }
235 
buildTransportModeChildParamsWithTs( IkeTrafficSelector inboundTs, IkeTrafficSelector outboundTs)236     TransportModeChildSessionParams buildTransportModeChildParamsWithTs(
237             IkeTrafficSelector inboundTs, IkeTrafficSelector outboundTs) {
238         return new TransportModeChildSessionParams.Builder()
239                 .addSaProposal(SaProposalTest.buildChildSaProposalWithCombinedModeCipher())
240                 .addSaProposal(SaProposalTest.buildChildSaProposalWithNormalModeCipher())
241                 .addInboundTrafficSelectors(inboundTs)
242                 .addOutboundTrafficSelectors(outboundTs)
243                 .build();
244     }
245 
buildTransportModeChildParamsWithDefaultTs()246     TransportModeChildSessionParams buildTransportModeChildParamsWithDefaultTs() {
247         return new TransportModeChildSessionParams.Builder()
248                 .addSaProposal(SaProposalTest.buildChildSaProposalWithCombinedModeCipher())
249                 .addSaProposal(SaProposalTest.buildChildSaProposalWithNormalModeCipher())
250                 .build();
251     }
252 
buildTunnelModeChildSessionParams()253     TunnelModeChildSessionParams buildTunnelModeChildSessionParams() {
254         return new TunnelModeChildSessionParams.Builder()
255                 .addSaProposal(SaProposalTest.buildChildSaProposalWithNormalModeCipher())
256                 .addSaProposal(SaProposalTest.buildChildSaProposalWithCombinedModeCipher())
257                 .addInternalAddressRequest(AF_INET)
258                 .addInternalAddressRequest(AF_INET6)
259                 .build();
260     }
261 
performSetupIkeAndFirstChildBlocking(String ikeInitRespHex, String... ikeAuthRespHexes)262     PortPair performSetupIkeAndFirstChildBlocking(String ikeInitRespHex, String... ikeAuthRespHexes)
263             throws Exception {
264         return performSetupIkeAndFirstChildBlocking(
265                 ikeInitRespHex,
266                 1 /* expectedAuthReqPktCnt */,
267                 true /*expectedAuthUseEncap*/,
268                 ikeAuthRespHexes);
269     }
270 
performSetupIkeAndFirstChildBlocking( String ikeInitRespHex, boolean expectedAuthUseEncap, String... ikeAuthRespHexes)271     PortPair performSetupIkeAndFirstChildBlocking(
272             String ikeInitRespHex, boolean expectedAuthUseEncap, String... ikeAuthRespHexes)
273             throws Exception {
274         return performSetupIkeAndFirstChildBlocking(
275                 ikeInitRespHex,
276                 1 /* expectedAuthReqPktCnt */,
277                 expectedAuthUseEncap,
278                 ikeAuthRespHexes);
279     }
280 
performSetupIkeAndFirstChildBlocking( String ikeInitRespHex, int expectedAuthReqPktCnt, boolean expectedAuthUseEncap, String... ikeAuthRespHexes)281     PortPair performSetupIkeAndFirstChildBlocking(
282             String ikeInitRespHex,
283             int expectedAuthReqPktCnt,
284             boolean expectedAuthUseEncap,
285             String... ikeAuthRespHexes)
286             throws Exception {
287         mTunNetworkContext.tunUtils.awaitReqAndInjectResp(
288                 IKE_DETERMINISTIC_INITIATOR_SPI,
289                 0 /* expectedMsgId */,
290                 false /* expectedUseEncap */,
291                 ikeInitRespHex);
292 
293         byte[] ikeAuthReqPkt =
294                 mTunNetworkContext
295                         .tunUtils
296                         .awaitReqAndInjectResp(
297                                 IKE_DETERMINISTIC_INITIATOR_SPI,
298                                 1 /* expectedMsgId */,
299                                 expectedAuthUseEncap,
300                                 expectedAuthReqPktCnt,
301                                 ikeAuthRespHexes)
302                         .get(0);
303         return IkeTunUtils.getSrcDestPortPair(ikeAuthReqPkt);
304     }
305 
performCloseIkeBlocking(int expectedMsgId, String deleteIkeRespHex)306     void performCloseIkeBlocking(int expectedMsgId, String deleteIkeRespHex) throws Exception {
307         performCloseIkeBlocking(expectedMsgId, true /* expectedUseEncap*/, deleteIkeRespHex);
308     }
309 
performCloseIkeBlocking( int expectedMsgId, boolean expectedUseEncap, String deleteIkeRespHex)310     void performCloseIkeBlocking(
311             int expectedMsgId, boolean expectedUseEncap, String deleteIkeRespHex) throws Exception {
312         mTunNetworkContext.tunUtils.awaitReqAndInjectResp(
313                 IKE_DETERMINISTIC_INITIATOR_SPI, expectedMsgId, expectedUseEncap, deleteIkeRespHex);
314     }
315 
316     /**
317      * Base testing callback that allows caller to block current thread until a method get called
318      */
319     abstract static class TestIkeSessionCallback implements IkeSessionCallback {
320         private CompletableFuture<IkeSessionConfiguration> mFutureIkeConfig =
321                 new CompletableFuture<>();
322         private CompletableFuture<Boolean> mFutureOnClosedCall = new CompletableFuture<>();
323         private CompletableFuture<IkeSessionConnectionInfo> mFutureConnectionConfig =
324                 new CompletableFuture<>();
325 
326         private int mOnErrorExceptionsCount = 0;
327         private ArrayTrackRecord<IkeException> mOnErrorExceptionsTrackRecord =
328                 new ArrayTrackRecord<>();
329 
330         protected CompletableFuture<IkeException> mFutureOnClosedException =
331                 new CompletableFuture<>();
332 
333         private int mOnLivenessStatusCount = 0;
334         private ArrayTrackRecord<Integer> mOnLivenessStatusTrackRecord = new ArrayTrackRecord<>();
335 
336         @Override
onOpened(@onNull IkeSessionConfiguration sessionConfiguration)337         public void onOpened(@NonNull IkeSessionConfiguration sessionConfiguration) {
338             mFutureIkeConfig.complete(sessionConfiguration);
339         }
340 
341         @Override
onClosed()342         public void onClosed() {
343             mFutureOnClosedCall.complete(true /* unused */);
344         }
345 
346         @Override
onError(@onNull IkeException exception)347         public void onError(@NonNull IkeException exception) {
348             IkeSessionCallback.super.onError(exception);
349             mOnErrorExceptionsTrackRecord.add(exception);
350         }
351 
352         @Override
onIkeSessionConnectionInfoChanged( @onNull IkeSessionConnectionInfo connectionInfo)353         public void onIkeSessionConnectionInfoChanged(
354                 @NonNull IkeSessionConnectionInfo connectionInfo) {
355             IkeSessionCallback.super.onIkeSessionConnectionInfoChanged(connectionInfo);
356             mFutureConnectionConfig.complete(connectionInfo);
357         }
358 
359         @Override
onLivenessStatusChanged(int livenessStatus)360         public void onLivenessStatusChanged(int livenessStatus) {
361             IkeSessionCallback.super.onLivenessStatusChanged(livenessStatus);
362             mOnLivenessStatusTrackRecord.add(livenessStatus);
363         }
364 
awaitIkeConfig()365         public IkeSessionConfiguration awaitIkeConfig() throws Exception {
366             return mFutureIkeConfig.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
367         }
368 
awaitOnClosedException()369         public IkeException awaitOnClosedException() throws Exception {
370             return mFutureOnClosedException.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
371         }
372 
awaitNextOnErrorException()373         public IkeException awaitNextOnErrorException() {
374             return mOnErrorExceptionsTrackRecord.poll(
375                     (long) TIMEOUT_MS,
376                     mOnErrorExceptionsCount++,
377                     (transform) -> {
378                         return true;
379                     });
380         }
381 
awaitOnClosed()382         public void awaitOnClosed() throws Exception {
383             mFutureOnClosedCall.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
384         }
385 
awaitOnIkeSessionConnectionInfoChanged()386         public IkeSessionConnectionInfo awaitOnIkeSessionConnectionInfoChanged() throws Exception {
387             return mFutureConnectionConfig.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
388         }
389 
awaitNextOnLivenessStatus()390         public int awaitNextOnLivenessStatus() throws Exception {
391             return mOnLivenessStatusTrackRecord.poll(
392                     (long) TIMEOUT_MS,
393                     mOnLivenessStatusCount++,
394                     (transform) -> {
395                         return true;
396                     });
397         }
398     }
399 
400     /** Default testing callback for all IKE exchange tests */
401     static class DefaultTestIkeSessionCallback extends TestIkeSessionCallback {
402         @Override
403         public void onClosedWithException(@NonNull IkeException exception) {
404             mFutureOnClosedException.complete(exception);
405         }
406     }
407 
408     /** Testing callback to verify deprecated methods before they are removed */
409     static class LegacyTestIkeSessionCallback extends TestIkeSessionCallback {
410         @Override
411         public void onClosedExceptionally(@NonNull IkeException exception) {
412             mFutureOnClosedException.complete(exception);
413         }
414     }
415 
416     /**
417      * Base testing callback that allows caller to block current thread until a method get called
418      */
419     abstract static class TestChildSessionCallback implements ChildSessionCallback {
420         private CompletableFuture<ChildSessionConfiguration> mFutureChildConfig =
421                 new CompletableFuture<>();
422         private CompletableFuture<Boolean> mFutureOnClosedCall = new CompletableFuture<>();
423 
424         protected CompletableFuture<IkeException> mFutureOnClosedException =
425                 new CompletableFuture<>();
426 
427         private int mCreatedIpSecTransformCount = 0;
428         private int mMigratedIpSecTransformCount = 0;
429         private int mDeletedIpSecTransformCount = 0;
430         private ArrayTrackRecord<IpSecTransformCallRecord> mCreatedIpSecTransformsTrackRecord =
431                 new ArrayTrackRecord<>();
432         private ArrayTrackRecord<IpSecTransformCallRecord[]> mMigratedIpSecTransformsTrackRecord =
433                 new ArrayTrackRecord<>();
434         private ArrayTrackRecord<IpSecTransformCallRecord> mDeletedIpSecTransformsTrackRecord =
435                 new ArrayTrackRecord<>();
436 
437         @Override
438         public void onOpened(@NonNull ChildSessionConfiguration sessionConfiguration) {
439             mFutureChildConfig.complete(sessionConfiguration);
440         }
441 
442         @Override
443         public void onClosed() {
444             mFutureOnClosedCall.complete(true /* unused */);
445         }
446 
447         @Override
448         public void onIpSecTransformCreated(@NonNull IpSecTransform ipSecTransform, int direction) {
449             mCreatedIpSecTransformsTrackRecord.add(
450                     new IpSecTransformCallRecord(ipSecTransform, direction));
451         }
452 
453         @Override
454         public void onIpSecTransformsMigrated(
455                 IpSecTransform inIpSecTransform, IpSecTransform outIpSecTransform) {
456             ChildSessionCallback.super.onIpSecTransformsMigrated(
457                     inIpSecTransform, outIpSecTransform);
458 
459             IpSecTransformCallRecord inRecord =
460                     new IpSecTransformCallRecord(inIpSecTransform, IpSecManager.DIRECTION_IN);
461             IpSecTransformCallRecord outRecord =
462                     new IpSecTransformCallRecord(outIpSecTransform, IpSecManager.DIRECTION_OUT);
463             mMigratedIpSecTransformsTrackRecord.add(
464                     new IpSecTransformCallRecord[] {inRecord, outRecord});
465         }
466 
467         @Override
468         public void onIpSecTransformDeleted(@NonNull IpSecTransform ipSecTransform, int direction) {
469             mDeletedIpSecTransformsTrackRecord.add(
470                     new IpSecTransformCallRecord(ipSecTransform, direction));
471         }
472 
473         public ChildSessionConfiguration awaitChildConfig() throws Exception {
474             return mFutureChildConfig.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
475         }
476 
477         public IkeException awaitOnClosedException() throws Exception {
478             return mFutureOnClosedException.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
479         }
480 
481         public IpSecTransformCallRecord awaitNextCreatedIpSecTransform() {
482             return mCreatedIpSecTransformsTrackRecord.poll(
483                     (long) TIMEOUT_MS,
484                     mCreatedIpSecTransformCount++,
485                     (transform) -> {
486                         return true;
487                     });
488         }
489 
490         public IpSecTransformCallRecord[] awaitNextMigratedIpSecTransform() {
491             return mMigratedIpSecTransformsTrackRecord.poll(
492                     (long) TIMEOUT_MS,
493                     mMigratedIpSecTransformCount++,
494                     (transform) -> {
495                         return true;
496                     });
497         }
498 
499         public IpSecTransformCallRecord awaitNextDeletedIpSecTransform() {
500             return mDeletedIpSecTransformsTrackRecord.poll(
501                     (long) TIMEOUT_MS,
502                     mDeletedIpSecTransformCount++,
503                     (transform) -> {
504                         return true;
505                     });
506         }
507 
508         public void awaitOnClosed() throws Exception {
509             mFutureOnClosedCall.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
510         }
511     }
512 
513     /** Default testing callback for all IKE exchange tests */
514     static class DefaultTestChildSessionCallback extends TestChildSessionCallback {
515         @Override
516         public void onClosedWithException(@NonNull IkeException exception) {
517             mFutureOnClosedException.complete(exception);
518         }
519     }
520 
521     /** Testing callback to verify deprecated methods before they are removed */
522     static class LegacyTestChildSessionCallback extends TestChildSessionCallback {
523         @Override
524         public void onClosedExceptionally(@NonNull IkeException exception) {
525             mFutureOnClosedException.complete(exception);
526         }
527     }
528 
529     /**
530      * This class represents a created or deleted IpSecTransfrom that is provided by
531      * ChildSessionCallback
532      */
533     static class IpSecTransformCallRecord {
534         public final IpSecTransform ipSecTransform;
535         public final int direction;
536 
537         IpSecTransformCallRecord(IpSecTransform ipSecTransform, @PolicyDirection int direction) {
538             this.ipSecTransform = ipSecTransform;
539             this.direction = direction;
540         }
541 
542         @Override
543         public int hashCode() {
544             return Objects.hash(ipSecTransform, direction);
545         }
546 
547         @Override
548         public boolean equals(Object o) {
549             if (!(o instanceof IpSecTransformCallRecord)) return false;
550 
551             IpSecTransformCallRecord record = (IpSecTransformCallRecord) o;
552             return ipSecTransform.equals(record.ipSecTransform) && direction == record.direction;
553         }
554     }
555 
556     // TODO: b/275938211 Rename the method to reflect that it will return a value besides doing
557     // validations
558     IkeSessionConnectionInfo verifyIkeSessionSetupBlocking() throws Exception {
559         return verifyIkeSessionSetupBlocking(EXTENSION_TYPE_FRAGMENTATION);
560     }
561 
562     IkeSessionConnectionInfo verifyIkeSessionSetupBlocking(int... expectedIkeExtensions)
563             throws Exception {
564         IkeSessionConfiguration ikeConfig = mIkeSessionCallback.awaitIkeConfig();
565         assertNotNull(ikeConfig);
566         assertEquals(EXPECTED_REMOTE_APP_VERSION_EMPTY, ikeConfig.getRemoteApplicationVersion());
567         assertTrue(ikeConfig.getRemoteVendorIds().isEmpty());
568         assertTrue(ikeConfig.getPcscfServers().isEmpty());
569         for (int ikeExtension : expectedIkeExtensions) {
570             assertTrue(ikeConfig.isIkeExtensionEnabled(ikeExtension));
571         }
572 
573         IkeSessionConnectionInfo ikeConnectInfo = ikeConfig.getIkeSessionConnectionInfo();
574         assertNotNull(ikeConnectInfo);
575         assertEquals(mLocalAddress, ikeConnectInfo.getLocalAddress());
576         assertEquals(mRemoteAddress, ikeConnectInfo.getRemoteAddress());
577         assertEquals(mTunNetworkContext.tunNetwork, ikeConnectInfo.getNetwork());
578 
579         return ikeConnectInfo;
580     }
581 
582     ChildSessionConfiguration verifyChildSessionSetupBlocking(
583             TestChildSessionCallback childCallback,
584             List<IkeTrafficSelector> expectedInboundTs,
585             List<IkeTrafficSelector> expectedOutboundTs,
586             List<LinkAddress> expectedInternalAddresses)
587             throws Exception {
588         return verifyChildSessionSetupBlocking(
589                 childCallback,
590                 expectedInboundTs,
591                 expectedOutboundTs,
592                 expectedInternalAddresses,
593                 new ArrayList<InetAddress>() /* expectedDnsServers */);
594     }
595 
596     ChildSessionConfiguration verifyChildSessionSetupBlocking(
597             TestChildSessionCallback childCallback,
598             List<IkeTrafficSelector> expectedInboundTs,
599             List<IkeTrafficSelector> expectedOutboundTs,
600             List<LinkAddress> expectedInternalAddresses,
601             List<InetAddress> expectedDnsServers)
602             throws Exception {
603         ChildSessionConfiguration childConfig = childCallback.awaitChildConfig();
604         assertNotNull(childConfig);
605         assertEquals(expectedInboundTs, childConfig.getInboundTrafficSelectors());
606         assertEquals(expectedOutboundTs, childConfig.getOutboundTrafficSelectors());
607         assertEquals(expectedInternalAddresses, childConfig.getInternalAddresses());
608         assertEquals(expectedDnsServers, childConfig.getInternalDnsServers());
609         assertTrue(childConfig.getInternalSubnets().isEmpty());
610         assertTrue(childConfig.getInternalDhcpServers().isEmpty());
611         return childConfig;
612     }
613 
614     void verifyCloseIkeAndChildBlocking(
615             IpSecTransformCallRecord expectedTransformRecordA,
616             IpSecTransformCallRecord expectedTransformRecordB)
617             throws Exception {
618         verifyDeleteIpSecTransformPair(
619                 mFirstChildSessionCallback, expectedTransformRecordA, expectedTransformRecordB);
620         mFirstChildSessionCallback.awaitOnClosed();
621         mIkeSessionCallback.awaitOnClosed();
622     }
623 
624     static void verifyCreateIpSecTransformPair(
625             IpSecTransformCallRecord transformRecordA, IpSecTransformCallRecord transformRecordB) {
626         IpSecTransform transformA = transformRecordA.ipSecTransform;
627         IpSecTransform transformB = transformRecordB.ipSecTransform;
628 
629         assertNotNull(transformA);
630         assertNotNull(transformB);
631 
632         Set<Integer> expectedDirections = new HashSet<>();
633         expectedDirections.add(IpSecManager.DIRECTION_IN);
634         expectedDirections.add(IpSecManager.DIRECTION_OUT);
635 
636         Set<Integer> resultDirections = new HashSet<>();
637         resultDirections.add(transformRecordA.direction);
638         resultDirections.add(transformRecordB.direction);
639 
640         assertEquals(expectedDirections, resultDirections);
641     }
642 
643     static void verifyDeleteIpSecTransformPair(
644             TestChildSessionCallback childCb,
645             IpSecTransformCallRecord expectedTransformRecordA,
646             IpSecTransformCallRecord expectedTransformRecordB) {
647         Set<IpSecTransformCallRecord> expectedTransforms = new HashSet<>();
648         expectedTransforms.add(expectedTransformRecordA);
649         expectedTransforms.add(expectedTransformRecordB);
650 
651         Set<IpSecTransformCallRecord> resultTransforms = new HashSet<>();
652         resultTransforms.add(childCb.awaitNextDeletedIpSecTransform());
653         resultTransforms.add(childCb.awaitNextDeletedIpSecTransform());
654 
655         assertEquals(expectedTransforms, resultTransforms);
656     }
657 
658     /** Package private method to check if device has IPsec tunnels feature */
659     static boolean hasTunnelsFeature() {
660         return sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS);
661     }
662 
663     /** Package private method to check if device has IPsec tunnel migration feature */
664     static boolean hasTunnelMigrationFeature() {
665         return sContext.getPackageManager()
666                 .hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNEL_MIGRATION);
667     }
668 
669     // TODO(b/148689509): Verify hostname based creation
670 }
671