Merge changes I1e6846e5,I827cd8ea

* changes:
  Do not count defaultOrConfiguredNetwork in #hashCode or #equals
  Construct a Builder with ChildSessionParams
diff --git a/src/java/android/net/ipsec/ike/ChildSessionParams.java b/src/java/android/net/ipsec/ike/ChildSessionParams.java
index bf83c7a..b0e5fe8 100644
--- a/src/java/android/net/ipsec/ike/ChildSessionParams.java
+++ b/src/java/android/net/ipsec/ike/ChildSessionParams.java
@@ -300,6 +300,20 @@
         protected int mHardLifetimeSec = CHILD_HARD_LIFETIME_SEC_DEFAULT;
         protected int mSoftLifetimeSec = CHILD_SOFT_LIFETIME_SEC_DEFAULT;
 
+        /** Package private constructor */
+        Builder() {}
+
+        /** Package private constructor */
+        Builder(@NonNull ChildSessionParams childParams) {
+            Objects.requireNonNull(childParams, "childParams was null");
+
+            mInboundTsList.addAll(childParams.getInboundTrafficSelectors());
+            mOutboundTsList.addAll(childParams.getOutboundTrafficSelectors());
+            mSaProposalList.addAll(childParams.getSaProposals());
+            mHardLifetimeSec = childParams.getHardLifetimeSeconds();
+            mSoftLifetimeSec = childParams.getSoftLifetimeSeconds();
+        }
+
         protected void addProposal(@NonNull ChildSaProposal proposal) {
             mSaProposalList.add(proposal);
         }
diff --git a/src/java/android/net/ipsec/ike/IkeSessionParams.java b/src/java/android/net/ipsec/ike/IkeSessionParams.java
index 05dc97c..b2b473c 100644
--- a/src/java/android/net/ipsec/ike/IkeSessionParams.java
+++ b/src/java/android/net/ipsec/ike/IkeSessionParams.java
@@ -228,7 +228,13 @@
 
     // @see #getNetwork for reasons of changing the annotation from @NonNull to @Nullable in Android
     // S and why it is safe.
-    @Nullable private final Network mNetwork;
+    // Do not include mDefaultOrConfiguredNetwork in #hashCode or #equal because when it represents
+    // configured network, it always has the same value as mCallerConfiguredNetwork. When it
+    // represents a default network it can only reflects the device status at the IkeSessionParams
+    // creation time. Since the actually default network may change after IkeSessionParams is
+    // constructed, depending on mDefaultOrConfiguredNetwork in #hashCode and #equal to decide
+    // if this object equals to another object does not make sense.
+    @Nullable private final Network mDefaultOrConfiguredNetwork;
 
     @Nullable private final Network mCallerConfiguredNetwork;
 
@@ -259,7 +265,7 @@
 
     private IkeSessionParams(
             @NonNull String serverHostname,
-            @NonNull Network network,
+            @NonNull Network defaultOrConfiguredNetwork,
             @NonNull Network callerConfiguredNetwork,
             @NonNull IkeSaProposal[] proposals,
             @NonNull IkeIdentification localIdentification,
@@ -276,7 +282,7 @@
             int nattKeepaliveDelaySec,
             boolean isIkeFragmentationSupported) {
         mServerHostname = serverHostname;
-        mNetwork = network;
+        mDefaultOrConfiguredNetwork = defaultOrConfiguredNetwork;
         mCallerConfiguredNetwork = callerConfiguredNetwork;
 
         mSaProposals = proposals;
@@ -465,7 +471,7 @@
     @NonNull
     // TODO: b/163604823 Make it @Nullable
     public Network getNetwork() {
-        return mNetwork;
+        return mDefaultOrConfiguredNetwork;
     }
 
     /** Retrieves all IkeSaProposals configured */
@@ -598,7 +604,6 @@
         return Objects.hash(
                 mServerHostname,
                 mCallerConfiguredNetwork,
-                mNetwork,
                 Arrays.hashCode(mSaProposals),
                 mLocalIdentification,
                 mRemoteIdentification,
@@ -625,7 +630,6 @@
 
         return mServerHostname.equals(other.mServerHostname)
                 && Objects.equals(mCallerConfiguredNetwork, other.mCallerConfiguredNetwork)
-                && Objects.equals(mNetwork, other.mNetwork)
                 && Arrays.equals(mSaProposals, other.mSaProposals)
                 && mLocalIdentification.equals(other.mLocalIdentification)
                 && mRemoteIdentification.equals(other.mRemoteIdentification)
diff --git a/src/java/android/net/ipsec/ike/TransportModeChildSessionParams.java b/src/java/android/net/ipsec/ike/TransportModeChildSessionParams.java
index 50fc8de..4ae02d8 100644
--- a/src/java/android/net/ipsec/ike/TransportModeChildSessionParams.java
+++ b/src/java/android/net/ipsec/ike/TransportModeChildSessionParams.java
@@ -87,6 +87,16 @@
         }
 
         /**
+         * Construct Builder from the {@link TransportModeChildSessionParams} object.
+         *
+         * @param childParams the object this Builder will be constructed with.
+         * @hide
+         */
+        public Builder(@NonNull TransportModeChildSessionParams childParams) {
+            super(childParams);
+        }
+
+        /**
          * Adds a Child SA proposal to the {@link TransportModeChildSessionParams} being built.
          *
          * @param proposal Child SA proposal.
diff --git a/src/java/android/net/ipsec/ike/TunnelModeChildSessionParams.java b/src/java/android/net/ipsec/ike/TunnelModeChildSessionParams.java
index a9009eb..71b624e 100644
--- a/src/java/android/net/ipsec/ike/TunnelModeChildSessionParams.java
+++ b/src/java/android/net/ipsec/ike/TunnelModeChildSessionParams.java
@@ -39,9 +39,9 @@
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Objects;
 
@@ -210,14 +210,31 @@
 
         private boolean mHasIp4AddressRequest;
         private boolean mHasIp4NetmaskRequest;
-        private List<TunnelModeChildConfigAttribute> mConfigRequestList;
+        private List<TunnelModeChildConfigAttribute> mConfigRequestList = new ArrayList<>();
 
-        /** Create a Builder for negotiating a transport mode Child Session. */
+        /** Create a Builder for negotiating a tunnel mode Child Session. */
         public Builder() {
             super();
             mHasIp4AddressRequest = false;
             mHasIp4NetmaskRequest = false;
-            mConfigRequestList = new LinkedList<>();
+        }
+
+        /**
+         * Construct Builder from the {@link TunnelModeChildSessionParams} object.
+         *
+         * @param childParams the object this Builder will be constructed with.
+         * @hide
+         */
+        public Builder(@NonNull TunnelModeChildSessionParams childParams) {
+            super(childParams);
+            mConfigRequestList.addAll(Arrays.asList(childParams.mConfigRequests));
+            for (TunnelModeChildConfigAttribute config : mConfigRequestList) {
+                if (config instanceof ConfigAttributeIpv4Address) {
+                    mHasIp4AddressRequest = true;
+                } else if (config instanceof ConfigAttributeIpv4Netmask) {
+                    mHasIp4NetmaskRequest = true;
+                }
+            }
         }
 
         /**
diff --git a/tests/iketests/src/java/android/net/ipsec/ike/ChildSessionParamsTest.java b/tests/iketests/src/java/android/net/ipsec/ike/ChildSessionParamsTest.java
index 7180310..9995ad8 100644
--- a/tests/iketests/src/java/android/net/ipsec/ike/ChildSessionParamsTest.java
+++ b/tests/iketests/src/java/android/net/ipsec/ike/ChildSessionParamsTest.java
@@ -35,6 +35,8 @@
     private static final int NUM_TS = 2;
 
     private final ChildSaProposal mSaProposal;
+    private final IkeTrafficSelector mTsInbound;
+    private final IkeTrafficSelector mTsOutbound;
 
     public ChildSessionParamsTest() {
         mSaProposal =
@@ -43,6 +45,18 @@
                                 SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12,
                                 SaProposal.KEY_LEN_AES_128)
                         .build();
+        mTsInbound =
+                new IkeTrafficSelector(
+                        16,
+                        65520,
+                        InetAddress.parseNumericAddress("192.0.2.100"),
+                        InetAddress.parseNumericAddress("192.0.2.101"));
+        mTsOutbound =
+                new IkeTrafficSelector(
+                        32,
+                        256,
+                        InetAddress.parseNumericAddress("192.0.2.200"),
+                        InetAddress.parseNumericAddress("192.0.2.255"));
     }
 
     @Test
@@ -86,29 +100,16 @@
 
     @Test
     public void testBuildTrafficSelectors() {
-        IkeTrafficSelector tsInbound =
-                new IkeTrafficSelector(
-                        16,
-                        65520,
-                        InetAddress.parseNumericAddress("192.0.2.100"),
-                        InetAddress.parseNumericAddress("192.0.2.101"));
-        IkeTrafficSelector tsOutbound =
-                new IkeTrafficSelector(
-                        32,
-                        256,
-                        InetAddress.parseNumericAddress("192.0.2.200"),
-                        InetAddress.parseNumericAddress("192.0.2.255"));
-
         ChildSessionParams sessionParams =
                 new TunnelModeChildSessionParams.Builder()
                         .addSaProposal(mSaProposal)
-                        .addInboundTrafficSelectors(tsInbound)
-                        .addOutboundTrafficSelectors(tsOutbound)
+                        .addInboundTrafficSelectors(mTsInbound)
+                        .addOutboundTrafficSelectors(mTsOutbound)
                         .build();
 
         assertEquals(Arrays.asList(mSaProposal), sessionParams.getSaProposals());
-        assertEquals(Arrays.asList(tsInbound), sessionParams.getInboundTrafficSelectors());
-        assertEquals(Arrays.asList(tsOutbound), sessionParams.getOutboundTrafficSelectors());
+        assertEquals(Arrays.asList(mTsInbound), sessionParams.getInboundTrafficSelectors());
+        assertEquals(Arrays.asList(mTsOutbound), sessionParams.getOutboundTrafficSelectors());
     }
 
     @Test
@@ -134,4 +135,18 @@
 
         return new IkeTrafficSelector(0, 65535, tsStartAddress, tsEndAddress);
     }
+
+    @Test
+    public void testConstructTransportModeChildParamsCopy() throws Exception {
+        TransportModeChildSessionParams childParams =
+                new TransportModeChildSessionParams.Builder()
+                        .addInboundTrafficSelectors(mTsInbound)
+                        .addOutboundTrafficSelectors(mTsOutbound)
+                        .addSaProposal(mSaProposal)
+                        .build();
+
+        TransportModeChildSessionParams result =
+                new TransportModeChildSessionParams.Builder(childParams).build();
+        assertEquals(childParams, result);
+    }
 }
diff --git a/tests/iketests/src/java/android/net/ipsec/ike/IkeSessionParamsTest.java b/tests/iketests/src/java/android/net/ipsec/ike/IkeSessionParamsTest.java
index 01dc9db..00fc7fd 100644
--- a/tests/iketests/src/java/android/net/ipsec/ike/IkeSessionParamsTest.java
+++ b/tests/iketests/src/java/android/net/ipsec/ike/IkeSessionParamsTest.java
@@ -825,4 +825,26 @@
                 new IkeSessionParams.Builder(sessionParams).setConfiguredNetwork(null).build();
         assertNull(result.getConfiguredNetwork());
     }
+
+    @Test
+    public void testCreateWithAndWithoutConnectivityMgr() throws Exception {
+        IkeSessionParams withConnectivityMgr =
+                new IkeSessionParams.Builder(mMockConnectManager)
+                        .setServerHostname(REMOTE_IPV4_HOST_ADDRESS)
+                        .addSaProposal(mIkeSaProposal)
+                        .setLocalIdentification(mLocalIdentification)
+                        .setRemoteIdentification(mRemoteIdentification)
+                        .setAuthPsk(PSK)
+                        .build();
+
+        IkeSessionParams withoutConnectivityMgr =
+                new IkeSessionParams.Builder()
+                        .setServerHostname(REMOTE_IPV4_HOST_ADDRESS)
+                        .addSaProposal(mIkeSaProposal)
+                        .setLocalIdentification(mLocalIdentification)
+                        .setRemoteIdentification(mRemoteIdentification)
+                        .setAuthPsk(PSK)
+                        .build();
+        assertEquals(withConnectivityMgr, withoutConnectivityMgr);
+    }
 }
diff --git a/tests/iketests/src/java/android/net/ipsec/ike/TunnelModeChildSessionParamsTest.java b/tests/iketests/src/java/android/net/ipsec/ike/TunnelModeChildSessionParamsTest.java
index 0475a27..76cd0b3 100644
--- a/tests/iketests/src/java/android/net/ipsec/ike/TunnelModeChildSessionParamsTest.java
+++ b/tests/iketests/src/java/android/net/ipsec/ike/TunnelModeChildSessionParamsTest.java
@@ -264,5 +264,27 @@
         } catch (IllegalArgumentException expected) {
         }
     }
+
+    @Test
+    public void testConstructTunnelModeChildParamsCopy() throws Exception {
+        TunnelModeChildSessionParams childParams =
+                new TunnelModeChildSessionParams.Builder()
+                        .addSaProposal(mSaProposal)
+                        .setLifetimeSeconds(
+                                (int) TimeUnit.HOURS.toSeconds(3L),
+                                (int) TimeUnit.HOURS.toSeconds(1L))
+                        .addInternalAddressRequest(AF_INET)
+                        .addInternalAddressRequest(AF_INET6)
+                        .addInternalAddressRequest(IPV4_ADDRESS)
+                        .addInternalAddressRequest(IPV6_ADDRESS, IP6_PREFIX_LEN)
+                        .addInternalDnsServerRequest(AF_INET)
+                        .addInternalDnsServerRequest(AF_INET6)
+                        .addInternalDhcpServerRequest(AF_INET)
+                        .build();
+
+        TunnelModeChildSessionParams result =
+                new TunnelModeChildSessionParams.Builder(childParams).build();
+        assertEquals(childParams, result);
+    }
 }