Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61eb0bf8 authored by Etan Cohen's avatar Etan Cohen Committed by android-build-merger
Browse files

Merge "AWARE: Abstract structure of match filters" am: f358a69c

am: 7f12aa54

Change-Id: I6d70ec6234752e2d84ad72dcbcbb15dfad6ad5d1
parents 6a3e0921 7f12aa54
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ import android.os.Parcelable;
/**
 * Defines a request object to configure a Wi-Fi Aware network. Built using
 * {@link ConfigRequest.Builder}. Configuration is requested using
 * {@link WifiAwareManager#attach(android.os.Handler, WifiAwareAttachCallback)}.
 * {@link WifiAwareManager#attach(WifiAwareAttachCallback, android.os.Handler)}.
 * Note that the actual achieved configuration may be different from the
 * requested configuration - since different applications may request different
 * configurations.
+0 −340
Original line number Diff line number Diff line
/*
 * 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.aware;

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_AWARE_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);
    }
}
+12 −11
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

/**
 * Defines the configuration of a Aware publish session. Built using
@@ -84,7 +85,8 @@ public final class PublishConfig implements Parcelable {
    /** @hide */
    public final boolean mEnableTerminateNotification;

    private PublishConfig(byte[] serviceName, byte[] serviceSpecificInfo, byte[] matchFilter,
    /** @hide */
    public PublishConfig(byte[] serviceName, byte[] serviceSpecificInfo, byte[] matchFilter,
            int publishType, int publichCount, int ttlSec, boolean enableTerminateNotification) {
        mServiceName = serviceName;
        mServiceSpecificInfo = serviceSpecificInfo;
@@ -99,9 +101,9 @@ public final class PublishConfig implements Parcelable {
    public String toString() {
        return "PublishConfig [mServiceName='" + mServiceName + ", mServiceSpecificInfo='" + (
                (mServiceSpecificInfo == null) ? "null" : HexEncoding.encode(mServiceSpecificInfo))
                + ", mTxFilter=" + (new LvBufferUtils.LvIterable(1, mMatchFilter)).toString()
                + ", mPublishType=" + mPublishType + ", mPublishCount=" + mPublishCount
                + ", mTtlSec=" + mTtlSec + ", mEnableTerminateNotification="
                + ", mMatchFilter=" + (new TlvBufferUtils.TlvIterable(0, 1,
                mMatchFilter)).toString() + ", mPublishType=" + mPublishType + ", mPublishCount="
                + mPublishCount + ", mTtlSec=" + mTtlSec + ", mEnableTerminateNotification="
                + mEnableTerminateNotification + "]";
    }

@@ -186,7 +188,7 @@ public final class PublishConfig implements Parcelable {
            throws IllegalArgumentException {
        WifiAwareUtils.validateServiceName(mServiceName);

        if (!LvBufferUtils.isValid(mMatchFilter, 1)) {
        if (!TlvBufferUtils.isValid(mMatchFilter, 0, 1)) {
            throw new IllegalArgumentException(
                    "Invalid txFilter configuration - LV fields do not match up to length");
        }
@@ -281,18 +283,17 @@ public final class PublishConfig implements Parcelable {
         * The match filter for a publish session. Used to determine whether a service
         * discovery occurred - in addition to relying on the service name.
         * <p>
         * Format is an LV byte array: a single byte Length field followed by L bytes (the value of
         * the Length field) of a value blob.
         * <p>
         *     Optional. Empty by default.
         *
         * @param matchFilter The byte-array containing the LV formatted match filter.
         * @param matchFilter A list of match filter entries (each of which is an arbitrary byte
         *                    array).
         *
         * @return The builder to facilitate chaining
         *         {@code builder.setXXX(..).setXXX(..)}.
         */
        public Builder setMatchFilter(@Nullable byte[] matchFilter) {
            mMatchFilter = matchFilter;
        public Builder setMatchFilter(@Nullable List<byte[]> matchFilter) {
            mMatchFilter = new TlvBufferUtils.TlvConstructor(0, 1).allocateAndPut(
                    matchFilter).getArray();
            return this;
        }

+14 −12
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;

/**
 * Defines the configuration of a Aware subscribe session. Built using
@@ -106,7 +107,8 @@ public final class SubscribeConfig implements Parcelable {
    /** @hide */
    public final boolean mEnableTerminateNotification;

    private SubscribeConfig(byte[] serviceName, byte[] serviceSpecificInfo, byte[] matchFilter,
    /** @hide */
    public SubscribeConfig(byte[] serviceName, byte[] serviceSpecificInfo, byte[] matchFilter,
            int subscribeType, int publichCount, int ttlSec, int matchStyle,
            boolean enableTerminateNotification) {
        mServiceName = serviceName;
@@ -123,10 +125,11 @@ public final class SubscribeConfig implements Parcelable {
    public String toString() {
        return "SubscribeConfig [mServiceName='" + mServiceName + ", mServiceSpecificInfo='" + (
                (mServiceSpecificInfo == null) ? "null" : HexEncoding.encode(mServiceSpecificInfo))
                + ", mMatchFilter=" + (new LvBufferUtils.LvIterable(1, mMatchFilter)).toString()
                + ", mSubscribeType=" + mSubscribeType + ", mSubscribeCount=" + mSubscribeCount
                + ", mTtlSec=" + mTtlSec + ", mMatchType=" + mMatchStyle
                + ", mEnableTerminateNotification=" + mEnableTerminateNotification + "]";
                + ", mMatchFilter=" + (new TlvBufferUtils.TlvIterable(0, 1,
                mMatchFilter)).toString() + ", mSubscribeType=" + mSubscribeType
                + ", mSubscribeCount=" + mSubscribeCount + ", mTtlSec=" + mTtlSec + ", mMatchType="
                + mMatchStyle + ", mEnableTerminateNotification=" + mEnableTerminateNotification
                + "]";
    }

    @Override
@@ -213,7 +216,7 @@ public final class SubscribeConfig implements Parcelable {
            throws IllegalArgumentException {
        WifiAwareUtils.validateServiceName(mServiceName);

        if (!LvBufferUtils.isValid(mMatchFilter, 1)) {
        if (!TlvBufferUtils.isValid(mMatchFilter, 0, 1)) {
            throw new IllegalArgumentException(
                    "Invalid matchFilter configuration - LV fields do not match up to length");
        }
@@ -313,18 +316,17 @@ public final class SubscribeConfig implements Parcelable {
         * The match filter for a subscribe session. Used to determine whether a service
         * discovery occurred - in addition to relying on the service name.
         * <p>
         * Format is an LV byte array: a single byte Length field followed by L bytes (the value of
         * the Length field) of a value blob.
         * <p>
         *     Optional. Empty by default.
         *
         * @param matchFilter The byte-array containing the LV formatted match filter.
         * @param matchFilter A list of match filter entries (each of which is an arbitrary byte
         *                    array).
         *
         * @return The builder to facilitate chaining
         *         {@code builder.setXXX(..).setXXX(..)}.
         */
        public Builder setMatchFilter(@Nullable byte[] matchFilter) {
            mMatchFilter = matchFilter;
        public Builder setMatchFilter(@Nullable List<byte[]> matchFilter) {
            mMatchFilter = new TlvBufferUtils.TlvConstructor(0, 1).allocateAndPut(
                    matchFilter).getArray();
            return this;
        }

+45 −2
Original line number Diff line number Diff line
@@ -22,8 +22,10 @@ import libcore.io.Memory;

import java.nio.BufferOverflowException;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

/**
@@ -32,7 +34,7 @@ import java.util.NoSuchElementException;
 * the Type field and the Length field. A Type field size of 0 is allowed -
 * allowing usage for LV (no T) array formats.
 *
 * @hide PROPOSED_AWARE_API
 * @hide
 */
public class TlvBufferUtils {
    private TlvBufferUtils() {
@@ -110,6 +112,31 @@ public class TlvBufferUtils {
            return this;
        }

        /**
         * Creates a TLV array (of the previously specified Type and Length sizes) from the input
         * list. Allocates an array matching the contents (and required Type and Length
         * fields), copies the contents, and set the Length fields. The Type field is set to 0.
         *
         * @param list A list of fields to be added to the TLV buffer.
         * @return The constructor of the TLV.
         */
        public TlvConstructor allocateAndPut(@Nullable List<byte[]> list) {
            if (list != null) {
                int size = 0;
                for (byte[] field : list) {
                    size += mTypeSize + mLengthSize;
                    if (field != null) {
                        size += field.length;
                    }
                }
                allocate(size);
                for (byte[] field : list) {
                    putByteArray(0, field);
                }
            }
            return this;
        }

        /**
         * Copies a byte into the TLV with the indicated type. For an LV
         * formatted structure (i.e. typeLength=0 in {@link TlvConstructor
@@ -319,6 +346,10 @@ public class TlvBufferUtils {
            this.length = length;
            this.refArray = refArray;
            this.offset = offset;

            if (offset + length > refArray.length) {
                throw new BufferOverflowException();
            }
        }

        /**
@@ -393,7 +424,7 @@ public class TlvBufferUtils {
         * @param typeSize Number of bytes used for the Type (T) field. Valid
         *            values are 0 (i.e. indicating the format is LV rather than
         *            TLV), 1, and 2 bytes.
         * @param lengthSize Number of bytes sued for the Length (L) field.
         * @param lengthSize Number of bytes used for the Length (L) field.
         *            Values values are 1 or 2 bytes.
         * @param array The TLV formatted byte-array to parse.
         */
@@ -449,6 +480,18 @@ public class TlvBufferUtils {
            return builder.toString();
        }

        /**
         * Returns a List with the raw contents (no types) of the iterator.
         */
        public List<byte[]> toList() {
            List<byte[]> list = new ArrayList<>();
            for (TlvElement tlv : this) {
                list.add(Arrays.copyOfRange(tlv.refArray, tlv.offset, tlv.offset + tlv.length));
            }

            return list;
        }

        /**
         * Returns an iterator to step through a TLV formatted byte-array. The
         * individual elements returned by the iterator are {@link TlvElement}.
Loading