Merge "Remove the concept of byte order from StructNlAttr."
diff --git a/common/netlinkclient/src/android/net/netlink/StructNlAttr.java b/common/netlinkclient/src/android/net/netlink/StructNlAttr.java
index 747998d..59458c1 100644
--- a/common/netlinkclient/src/android/net/netlink/StructNlAttr.java
+++ b/common/netlinkclient/src/android/net/netlink/StructNlAttr.java
@@ -18,8 +18,8 @@
 
 import java.net.InetAddress;
 import java.net.UnknownHostException;
-import java.nio.ByteOrder;
 import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 
 
 /**
@@ -48,9 +48,7 @@
         }
         final int baseOffset = byteBuffer.position();
 
-        // Assume the byte order of the buffer is the expected byte order of the value.
-        final StructNlAttr struct = new StructNlAttr(byteBuffer.order());
-        // The byte order of nla_len and nla_type is always native.
+        final StructNlAttr struct = new StructNlAttr();
         final ByteOrder originalOrder = byteBuffer.order();
         byteBuffer.order(ByteOrder.nativeOrder());
         try {
@@ -91,16 +89,8 @@
     public short nla_type;
     public byte[] nla_value;
 
-    // The byte order used to read/write the value member. Netlink length and
-    // type members are always read/written in native order.
-    private ByteOrder mByteOrder = ByteOrder.nativeOrder();
-
     public StructNlAttr() {}
 
-    public StructNlAttr(ByteOrder byteOrder) {
-        mByteOrder = byteOrder;
-    }
-
     public StructNlAttr(short type, byte value) {
         nla_type = type;
         setValue(new byte[1]);
@@ -112,10 +102,16 @@
     }
 
     public StructNlAttr(short type, short value, ByteOrder order) {
-        this(order);
         nla_type = type;
         setValue(new byte[Short.BYTES]);
-        getValueAsByteBuffer().putShort(value);
+        final ByteBuffer buf = getValueAsByteBuffer();
+        final ByteOrder originalOrder = buf.order();
+        try {
+            buf.order(order);
+            buf.putShort(value);
+        } finally {
+            buf.order(originalOrder);
+        }
     }
 
     public StructNlAttr(short type, int value) {
@@ -123,10 +119,16 @@
     }
 
     public StructNlAttr(short type, int value, ByteOrder order) {
-        this(order);
         nla_type = type;
         setValue(new byte[Integer.BYTES]);
-        getValueAsByteBuffer().putInt(value);
+        final ByteBuffer buf = getValueAsByteBuffer();
+        final ByteOrder originalOrder = buf.order();
+        try {
+            buf.order(order);
+            buf.putInt(value);
+        } finally {
+            buf.order(originalOrder);
+        }
     }
 
     public StructNlAttr(short type, InetAddress ip) {
@@ -152,10 +154,27 @@
         return NetlinkConstants.alignedLengthOf(nla_len);
     }
 
+    public int getValueAsBe32(int defaultValue) {
+        final ByteBuffer byteBuffer = getValueAsByteBuffer();
+        if (byteBuffer == null || byteBuffer.remaining() != Integer.BYTES) {
+            return defaultValue;
+        }
+        final ByteOrder originalOrder = byteBuffer.order();
+        try {
+            byteBuffer.order(ByteOrder.BIG_ENDIAN);
+            return byteBuffer.getInt();
+        } finally {
+            byteBuffer.order(originalOrder);
+        }
+    }
+
     public ByteBuffer getValueAsByteBuffer() {
         if (nla_value == null) { return null; }
         final ByteBuffer byteBuffer = ByteBuffer.wrap(nla_value);
-        byteBuffer.order(mByteOrder);
+        // By convention, all buffers in this library are in native byte order because netlink is in
+        // native byte order. It's the order that is used by NetlinkSocket.recvMessage and the only
+        // order accepted by NetlinkMessage.parse.
+        byteBuffer.order(ByteOrder.nativeOrder());
         return byteBuffer;
     }
 
diff --git a/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java b/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
index c3f9068..a1f1d44 100644
--- a/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
+++ b/tests/unit/src/android/net/netlink/RtNetlinkNeighborMessageTest.java
@@ -151,6 +151,13 @@
             assertEquals(0, hdr.nlmsg_seq);
             assertEquals(11070, hdr.nlmsg_pid);
 
+            final int probes = neighMsg.getProbes();
+            assertTrue("Unexpected number of probes. Got " +  probes + ", max=5",
+                    probes < 5);
+            final int ndm_refcnt = neighMsg.getCacheInfo().ndm_refcnt;
+            assertTrue("nda_cacheinfo has unexpectedly high ndm_refcnt: " + ndm_refcnt,
+                    ndm_refcnt < 0x100);
+
             messageCount++;
         }
         // TODO: add more detailed spot checks.