[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
This commit is contained in:
340
wifi/java/android/net/wifi/nan/LvBufferUtils.java
Normal file
340
wifi/java/android/net/wifi/nan/LvBufferUtils.java
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -116,8 +116,8 @@ public class PublishConfig implements Parcelable {
|
||||
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 class PublishConfig implements Parcelable {
|
||||
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 @@ public class PublishConfig implements Parcelable {
|
||||
* 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 @@ public class PublishConfig implements Parcelable {
|
||||
* (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
|
||||
|
||||
@@ -140,8 +140,8 @@ public class SubscribeConfig implements Parcelable {
|
||||
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 class SubscribeConfig implements Parcelable {
|
||||
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 @@ public class SubscribeConfig implements Parcelable {
|
||||
* 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 @@ public class SubscribeConfig implements Parcelable {
|
||||
* 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
|
||||
|
||||
Reference in New Issue
Block a user