[NAN] Add LV utilities (TLV with T size of 0).

NAN uses LV (not TLV). Expose an LV variant of TLV to make API
cleaner.

Bug: 30096512
Change-Id: I74b4c514d50f1df5750b521bd68a5e2d832d92c3
(cherry picked from commit 009b1fcb85ab8f8eb4ab5f3e125127b449df77cb)
diff --git a/wifi/java/android/net/wifi/nan/LvBufferUtils.java b/wifi/java/android/net/wifi/nan/LvBufferUtils.java
new file mode 100644
index 0000000..eb56070
--- /dev/null
+++ b/wifi/java/android/net/wifi/nan/LvBufferUtils.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.nan;
+
+import android.annotation.Nullable;
+
+import libcore.io.Memory;
+
+import java.nio.ByteOrder;
+import java.util.Iterator;
+
+/**
+ * Utility class to construct and parse byte arrays using the LV format -
+ * Length/Value format. The utilities accept a configuration of the size of
+ * the Length field.
+ *
+ * @hide PROPOSED_NAN_API
+ */
+public class LvBufferUtils {
+    private LvBufferUtils() {
+        // no reason to ever create this class
+    }
+
+    /**
+     * Utility class to construct byte arrays using the LV format - Length/Value.
+     * <p>
+     * A constructor is created specifying the size of the Length (L) field.
+     * <p>
+     * The byte array is either provided (using
+     * {@link LvBufferUtils.LvConstructor#wrap(byte[])}) or allocated (using
+     * {@link LvBufferUtils.LvConstructor#allocate(int)}).
+     * <p>
+     * Values are added to the structure using the {@code LvConstructor.put*()}
+     * methods.
+     * <p>
+     * The final byte array is obtained using {@link LvBufferUtils.LvConstructor#getArray()}.
+     */
+    public static class LvConstructor {
+        private TlvBufferUtils.TlvConstructor mTlvImpl;
+
+        /**
+         * Define a LV constructor with the specified size of the Length (L) field.
+         *
+         * @param lengthSize Number of bytes used for the Length (L) field.
+         *            Values of 1 or 2 bytes are allowed.
+         */
+        public LvConstructor(int lengthSize) {
+            mTlvImpl = new TlvBufferUtils.TlvConstructor(0, lengthSize);
+        }
+
+        /**
+         * Set the byte array to be used to construct the LV.
+         *
+         * @param array Byte array to be formatted.
+         * @return The constructor to facilitate chaining
+         *         {@code ctr.putXXX(..).putXXX(..)}.
+         */
+        public LvBufferUtils.LvConstructor wrap(@Nullable byte[] array) {
+            mTlvImpl.wrap(array);
+            return this;
+        }
+
+        /**
+         * Allocates a new byte array to be used ot construct a LV.
+         *
+         * @param capacity The size of the byte array to be allocated.
+         * @return The constructor to facilitate chaining
+         *         {@code ctr.putXXX(..).putXXX(..)}.
+         */
+        public LvBufferUtils.LvConstructor allocate(int capacity) {
+            mTlvImpl.allocate(capacity);
+            return this;
+        }
+
+        /**
+         * Copies a byte into the LV array.
+         *
+         * @param b The byte to be inserted into the structure.
+         * @return The constructor to facilitate chaining
+         *         {@code ctr.putXXX(..).putXXX(..)}.
+         */
+        public LvBufferUtils.LvConstructor putByte(byte b) {
+            mTlvImpl.putByte(0, b);
+            return this;
+        }
+
+        /**
+         * Copies a byte array into the LV.
+         *
+         * @param array The array to be copied into the LV structure.
+         * @param offset Start copying from the array at the specified offset.
+         * @param length Copy the specified number (length) of bytes from the
+         *            array.
+         * @return The constructor to facilitate chaining
+         *         {@code ctr.putXXX(..).putXXX(..)}.
+         */
+        public LvBufferUtils.LvConstructor putByteArray(@Nullable byte[] array, int offset,
+                int length) {
+            mTlvImpl.putByteArray(0, array, offset, length);
+            return this;
+        }
+
+        /**
+         * Copies a byte array into the LV.
+         *
+         * @param array The array to be copied (in full) into the LV structure.
+         * @return The constructor to facilitate chaining
+         *         {@code ctr.putXXX(..).putXXX(..)}.
+         */
+        public LvBufferUtils.LvConstructor putByteArray(int type, @Nullable byte[] array) {
+            return putByteArray(array, 0, (array == null) ? 0 : array.length);
+        }
+
+        /**
+         * Places a zero length element (i.e. Length field = 0) into the LV.
+         *
+         * @return The constructor to facilitate chaining
+         *         {@code ctr.putXXX(..).putXXX(..)}.
+         */
+        public LvBufferUtils.LvConstructor putZeroLengthElement() {
+            mTlvImpl.putZeroLengthElement(0);
+            return this;
+        }
+
+        /**
+         * Copies short into the LV.
+         *
+         * @param data The short to be inserted into the structure.
+         * @return The constructor to facilitate chaining
+         *         {@code ctr.putXXX(..).putXXX(..)}.
+         */
+        public LvBufferUtils.LvConstructor putShort(short data) {
+            mTlvImpl.putShort(0, data);
+            return this;
+        }
+
+        /**
+         * Copies integer into the LV.
+         *
+         * @param data The integer to be inserted into the structure.
+         * @return The constructor to facilitate chaining
+         *         {@code ctr.putXXX(..).putXXX(..)}.
+         */
+        public LvBufferUtils.LvConstructor putInt(int data) {
+            mTlvImpl.putInt(0, data);
+            return this;
+        }
+
+        /**
+         * Copies a String's byte representation into the LV.
+         *
+         * @param data The string whose bytes are to be inserted into the
+         *            structure.
+         * @return The constructor to facilitate chaining
+         *         {@code ctr.putXXX(..).putXXX(..)}.
+         */
+        public LvBufferUtils.LvConstructor putString(@Nullable String data) {
+            mTlvImpl.putString(0, data);
+            return this;
+        }
+
+        /**
+         * Returns the constructed LV formatted byte-array. This array is a copy of the wrapped
+         * or allocated array - truncated to just the significant bytes - i.e. those written into
+         * the LV.
+         *
+         * @return The byte array containing the LV formatted structure.
+         */
+        public byte[] getArray() {
+            return mTlvImpl.getArray();
+        }
+    }
+
+    /**
+     * Utility class used when iterating over an LV formatted byte-array. Use
+     * {@link LvBufferUtils.LvIterable} to iterate over array. A {@link LvBufferUtils.LvElement}
+     * represents each entry in a LV formatted byte-array.
+     */
+    public static class LvElement {
+        /**
+         * The Length (L) field of the current LV element.
+         */
+        public int length;
+
+        /**
+         * The Value (V) field - a raw byte array representing the current LV
+         * element where the entry starts at {@link LvBufferUtils.LvElement#offset}.
+         */
+        public byte[] refArray;
+
+        /**
+         * The offset to be used into {@link LvBufferUtils.LvElement#refArray} to access the
+         * raw data representing the current LV element.
+         */
+        public int offset;
+
+        private LvElement(int length, @Nullable byte[] refArray, int offset) {
+            this.length = length;
+            this.refArray = refArray;
+            this.offset = offset;
+        }
+
+        /**
+         * Utility function to return a byte representation of a LV element of
+         * length 1. Note: an attempt to call this function on a LV item whose
+         * {@link LvBufferUtils.LvElement#length} is != 1 will result in an exception.
+         *
+         * @return byte representation of current LV element.
+         */
+        public byte getByte() {
+            if (length != 1) {
+                throw new IllegalArgumentException(
+                        "Accesing a byte from a LV element of length " + length);
+            }
+            return refArray[offset];
+        }
+
+        /**
+         * Utility function to return a short representation of a LV element of
+         * length 2. Note: an attempt to call this function on a LV item whose
+         * {@link LvBufferUtils.LvElement#length} is != 2 will result in an exception.
+         *
+         * @return short representation of current LV element.
+         */
+        public short getShort() {
+            if (length != 2) {
+                throw new IllegalArgumentException(
+                        "Accesing a short from a LV element of length " + length);
+            }
+            return Memory.peekShort(refArray, offset, ByteOrder.BIG_ENDIAN);
+        }
+
+        /**
+         * Utility function to return an integer representation of a LV element
+         * of length 4. Note: an attempt to call this function on a LV item
+         * whose {@link LvBufferUtils.LvElement#length} is != 4 will result in an exception.
+         *
+         * @return integer representation of current LV element.
+         */
+        public int getInt() {
+            if (length != 4) {
+                throw new IllegalArgumentException(
+                        "Accesing an int from a LV element of length " + length);
+            }
+            return Memory.peekInt(refArray, offset, ByteOrder.BIG_ENDIAN);
+        }
+
+        /**
+         * Utility function to return a String representation of a LV element.
+         *
+         * @return String representation of the current LV element.
+         */
+        public String getString() {
+            return new String(refArray, offset, length);
+        }
+    }
+
+    /**
+     * Utility class to iterate over a LV formatted byte-array.
+     */
+    public static class LvIterable implements Iterable<LvBufferUtils.LvElement> {
+        private final TlvBufferUtils.TlvIterable mTlvIterable;
+
+        /**
+         * Constructs an LvIterable object - specifying the format of the LV
+         * (the size of the Length field), and the byte array whose data is to be parsed.
+         *
+         * @param lengthSize Number of bytes sued for the Length (L) field.
+         *            Values values are 1 or 2 bytes.
+         * @param array The LV formatted byte-array to parse.
+         */
+        public LvIterable(int lengthSize, @Nullable byte[] array) {
+            mTlvIterable = new TlvBufferUtils.TlvIterable(0, lengthSize, array);
+        }
+
+        /**
+         * Prints out a parsed representation of the LV-formatted byte array.
+         * Whenever possible bytes, shorts, and integer are printed out (for
+         * fields whose length is 1, 2, or 4 respectively).
+         */
+        @Override
+        public String toString() {
+            return mTlvIterable.toString();
+        }
+
+        /**
+         * Returns an iterator to step through a LV formatted byte-array. The
+         * individual elements returned by the iterator are {@link LvBufferUtils.LvElement}.
+         */
+        @Override
+        public Iterator<LvBufferUtils.LvElement> iterator() {
+            return new Iterator<LvBufferUtils.LvElement>() {
+                private Iterator<TlvBufferUtils.TlvElement> mTlvIterator = mTlvIterable.iterator();
+
+                @Override
+                public boolean hasNext() {
+                    return mTlvIterator.hasNext();
+                }
+
+                @Override
+                public LvBufferUtils.LvElement next() {
+                    TlvBufferUtils.TlvElement tlvE = mTlvIterator.next();
+
+                    return new LvElement(tlvE.length, tlvE.refArray, tlvE.offset);
+                }
+
+                @Override
+                public void remove() {
+                    throw new UnsupportedOperationException();
+                }
+            };
+        }
+    }
+
+    /**
+     * Validates that a LV array is constructed correctly. I.e. that its specified Length
+     * fields correctly fill the specified length (and do not overshoot).
+     *
+     * @param array The LV array to verify.
+     * @param lengthSize The size (in bytes) of the length field. Valid values are 1 or 2.
+     * @return A boolean indicating whether the array is valid (true) or invalid (false).
+     */
+    public static boolean isValid(@Nullable byte[] array, int lengthSize) {
+        return TlvBufferUtils.isValid(array, 0, lengthSize);
+    }
+}
diff --git a/wifi/java/android/net/wifi/nan/PublishConfig.java b/wifi/java/android/net/wifi/nan/PublishConfig.java
index 3bc5251..3fd756e 100644
--- a/wifi/java/android/net/wifi/nan/PublishConfig.java
+++ b/wifi/java/android/net/wifi/nan/PublishConfig.java
@@ -116,8 +116,8 @@
     public String toString() {
         return "PublishConfig [mServiceName='" + mServiceName + ", mServiceSpecificInfo='" + (
                 (mServiceSpecificInfo == null) ? "null" : HexEncoding.encode(mServiceSpecificInfo))
-                + ", mTxFilter=" + (new TlvBufferUtils.TlvIterable(0, 1, mTxFilter)).toString()
-                + ", mRxFilter=" + (new TlvBufferUtils.TlvIterable(0, 1, mRxFilter)).toString()
+                + ", mTxFilter=" + (new LvBufferUtils.LvIterable(1, mTxFilter)).toString()
+                + ", mRxFilter=" + (new LvBufferUtils.LvIterable(1, mRxFilter)).toString()
                 + ", mPublishType=" + mPublishType + ", mPublishCount=" + mPublishCount
                 + ", mTtlSec=" + mTtlSec + ", mEnableTerminateNotification="
                 + mEnableTerminateNotification + "]";
@@ -206,11 +206,11 @@
     public void validate() throws IllegalArgumentException {
         WifiNanUtils.validateServiceName(mServiceName);
 
-        if (!TlvBufferUtils.isValid(mTxFilter, 0, 1)) {
+        if (!LvBufferUtils.isValid(mTxFilter, 1)) {
             throw new IllegalArgumentException(
                     "Invalid txFilter configuration - LV fields do not match up to length");
         }
-        if (!TlvBufferUtils.isValid(mRxFilter, 0, 1)) {
+        if (!LvBufferUtils.isValid(mRxFilter, 1)) {
             throw new IllegalArgumentException(
                     "Invalid rxFilter configuration - LV fields do not match up to length");
         }
@@ -310,7 +310,7 @@
          * determine whether they match - in addition to just relying on the
          * service name.
          * <p>
-         * Format is an LV byte array - the {@link TlvBufferUtils} utility class
+         * Format is an LV byte array - the {@link LvBufferUtils} utility class
          * is available to form and parse.
          *
          * @param txFilter The byte-array containing the LV formatted transmit
@@ -331,7 +331,7 @@
          * (active subscribers) - in addition to just relying on the service
          * name.
          * <p>
-         * Format is an LV byte array - the {@link TlvBufferUtils} utility class
+         * Format is an LV byte array - the {@link LvBufferUtils} utility class
          * is available to form and parse.
          *
          * @param rxFilter The byte-array containing the LV formatted receive
diff --git a/wifi/java/android/net/wifi/nan/SubscribeConfig.java b/wifi/java/android/net/wifi/nan/SubscribeConfig.java
index 4e53073..fd19ddb 100644
--- a/wifi/java/android/net/wifi/nan/SubscribeConfig.java
+++ b/wifi/java/android/net/wifi/nan/SubscribeConfig.java
@@ -140,8 +140,8 @@
     public String toString() {
         return "SubscribeConfig [mServiceName='" + mServiceName + ", mServiceSpecificInfo='" + (
                 (mServiceSpecificInfo == null) ? "null" : HexEncoding.encode(mServiceSpecificInfo))
-                + ", mTxFilter=" + (new TlvBufferUtils.TlvIterable(0, 1, mTxFilter)).toString()
-                + ", mRxFilter=" + (new TlvBufferUtils.TlvIterable(0, 1, mRxFilter)).toString()
+                + ", mTxFilter=" + (new LvBufferUtils.LvIterable(1, mTxFilter)).toString()
+                + ", mRxFilter=" + (new LvBufferUtils.LvIterable(1, mRxFilter)).toString()
                 + ", mSubscribeType=" + mSubscribeType + ", mSubscribeCount=" + mSubscribeCount
                 + ", mTtlSec=" + mTtlSec + ", mMatchType=" + mMatchStyle
                 + ", mEnableTerminateNotification=" + mEnableTerminateNotification + "]";
@@ -234,11 +234,11 @@
     public void validate() throws IllegalArgumentException {
         WifiNanUtils.validateServiceName(mServiceName);
 
-        if (!TlvBufferUtils.isValid(mTxFilter, 0, 1)) {
+        if (!LvBufferUtils.isValid(mTxFilter, 1)) {
             throw new IllegalArgumentException(
                     "Invalid txFilter configuration - LV fields do not match up to length");
         }
-        if (!TlvBufferUtils.isValid(mRxFilter, 0, 1)) {
+        if (!LvBufferUtils.isValid(mRxFilter, 1)) {
             throw new IllegalArgumentException(
                     "Invalid rxFilter configuration - LV fields do not match up to length");
         }
@@ -344,7 +344,7 @@
          * publishers) to determine whether they match - in addition to just
          * relying on the service name.
          * <p>
-         * Format is an LV byte array - the {@link TlvBufferUtils} utility class
+         * Format is an LV byte array - the {@link LvBufferUtils} utility class
          * is available to form and parse.
          *
          * @param txFilter The byte-array containing the LV formatted transmit
@@ -364,7 +364,7 @@
          * subscriber to determine whether they match transmitted publish
          * packets - in addition to just relying on the service name.
          * <p>
-         * Format is an LV byte array - the {@link TlvBufferUtils} utility class
+         * Format is an LV byte array - the {@link LvBufferUtils} utility class
          * is available to form and parse.
          *
          * @param rxFilter The byte-array containing the LV formatted receive