Delete buildIaPdOption and introduce PrefixDelegation#build

There is no reason to have a static helper function. Moving this to
PrefixDelegation is better OO. Encapsulate both decode and build methods
for IA_PD options inside PrefixDelegation class.

Test: atest NetworkStackIntegrationTests
Change-Id: I6ffdbb3701449c54ef7db0302fb0a32710ceb722
diff --git a/src/android/net/dhcp6/Dhcp6Client.java b/src/android/net/dhcp6/Dhcp6Client.java
index 990f026..2f74a06 100644
--- a/src/android/net/dhcp6/Dhcp6Client.java
+++ b/src/android/net/dhcp6/Dhcp6Client.java
@@ -68,7 +68,6 @@
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.List;
 import java.util.Random;
 import java.util.function.IntSupplier;
 
@@ -465,10 +464,6 @@
         return transmitPacket(packet, "rebind");
     }
 
-    private ByteBuffer buildIaPdOption(@NonNull final List<IaPrefixOption> ipos) {
-        return Dhcp6Packet.buildIaPdOption(IAID, 0 /* t1 */, 0 /* t2 */, ipos);
-    }
-
     /**
      * Parent state at which client does initialization of interface and packet handler, also
      * processes the CMD_STOP_DHCP6 command in this state which child states don't handle.
@@ -543,11 +538,12 @@
 
         @Override
         protected boolean sendPacket(int transId, long elapsedTimeMs) {
-            final IaPrefixOption emptyPrefix = new IaPrefixOption((short) IaPrefixOption.LENGTH,
+            final IaPrefixOption hintOption = new IaPrefixOption((short) IaPrefixOption.LENGTH,
                     0 /* preferred */, 0 /* valid */, (byte) RFC7421_PREFIX_LENGTH,
                     new byte[16] /* empty prefix */);
-            return sendSolicitPacket(transId, elapsedTimeMs,
-                    buildIaPdOption(Collections.singletonList(emptyPrefix)));
+            final PrefixDelegation pd = new PrefixDelegation(IAID, 0 /* t1 */, 0 /* t2 */,
+                    Collections.singletonList(hintOption));
+            return sendSolicitPacket(transId, elapsedTimeMs, pd.build());
         }
 
         // TODO: support multiple prefixes.
@@ -587,7 +583,7 @@
 
         @Override
         protected boolean sendPacket(int transId, long elapsedTimeMs) {
-            return sendRequestPacket(transId, elapsedTimeMs, buildIaPdOption(mAdvertise.ipos));
+            return sendRequestPacket(transId, elapsedTimeMs, mAdvertise.build());
         }
 
         @Override
@@ -753,7 +749,7 @@
 
         @Override
         protected boolean sendPacket(int transId, long elapsedTimeMs) {
-            return sendRenewPacket(transId, elapsedTimeMs, buildIaPdOption(mReply.ipos));
+            return sendRenewPacket(transId, elapsedTimeMs, mReply.build());
         }
     }
 
@@ -769,7 +765,7 @@
 
         @Override
         protected boolean sendPacket(int transId, long elapsedTimeMs) {
-            return sendRebindPacket(transId, elapsedTimeMs, buildIaPdOption(mReply.ipos));
+            return sendRebindPacket(transId, elapsedTimeMs, mReply.build());
         }
     }
 
diff --git a/src/android/net/dhcp6/Dhcp6Packet.java b/src/android/net/dhcp6/Dhcp6Packet.java
index 9eb2a74..250aa73 100644
--- a/src/android/net/dhcp6/Dhcp6Packet.java
+++ b/src/android/net/dhcp6/Dhcp6Packet.java
@@ -211,7 +211,8 @@
         @NonNull
         public final List<IaPrefixOption> ipos;
 
-        PrefixDelegation(int iaid, int t1, int t2, @NonNull final List<IaPrefixOption> ipos) {
+        public PrefixDelegation(int iaid, int t1, int t2,
+                @NonNull final List<IaPrefixOption> ipos) {
             Objects.requireNonNull(ipos);
             this.iaid = iaid;
             this.t1 = t1;
@@ -242,7 +243,7 @@
         }
 
         /**
-         * Decode IA Prefix options.
+         * Decode an IA_PD option from the byte buffer.
          */
         public static PrefixDelegation decode(@NonNull final ByteBuffer buffer)
                 throws ParseException {
@@ -274,6 +275,22 @@
         }
 
         /**
+         * Build an IA_PD option from given specific parameters, including IA_PREFIX options.
+         */
+        public ByteBuffer build() {
+            final ByteBuffer iapd = ByteBuffer.allocate(IaPdOption.LENGTH
+                    + Struct.getSize(IaPrefixOption.class) * ipos.size());
+            iapd.putInt(iaid);
+            iapd.putInt(t1);
+            iapd.putInt(t2);
+            for (IaPrefixOption ipo : ipos) {
+                ipo.writeToByteBuffer(iapd);
+            }
+            iapd.flip();
+            return iapd;
+        }
+
+        /**
          * Return valid IA prefix options to be used and extended in the Reply message. It may
          * return empty list if there isn't any valid IA prefix option in the Reply message.
          *
@@ -611,23 +628,6 @@
     }
 
     /**
-     * Build an IA_PD option from given specific parameters, including IA_PREFIX option.
-     */
-    public static ByteBuffer buildIaPdOption(int iaid, int t1, int t2,
-            @NonNull final List<IaPrefixOption> ipos) {
-        final ByteBuffer iapd = ByteBuffer.allocate(IaPdOption.LENGTH
-                + Struct.getSize(IaPrefixOption.class) * ipos.size());
-        iapd.putInt(iaid);
-        iapd.putInt(t1);
-        iapd.putInt(t2);
-        for (IaPrefixOption ipo : ipos) {
-            ipo.writeToByteBuffer(iapd);
-        }
-        iapd.flip();
-        return iapd;
-    }
-
-    /**
      * Builds a DHCPv6 SOLICIT packet from the required specified parameters.
      */
     public static ByteBuffer buildSolicitPacket(int transId, long millisecs,
diff --git a/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java b/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java
index 6e8e535..3f6d8fc 100644
--- a/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java
+++ b/tests/integration/common/android/net/ip/IpClientIntegrationTestCommon.java
@@ -153,6 +153,7 @@
 import android.net.dhcp.DhcpRequestPacket;
 import android.net.dhcp6.Dhcp6Client;
 import android.net.dhcp6.Dhcp6Packet;
+import android.net.dhcp6.Dhcp6Packet.PrefixDelegation;
 import android.net.dhcp6.Dhcp6RebindPacket;
 import android.net.dhcp6.Dhcp6RenewPacket;
 import android.net.dhcp6.Dhcp6RequestPacket;
@@ -4825,8 +4826,9 @@
         ByteBuffer iapd;
         Dhcp6Packet packet;
         while ((packet = getNextDhcp6Packet()) != null) {
+            final PrefixDelegation pd = new PrefixDelegation(packet.getIaId(), t1, t2, ipos);
+            iapd = pd.build();
             if (packet instanceof Dhcp6SolicitPacket) {
-                iapd = Dhcp6Packet.buildIaPdOption(packet.getIaId(), t1, t2, ipos);
                 if (shouldReplyRapidCommit) {
                     mPacketReader.sendResponse(buildDhcp6Reply(packet, iapd.array(), mClientMac,
                             (Inet6Address) mClientIpAddress, true /* rapidCommit */));
@@ -4835,8 +4837,6 @@
                             (Inet6Address) mClientIpAddress));
                 }
             } else if (packet instanceof Dhcp6RequestPacket) {
-                final PrefixDelegation pd = packet.getPrefixDelegation();
-                iapd = Dhcp6Packet.buildIaPdOption(packet.getIaId(), pd.t1, pd.t2, pd.ipos);
                 mPacketReader.sendResponse(buildDhcp6Reply(packet, iapd.array(), mClientMac,
                           (Inet6Address) mClientIpAddress, false /* rapidCommit */));
             } else {
@@ -5087,8 +5087,9 @@
         final IpPrefix prefix1 = new IpPrefix("2001:db8:2::/64");
         final IaPrefixOption ipo = buildIaPrefixOption(prefix1, 4500 /* preferred */,
                 7200 /* valid */);
-        final ByteBuffer iapd = Dhcp6Packet.buildIaPdOption(packet.getIaId(), 3600 /* t1*/,
+        final PrefixDelegation pd = new PrefixDelegation(packet.getIaId(), 3600 /* t1 */,
                 4500 /* t2 */, Collections.singletonList(ipo));
+        final ByteBuffer iapd = pd.build();
         mPacketReader.sendResponse(buildDhcp6Reply(packet, iapd.array(), mClientMac,
                 (Inet6Address) mClientIpAddress, false /* rapidCommit */));
         verify(mCb, timeout(TEST_TIMEOUT_MS)).onProvisioningFailure(any());