Merge "Add bool type to Struct.java." into main am: 5884049cbd am: 23714973c2

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/3238024

Change-Id: I1d73ee664974938d687b3187985e43055c2689ed
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/staticlibs/device/com/android/net/module/util/Struct.java b/staticlibs/device/com/android/net/module/util/Struct.java
index ff7a711..69ca678 100644
--- a/staticlibs/device/com/android/net/module/util/Struct.java
+++ b/staticlibs/device/com/android/net/module/util/Struct.java
@@ -105,6 +105,7 @@
  */
 public class Struct {
     public enum Type {
+        Bool,        // bool,           size = 1 byte
         U8,          // unsigned byte,  size = 1 byte
         U16,         // unsigned short, size = 2 bytes
         U32,         // unsigned int,   size = 4 bytes
@@ -169,6 +170,9 @@
 
     private static void checkAnnotationType(final Field annotation, final Class fieldType) {
         switch (annotation.type()) {
+            case Bool:
+                if (fieldType == Boolean.TYPE) return;
+                break;
             case U8:
             case S16:
                 if (fieldType == Short.TYPE) return;
@@ -218,6 +222,7 @@
     private static int getFieldLength(final Field annotation) {
         int length = 0;
         switch (annotation.type()) {
+            case Bool:
             case U8:
             case S8:
                 length = 1;
@@ -357,6 +362,9 @@
         final Object value;
         checkAnnotationType(fieldInfo.annotation, fieldInfo.field.getType());
         switch (fieldInfo.annotation.type()) {
+            case Bool:
+                value = buf.get() != 0;
+                break;
             case U8:
                 value = (short) (buf.get() & 0xFF);
                 break;
@@ -457,6 +465,9 @@
     private static void putFieldValue(final ByteBuffer output, final FieldInfo fieldInfo,
             final Object value) throws BufferUnderflowException {
         switch (fieldInfo.annotation.type()) {
+            case Bool:
+                output.put((byte) (value != null && (boolean) value ? 1 : 0));
+                break;
             case U8:
                 output.put((byte) (((short) value) & 0xFF));
                 break;
@@ -748,6 +759,16 @@
         return sb.toString();
     }
 
+    /** A simple Struct which only contains a bool field. */
+    public static class Bool extends Struct {
+        @Struct.Field(order = 0, type = Struct.Type.Bool)
+        public final boolean val;
+
+        public Bool(final boolean val) {
+            this.val = val;
+        }
+    }
+
     /** A simple Struct which only contains a u8 field. */
     public static class U8 extends Struct {
         @Struct.Field(order = 0, type = Struct.Type.U8)
diff --git a/staticlibs/tests/unit/src/com/android/net/module/util/StructTest.java b/staticlibs/tests/unit/src/com/android/net/module/util/StructTest.java
index a39b7a3..0c2605f 100644
--- a/staticlibs/tests/unit/src/com/android/net/module/util/StructTest.java
+++ b/staticlibs/tests/unit/src/com/android/net/module/util/StructTest.java
@@ -32,6 +32,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.net.module.util.Struct.Bool;
 import com.android.net.module.util.Struct.Field;
 import com.android.net.module.util.Struct.Type;
 
@@ -133,6 +134,29 @@
         verifyHeaderParsing(msg);
     }
 
+    @Test
+    public void testBoolStruct() {
+        assertEquals(1, Struct.getSize(Bool.class));
+
+        assertEquals(false, Struct.parse(Bool.class, toByteBuffer("00")).val);
+        assertEquals(true,  Struct.parse(Bool.class, toByteBuffer("01")).val);
+        // maybe these should throw instead, but currently only 0 is false...
+        assertEquals(true,  Struct.parse(Bool.class, toByteBuffer("02")).val);
+        assertEquals(true,  Struct.parse(Bool.class, toByteBuffer("7F")).val);
+        assertEquals(true,  Struct.parse(Bool.class, toByteBuffer("80")).val);
+        assertEquals(true,  Struct.parse(Bool.class, toByteBuffer("FF")).val);
+
+        final var f = new Bool(false);
+        final var t = new Bool(true);
+        assertEquals(f.val, false);
+        assertEquals(t.val, true);
+
+        assertArrayEquals(toByteBuffer("00").array(), f.writeToBytes(ByteOrder.BIG_ENDIAN));
+        assertArrayEquals(toByteBuffer("00").array(), f.writeToBytes(ByteOrder.LITTLE_ENDIAN));
+        assertArrayEquals(toByteBuffer("01").array(), t.writeToBytes(ByteOrder.BIG_ENDIAN));
+        assertArrayEquals(toByteBuffer("01").array(), t.writeToBytes(ByteOrder.LITTLE_ENDIAN));
+    }
+
     public static class HeaderMsgWithoutConstructor extends Struct {
         static int sType;
         static int sLength;