Merge "gn2bp: delete obsolete version in p/m/C"
diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java
index 9c30811..f935cef 100644
--- a/tests/cts/net/src/android/net/cts/IpSecManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/IpSecManagerTest.java
@@ -364,10 +364,20 @@
         });
     }
 
-    private void assumeExperimentalIpv6UdpEncapSupported() throws Exception {
+    private static boolean isIpv6UdpEncapSupportedByKernel() {
+        return isKernelVersionAtLeast("5.15.31")
+                || (isKernelVersionAtLeast("5.10.108") && !isKernelVersionAtLeast("5.15.0"));
+    }
+
+    // Packet private for use in IpSecManagerTunnelTest
+    static boolean isIpv6UdpEncapSupported() {
+        return SdkLevel.isAtLeastU() && isIpv6UdpEncapSupportedByKernel();
+    }
+
+    // Packet private for use in IpSecManagerTunnelTest
+    static void assumeExperimentalIpv6UdpEncapSupported() throws Exception {
         assumeTrue("Not supported before U", SdkLevel.isAtLeastU());
-        assumeTrue("Not supported by kernel", isKernelVersionAtLeast("5.15.31")
-                || (isKernelVersionAtLeast("5.10.108") && !isKernelVersionAtLeast("5.15.0")));
+        assumeTrue("Not supported by kernel", isIpv6UdpEncapSupportedByKernel());
     }
 
     @Test
diff --git a/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java b/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
index da79158..1ede5c1 100644
--- a/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
+++ b/tests/cts/net/src/android/net/cts/IpSecManagerTunnelTest.java
@@ -18,6 +18,8 @@
 
 import static android.app.AppOpsManager.OP_MANAGE_IPSEC_TUNNELS;
 import static android.net.IpSecManager.UdpEncapsulationSocket;
+import static android.net.cts.IpSecManagerTest.assumeExperimentalIpv6UdpEncapSupported;
+import static android.net.cts.IpSecManagerTest.isIpv6UdpEncapSupported;
 import static android.net.cts.PacketUtils.AES_CBC_BLK_SIZE;
 import static android.net.cts.PacketUtils.AES_CBC_IV_LEN;
 import static android.net.cts.PacketUtils.BytePayload;
@@ -111,6 +113,7 @@
 
     private static final int IP4_PREFIX_LEN = 32;
     private static final int IP6_PREFIX_LEN = 128;
+    private static final int IP6_UDP_ENCAP_SOCKET_PORT_ANY = 65536;
 
     private static final int TIMEOUT_MS = 500;
 
@@ -310,6 +313,18 @@
         return expectedPacketSize;
     }
 
+    private UdpEncapsulationSocket openUdpEncapsulationSocket(int ipVersion) throws Exception {
+        if (ipVersion == AF_INET) {
+            return mISM.openUdpEncapsulationSocket();
+        }
+
+        if (!isIpv6UdpEncapSupported()) {
+            throw new UnsupportedOperationException("IPv6 UDP encapsulation unsupported");
+        }
+
+        return mISM.openUdpEncapsulationSocket(IP6_UDP_ENCAP_SOCKET_PORT_ANY);
+    }
+
     private interface IpSecTunnelTestRunnableFactory {
         /**
          * Build a IpSecTunnelTestRunnable.
@@ -321,7 +336,7 @@
          * @param remoteInner The remote address of the inner IP packet
          * @param inTransportTransform The inbound transport mode transform
          * @param outTransportTransform The outbound transport mode transform
-         * @param encapPort The port of the UDP encapsulation socket
+         * @param encapSocket The UDP encapsulation socket or null
          * @param innerSocketPort The inner socket port
          */
         IpSecTunnelTestRunnable getIpSecTunnelTestRunnable(
@@ -331,7 +346,7 @@
                 InetAddress remoteInner,
                 IpSecTransform inTransportTransform,
                 IpSecTransform outTransportTransform,
-                int encapPort,
+                UdpEncapsulationSocket encapSocket,
                 int innerSocketPort)
                 throws Exception;
     }
@@ -344,7 +359,7 @@
                 InetAddress remoteInner,
                 IpSecTransform inTransportTransform,
                 IpSecTransform outTransportTransform,
-                int encapPort,
+                UdpEncapsulationSocket encapSocket,
                 int unusedInnerSocketPort) {
             return new IpSecTunnelTestRunnable() {
                 @Override
@@ -378,7 +393,7 @@
                     // inner IP header (flow label, flags, etc)
                     int innerFamily = localInner instanceof Inet4Address ? AF_INET : AF_INET6;
                     int outerFamily = localOuter instanceof Inet4Address ? AF_INET : AF_INET6;
-                    boolean useEncap = encapPort != 0;
+                    boolean useEncap = encapSocket != null;
                     int expectedPacketSize =
                             getPacketSize(
                                     innerFamily, outerFamily, useEncap, transportInTunnelMode);
@@ -401,7 +416,7 @@
                 InetAddress remoteInner,
                 IpSecTransform inTransportTransform,
                 IpSecTransform outTransportTransform,
-                int encapPort,
+                UdpEncapsulationSocket encapSocket,
                 int innerSocketPort)
                 throws Exception {
             return new IpSecTunnelTestRunnable() {
@@ -450,7 +465,7 @@
                 InetAddress remoteInner,
                 IpSecTransform inTransportTransform,
                 IpSecTransform outTransportTransform,
-                int encapPort,
+                UdpEncapsulationSocket encapSocket,
                 int innerSocketPort)
                 throws Exception {
             return new IpSecTunnelTestRunnable() {
@@ -488,7 +503,7 @@
                                         remoteOuter,
                                         localOuter,
                                         socket.getPort(),
-                                        encapPort,
+                                        encapSocket != null ? encapSocket.getPort() : 0,
                                         seqNum);
                     } else {
                         pkt =
@@ -499,7 +514,7 @@
                                         remoteOuter,
                                         localOuter,
                                         socket.getPort(),
-                                        encapPort,
+                                        encapSocket != null ? encapSocket.getPort() : 0,
                                         seqNum);
                     }
                     tunUtils.injectPacket(pkt);
@@ -517,13 +532,16 @@
 
     private class MigrateIpSecTunnelTestRunnableFactory implements IpSecTunnelTestRunnableFactory {
         private final IpSecTunnelTestRunnableFactory mTestRunnableFactory;
+        private final boolean mTestEncapTypeChange;
 
-        MigrateIpSecTunnelTestRunnableFactory(boolean isOutputTest) {
+        MigrateIpSecTunnelTestRunnableFactory(boolean isOutputTest, boolean testEncapTypeChange) {
             if (isOutputTest) {
                 mTestRunnableFactory = new OutputIpSecTunnelTestRunnableFactory();
             } else {
                 mTestRunnableFactory = new InputPacketGeneratorIpSecTunnelTestRunnableFactory();
             }
+
+            mTestEncapTypeChange = testEncapTypeChange;
         }
 
         @Override
@@ -534,7 +552,7 @@
                 InetAddress remoteInner,
                 IpSecTransform inTransportTransform,
                 IpSecTransform outTransportTransform,
-                int encapPort,
+                UdpEncapsulationSocket encapSocket,
                 int unusedInnerSocketPort) {
             return new IpSecTunnelTestRunnable() {
                 @Override
@@ -556,7 +574,7 @@
                                     remoteInner,
                                     inTransportTransform,
                                     outTransportTransform,
-                                    encapPort,
+                                    encapSocket,
                                     unusedInnerSocketPort)
                             .run(
                                     ipsecNetwork,
@@ -569,6 +587,10 @@
                                     seqNum);
                     tunnelIface.setUnderlyingNetwork(sTunWrapperNew.network);
 
+                    final boolean useEncapBeforeMigrate = encapSocket != null;
+                    final boolean useEncapAfterMigrate =
+                            mTestEncapTypeChange ? !useEncapBeforeMigrate : useEncapBeforeMigrate;
+
                     // Verify migrating to IPv4 and IPv6 addresses. It ensures that not only
                     // can IPsec tunnel migrate across interfaces, IPsec tunnel can also migrate to
                     // a different address on the same interface.
@@ -577,21 +599,24 @@
                             remoteInner,
                             LOCAL_OUTER_4_NEW,
                             REMOTE_OUTER_4_NEW,
-                            encapPort != 0,
+                            useEncapAfterMigrate,
                             transportInTunnelMode,
                             sTunWrapperNew.utils,
                             tunnelIface,
                             ipsecNetwork);
-                    checkMigratedTunnel(
-                            localInner,
-                            remoteInner,
-                            LOCAL_OUTER_6_NEW,
-                            REMOTE_OUTER_6_NEW,
-                            false, // IPv6 does not support UDP encapsulation
-                            transportInTunnelMode,
-                            sTunWrapperNew.utils,
-                            tunnelIface,
-                            ipsecNetwork);
+
+                    if (!useEncapAfterMigrate || isIpv6UdpEncapSupported()) {
+                        checkMigratedTunnel(
+                                localInner,
+                                remoteInner,
+                                LOCAL_OUTER_6_NEW,
+                                REMOTE_OUTER_6_NEW,
+                                useEncapAfterMigrate,
+                                transportInTunnelMode,
+                                sTunWrapperNew.utils,
+                                tunnelIface,
+                                ipsecNetwork);
+                    }
 
                     return 0;
                 }
@@ -631,7 +656,8 @@
                             buildIpSecTransform(sContext, inTransportSpi, null, remoteInner);
                     IpSecTransform outTransportTransform =
                             buildIpSecTransform(sContext, outTransportSpi, null, localInner);
-                    UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+                    UdpEncapsulationSocket encapSocket =
+                            useEncap ? openUdpEncapsulationSocket(outerFamily) : null) {
 
                 // Configure tunnel mode Transform parameters
                 IpSecTransform.Builder transformBuilder = new IpSecTransform.Builder(sContext);
@@ -641,7 +667,7 @@
                         new IpSecAlgorithm(
                                 IpSecAlgorithm.AUTH_HMAC_SHA256, AUTH_KEY, AUTH_KEY.length * 4));
 
-                if (useEncap) {
+                if (encapSocket != null) {
                     transformBuilder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
                 }
 
@@ -667,7 +693,7 @@
                                     remoteInner,
                                     inTransportTransform,
                                     outTransportTransform,
-                                    useEncap ? encapSocket.getPort() : 0,
+                                    encapSocket,
                                     0)
                             .run(
                                     ipsecNetwork,
@@ -703,7 +729,7 @@
                 InetAddress remoteInner,
                 IpSecTransform inTransportTransform,
                 IpSecTransform outTransportTransform,
-                int encapPort,
+                UdpEncapsulationSocket encapSocket,
                 int unusedInnerSocketPort) {
             return new IpSecTunnelTestRunnable() {
                 @Override
@@ -725,7 +751,7 @@
                                     remoteInner,
                                     inTransportTransform,
                                     outTransportTransform,
-                                    encapPort,
+                                    encapSocket,
                                     unusedInnerSocketPort);
                     testRunnable.run(
                             ipsecNetwork,
@@ -738,19 +764,28 @@
                             seqNum++);
 
                     tunnelIface.setUnderlyingNetwork(sTunWrapperNew.network);
-                    checkMigrateTunnelModeTransform(
-                            testRunnable,
-                            inTunnelTransform,
-                            outTunnelTransform,
-                            tunnelIface,
-                            ipsecNetwork,
-                            sTunWrapperNew.utils,
-                            LOCAL_OUTER_4_NEW,
-                            REMOTE_OUTER_4_NEW,
-                            seqNum++);
 
-                    // Only test migration to IPv6 in non-UDP Encapsulation case
-                    if (encapPort == 0) {
+                    final boolean useEncap = encapSocket != null;
+                    if (useEncap) {
+                        sTunWrapperNew.network.bindSocket(encapSocket.getFileDescriptor());
+                    }
+
+                    // Updating UDP encapsulation socket is not supported. Thus this runnable will
+                    // only cover 1) migration from non-encap to non-encap and 2) migration from
+                    // encap to encap with the same family
+                    if (!useEncap || localOuter instanceof Inet4Address) {
+                        checkMigrateTunnelModeTransform(
+                                testRunnable,
+                                inTunnelTransform,
+                                outTunnelTransform,
+                                tunnelIface,
+                                ipsecNetwork,
+                                sTunWrapperNew.utils,
+                                LOCAL_OUTER_4_NEW,
+                                REMOTE_OUTER_4_NEW,
+                                seqNum++);
+                    }
+                    if (!useEncap || localOuter instanceof Inet6Address) {
                         checkMigrateTunnelModeTransform(
                                 testRunnable,
                                 inTunnelTransform,
@@ -825,25 +860,33 @@
     }
 
     private void checkMigrateTunnelOutput(
-            int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+            int innerFamily,
+            int outerFamily,
+            boolean useEncap,
+            boolean transportInTunnelMode,
+            boolean isEncapTypeChanged)
             throws Exception {
         checkTunnel(
                 innerFamily,
                 outerFamily,
                 useEncap,
                 transportInTunnelMode,
-                new MigrateIpSecTunnelTestRunnableFactory(true));
+                new MigrateIpSecTunnelTestRunnableFactory(true, isEncapTypeChanged));
     }
 
     private void checkMigrateTunnelInput(
-            int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+            int innerFamily,
+            int outerFamily,
+            boolean useEncap,
+            boolean transportInTunnelMode,
+            boolean isEncapTypeChanged)
             throws Exception {
         checkTunnel(
                 innerFamily,
                 outerFamily,
                 useEncap,
                 transportInTunnelMode,
-                new MigrateIpSecTunnelTestRunnableFactory(false));
+                new MigrateIpSecTunnelTestRunnableFactory(false, isEncapTypeChanged));
     }
 
     private void checkMigrateTunnelModeTransformOutput(
@@ -897,7 +940,8 @@
                         buildIpSecTransform(sContext, inTransportSpi, null, remoteInner);
                 IpSecTransform outTransportTransform =
                         buildIpSecTransform(sContext, outTransportSpi, null, localInner);
-                UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+                UdpEncapsulationSocket encapSocket =
+                        useEncap ? openUdpEncapsulationSocket(outerFamily) : null) {
 
             // Run output direction tests
             IpSecTunnelTestRunnable outputIpSecTunnelTestRunnable =
@@ -909,7 +953,7 @@
                                     remoteInner,
                                     inTransportTransform,
                                     outTransportTransform,
-                                    useEncap ? encapSocket.getPort() : 0,
+                                    encapSocket,
                                     0);
             int innerSocketPort =
                     buildTunnelNetworkAndRunTests(
@@ -918,7 +962,7 @@
                             localOuter,
                             remoteOuter,
                             spi,
-                            useEncap ? encapSocket : null,
+                            encapSocket,
                             outputIpSecTunnelTestRunnable);
 
             // Input direction tests, with matching inner socket ports.
@@ -931,7 +975,7 @@
                                     localInner,
                                     inTransportTransform,
                                     outTransportTransform,
-                                    useEncap ? encapSocket.getPort() : 0,
+                                    encapSocket,
                                     innerSocketPort);
             buildTunnelNetworkAndRunTests(
                     remoteInner,
@@ -939,7 +983,7 @@
                     localOuter,
                     remoteOuter,
                     spi,
-                    useEncap ? encapSocket : null,
+                    encapSocket,
                     inputIpSecTunnelTestRunnable);
         }
     }
@@ -973,7 +1017,8 @@
                         buildIpSecTransform(sContext, inTransportSpi, null, remoteInner);
                 IpSecTransform outTransportTransform =
                         buildIpSecTransform(sContext, outTransportSpi, null, localInner);
-                UdpEncapsulationSocket encapSocket = mISM.openUdpEncapsulationSocket()) {
+                UdpEncapsulationSocket encapSocket =
+                        useEncap ? openUdpEncapsulationSocket(outerFamily) : null) {
 
             buildTunnelNetworkAndRunTests(
                     localInner,
@@ -981,7 +1026,7 @@
                     localOuter,
                     remoteOuter,
                     spi,
-                    useEncap ? encapSocket : null,
+                    encapSocket,
                     factory.getIpSecTunnelTestRunnable(
                             transportInTunnelMode,
                             spi,
@@ -989,7 +1034,7 @@
                             remoteInner,
                             inTransportTransform,
                             outTransportTransform,
-                            useEncap ? encapSocket.getPort() : 0,
+                            encapSocket,
                             0));
         }
     }
@@ -1038,6 +1083,7 @@
 
             if (encapSocket != null) {
                 transformBuilder.setIpv4Encapsulation(encapSocket, encapSocket.getPort());
+                sTunWrapper.network.bindSocket(encapSocket.getFileDescriptor());
             }
 
             // Apply transform and check that traffic is properly encrypted
@@ -1189,11 +1235,39 @@
     }
 
     private void doTestMigrateTunnel(
-            int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+            int innerFamily,
+            int outerFamily,
+            boolean useEncap,
+            boolean transportInTunnelMode,
+            boolean testEncapTypeChange)
             throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
-        checkMigrateTunnelOutput(innerFamily, outerFamily, useEncap, transportInTunnelMode);
-        checkMigrateTunnelInput(innerFamily, outerFamily, useEncap, transportInTunnelMode);
+        checkMigrateTunnelOutput(
+                innerFamily, outerFamily, useEncap, transportInTunnelMode, testEncapTypeChange);
+        checkMigrateTunnelInput(
+                innerFamily, outerFamily, useEncap, transportInTunnelMode, testEncapTypeChange);
+    }
+
+    private void doTestMigrateTunnel(
+            int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+            throws Exception {
+        doTestMigrateTunnel(
+                innerFamily,
+                outerFamily,
+                useEncap,
+                transportInTunnelMode,
+                false /* testEncapTypeChange */);
+    }
+
+    private void doTestMigrateTunnelWithEncapTypeChange(
+            int innerFamily, int outerFamily, boolean useEncap, boolean transportInTunnelMode)
+            throws Exception {
+        doTestMigrateTunnel(
+                innerFamily,
+                outerFamily,
+                useEncap,
+                transportInTunnelMode,
+                true /* testEncapTypeChange */);
     }
 
     private void doTestMigrateTunnelModeTransform(
@@ -1230,6 +1304,12 @@
         doTestMigrateTunnel(AF_INET, AF_INET, false, true);
     }
 
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    @Test
+    public void testMigrateTransportInTunnelModeV4InV4_EncapTypeChange() throws Exception {
+        doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET, false, true);
+    }
+
     @Test
     public void testTransportInTunnelModeV4InV4Reflected() throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1249,6 +1329,12 @@
         doTestMigrateTunnel(AF_INET, AF_INET, true, true);
     }
 
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    @Test
+    public void testMigrateTransportInTunnelModeV4InV4UdpEncap_EncapTypeChange() throws Exception {
+        doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET, true, true);
+    }
+
     @Test
     public void testTransportInTunnelModeV4InV4UdpEncapReflected() throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1268,6 +1354,12 @@
         doTestMigrateTunnel(AF_INET, AF_INET6, false, true);
     }
 
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    @Test
+    public void testMigrateTransportInTunnelModeV4InV6_EncapTypeChange() throws Exception {
+        doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET6, false, true);
+    }
+
     @Test
     public void testTransportInTunnelModeV4InV6Reflected() throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1287,6 +1379,12 @@
         doTestMigrateTunnel(AF_INET6, AF_INET, false, true);
     }
 
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    @Test
+    public void testMigrateTransportInTunnelModeV6InV4_EncapTypeChange() throws Exception {
+        doTestMigrateTunnelWithEncapTypeChange(AF_INET6, AF_INET, false, true);
+    }
+
     @Test
     public void testTransportInTunnelModeV6InV4Reflected() throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1306,6 +1404,12 @@
         doTestMigrateTunnel(AF_INET6, AF_INET, true, true);
     }
 
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    @Test
+    public void testMigrateTransportInTunnelModeV6InV4UdpEncap_EncapTypeChange() throws Exception {
+        doTestMigrateTunnelWithEncapTypeChange(AF_INET6, AF_INET, true, true);
+    }
+
     @Test
     public void testTransportInTunnelModeV6InV4UdpEncapReflected() throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1325,6 +1429,12 @@
         doTestMigrateTunnel(AF_INET, AF_INET6, false, true);
     }
 
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    @Test
+    public void testMigrateTransportInTunnelModeV6InV6_EncapTypeChange() throws Exception {
+        doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET6, false, true);
+    }
+
     @Test
     public void testTransportInTunnelModeV6InV6Reflected() throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1345,6 +1455,12 @@
         doTestMigrateTunnel(AF_INET, AF_INET, false, false);
     }
 
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    @Test
+    public void testMigrateTunnelV4InV4_EncapTypeChange() throws Exception {
+        doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET, false, false);
+    }
+
     @Test
     public void testTunnelV4InV4Reflected() throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1364,6 +1480,12 @@
         doTestMigrateTunnel(AF_INET, AF_INET, true, false);
     }
 
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    @Test
+    public void testMigrateTunnelV4InV4UdpEncap_EncapTypeChange() throws Exception {
+        doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET, true, false);
+    }
+
     @Test
     public void testTunnelV4InV4UdpEncapReflected() throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1383,6 +1505,12 @@
         doTestMigrateTunnel(AF_INET, AF_INET6, false, false);
     }
 
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    @Test
+    public void testMigrateTunnelV4InV6_EncapTypeChange() throws Exception {
+        doTestMigrateTunnelWithEncapTypeChange(AF_INET, AF_INET6, false, false);
+    }
+
     @Test
     public void testTunnelV4InV6Reflected() throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1402,6 +1530,12 @@
         doTestMigrateTunnel(AF_INET6, AF_INET, false, false);
     }
 
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    @Test
+    public void testMigrateTunnelV6InV4_EncapTypeChange() throws Exception {
+        doTestMigrateTunnelWithEncapTypeChange(AF_INET6, AF_INET, false, false);
+    }
+
     @Test
     public void testTunnelV6InV4Reflected() throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1421,6 +1555,12 @@
         doTestMigrateTunnel(AF_INET6, AF_INET, true, false);
     }
 
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    @Test
+    public void testMigrateTunnelV6InV4UdpEncap_EncapTypeChange() throws Exception {
+        doTestMigrateTunnelWithEncapTypeChange(AF_INET6, AF_INET, true, false);
+    }
+
     @Test
     public void testTunnelV6InV4UdpEncapReflected() throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1440,6 +1580,12 @@
         doTestMigrateTunnel(AF_INET6, AF_INET6, false, false);
     }
 
+    @IgnoreUpTo(Build.VERSION_CODES.R)
+    @Test
+    public void testMigrateTunnelV6InV6_EncapTypeChange() throws Exception {
+        doTestMigrateTunnelWithEncapTypeChange(AF_INET6, AF_INET6, false, false);
+    }
+
     @Test
     public void testTunnelV6InV6Reflected() throws Exception {
         assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature());
@@ -1484,6 +1630,20 @@
 
     @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
     @Test
+    public void testMigrateTransformTransportInTunnelModeV4InV6UdpEncap() throws Exception {
+        assumeExperimentalIpv6UdpEncapSupported();
+        doTestMigrateTunnelModeTransform(AF_INET, AF_INET6, true, true);
+    }
+
+    @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    @Test
+    public void testMigrateTransformTransportInTunnelModeV6InV6UdpEncap() throws Exception {
+        assumeExperimentalIpv6UdpEncapSupported();
+        doTestMigrateTunnelModeTransform(AF_INET6, AF_INET6, true, true);
+    }
+
+    @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    @Test
     public void testMigrateTransformTunnelV4InV4() throws Exception {
         doTestMigrateTunnelModeTransform(AF_INET, AF_INET, false, false);
     }
@@ -1517,4 +1677,18 @@
     public void testMigrateTransformTunnelV6InV4UdpEncap() throws Exception {
         doTestMigrateTunnelModeTransform(AF_INET6, AF_INET, true, false);
     }
+
+    @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    @Test
+    public void testMigrateTransformTunnelV4InV6UdpEncap() throws Exception {
+        assumeExperimentalIpv6UdpEncapSupported();
+        doTestMigrateTunnelModeTransform(AF_INET, AF_INET6, true, false);
+    }
+
+    @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+    @Test
+    public void testMigrateTransformTunnelV6InV6UdpEncap() throws Exception {
+        assumeExperimentalIpv6UdpEncapSupported();
+        doTestMigrateTunnelModeTransform(AF_INET6, AF_INET6, true, false);
+    }
 }