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

Commit d758eda3 authored by Android Build Merger (Role)'s avatar Android Build Merger (Role) Committed by Android (Google) Code Review
Browse files

Merge changes from topic 'am-cf1d9b40771c43ef84f49f7752a3174b'

* changes:
  Merge "Merge "AWARE: Abstract structure of match filters" am: f358a69c am: 7f12aa54" into nyc-mr1-dev-plus-aosp am: c4289218 am: 50d2802a
  Merge "AWARE: Abstract structure of match filters" am: f358a69c am: 7f12aa54 am: 61eb0bf8 am: 257ed21d
parents 1381047f 04131417
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