Loading core/api/current.txt +27 −0 Original line number Diff line number Diff line Loading @@ -9546,6 +9546,7 @@ package android.bluetooth.le { method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData(); method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids(); method public java.util.List<android.os.ParcelUuid> getServiceUuids(); method @NonNull public java.util.List<android.bluetooth.le.TransportDiscoveryData> getTransportDiscoveryData(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseData> CREATOR; } Loading @@ -9556,6 +9557,7 @@ package android.bluetooth.le { method public android.bluetooth.le.AdvertiseData.Builder addServiceData(android.os.ParcelUuid, byte[]); method @NonNull public android.bluetooth.le.AdvertiseData.Builder addServiceSolicitationUuid(@NonNull android.os.ParcelUuid); method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid); method @NonNull public android.bluetooth.le.AdvertiseData.Builder addTransportDiscoveryData(@NonNull android.bluetooth.le.TransportDiscoveryData); method public android.bluetooth.le.AdvertiseData build(); method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean); method public android.bluetooth.le.AdvertiseData.Builder setIncludeTxPowerLevel(boolean); Loading Loading @@ -9815,6 +9817,31 @@ package android.bluetooth.le { method public android.bluetooth.le.ScanSettings.Builder setScanMode(int); } public final class TransportBlock implements android.os.Parcelable { ctor public TransportBlock(int, int, int, @Nullable byte[]); method public int describeContents(); method public int getOrgId(); method public int getTdsFlags(); method @Nullable public byte[] getTransportData(); method public int getTransportDataLength(); method @Nullable public byte[] toByteArray(); method public int totalBytes(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportBlock> CREATOR; } public final class TransportDiscoveryData implements android.os.Parcelable { ctor public TransportDiscoveryData(int, @NonNull java.util.List<android.bluetooth.le.TransportBlock>); ctor public TransportDiscoveryData(@NonNull byte[]); method public int describeContents(); method @NonNull public java.util.List<android.bluetooth.le.TransportBlock> getTransportBlocks(); method public int getTransportDataType(); method @Nullable public byte[] toByteArray(); method public int totalBytes(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportDiscoveryData> CREATOR; } } package android.companion { core/java/android/bluetooth/le/AdvertiseData.java +53 −5 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.util.ArrayMap; import android.util.SparseArray; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; Loading @@ -47,6 +48,9 @@ public final class AdvertiseData implements Parcelable { @NonNull private final List<ParcelUuid> mServiceSolicitationUuids; @Nullable private final List<TransportDiscoveryData> mTransportDiscoveryData; private final SparseArray<byte[]> mManufacturerSpecificData; private final Map<ParcelUuid, byte[]> mServiceData; private final boolean mIncludeTxPowerLevel; Loading @@ -54,12 +58,14 @@ public final class AdvertiseData implements Parcelable { private AdvertiseData(List<ParcelUuid> serviceUuids, List<ParcelUuid> serviceSolicitationUuids, List<TransportDiscoveryData> transportDiscoveryData, SparseArray<byte[]> manufacturerData, Map<ParcelUuid, byte[]> serviceData, boolean includeTxPowerLevel, boolean includeDeviceName) { mServiceUuids = serviceUuids; mServiceSolicitationUuids = serviceSolicitationUuids; mTransportDiscoveryData = transportDiscoveryData; mManufacturerSpecificData = manufacturerData; mServiceData = serviceData; mIncludeTxPowerLevel = includeTxPowerLevel; Loading @@ -82,6 +88,17 @@ public final class AdvertiseData implements Parcelable { return mServiceSolicitationUuids; } /** * Returns a list of {@link TransportDiscoveryData} within the advertisement. */ @NonNull public List<TransportDiscoveryData> getTransportDiscoveryData() { if (mTransportDiscoveryData == null) { return Collections.emptyList(); } return mTransportDiscoveryData; } /** * Returns an array of manufacturer Id and the corresponding manufacturer specific data. The * manufacturer id is a non-negative number assigned by Bluetooth SIG. Loading Loading @@ -116,8 +133,8 @@ public final class AdvertiseData implements Parcelable { */ @Override public int hashCode() { return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mManufacturerSpecificData, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel); return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mTransportDiscoveryData, mManufacturerSpecificData, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel); } /** Loading @@ -134,6 +151,7 @@ public final class AdvertiseData implements Parcelable { AdvertiseData other = (AdvertiseData) obj; return Objects.equals(mServiceUuids, other.mServiceUuids) && Objects.equals(mServiceSolicitationUuids, other.mServiceSolicitationUuids) && Objects.equals(mTransportDiscoveryData, other.mTransportDiscoveryData) && BluetoothLeUtils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) && BluetoothLeUtils.equals(mServiceData, other.mServiceData) Loading @@ -144,7 +162,8 @@ public final class AdvertiseData implements Parcelable { @Override public String toString() { return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mServiceSolicitationUuids=" + mServiceSolicitationUuids + ", mManufacturerSpecificData=" + mServiceSolicitationUuids + ", mTransportDiscoveryData=" + mTransportDiscoveryData + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData) + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" Loading @@ -162,6 +181,8 @@ public final class AdvertiseData implements Parcelable { dest.writeTypedArray(mServiceSolicitationUuids.toArray( new ParcelUuid[mServiceSolicitationUuids.size()]), flags); dest.writeTypedList(mTransportDiscoveryData); // mManufacturerSpecificData could not be null. dest.writeInt(mManufacturerSpecificData.size()); for (int i = 0; i < mManufacturerSpecificData.size(); ++i) { Loading Loading @@ -197,6 +218,12 @@ public final class AdvertiseData implements Parcelable { builder.addServiceSolicitationUuid(uuid); } List<TransportDiscoveryData> transportDiscoveryData = in.createTypedArrayList(TransportDiscoveryData.CREATOR); for (TransportDiscoveryData tdd : transportDiscoveryData) { builder.addTransportDiscoveryData(tdd); } int manufacturerSize = in.readInt(); for (int i = 0; i < manufacturerSize; ++i) { int manufacturerId = in.readInt(); Loading @@ -223,6 +250,9 @@ public final class AdvertiseData implements Parcelable { private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>(); @NonNull private List<ParcelUuid> mServiceSolicitationUuids = new ArrayList<ParcelUuid>(); @Nullable private List<TransportDiscoveryData> mTransportDiscoveryData = new ArrayList<TransportDiscoveryData>(); private SparseArray<byte[]> mManufacturerSpecificData = new SparseArray<byte[]>(); private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>(); private boolean mIncludeTxPowerLevel; Loading Loading @@ -256,6 +286,7 @@ public final class AdvertiseData implements Parcelable { mServiceSolicitationUuids.add(serviceSolicitationUuid); return this; } /** * Add service data to advertise data. * Loading @@ -273,6 +304,23 @@ public final class AdvertiseData implements Parcelable { return this; } /** * Add Transport Discovery Data to advertise data. * * @param transportDiscoveryData Transport Discovery Data, consisting of one or more * Transport Blocks. Transport Discovery Data AD Type Code is already included. * @throws IllegalArgumentException If the {@code transportDiscoveryData} is empty */ @NonNull public Builder addTransportDiscoveryData( @NonNull TransportDiscoveryData transportDiscoveryData) { if (transportDiscoveryData == null) { throw new IllegalArgumentException("transportDiscoveryData is null"); } mTransportDiscoveryData.add(transportDiscoveryData); return this; } /** * Add manufacturer specific data. * <p> Loading Loading @@ -319,8 +367,8 @@ public final class AdvertiseData implements Parcelable { */ public AdvertiseData build() { return new AdvertiseData(mServiceUuids, mServiceSolicitationUuids, mManufacturerSpecificData, mServiceData, mIncludeTxPowerLevel, mIncludeDeviceName); mTransportDiscoveryData, mManufacturerSpecificData, mServiceData, mIncludeTxPowerLevel, mIncludeDeviceName); } } } core/java/android/bluetooth/le/BluetoothLeAdvertiser.java +3 −0 Original line number Diff line number Diff line Loading @@ -567,6 +567,9 @@ public final class BluetoothLeAdvertiser { + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT; } } for (TransportDiscoveryData transportDiscoveryData : data.getTransportDiscoveryData()) { size += OVERHEAD_BYTES_PER_FIELD + transportDiscoveryData.totalBytes(); } for (ParcelUuid uuid : data.getServiceData().keySet()) { int uuidLen = BluetoothUuid.uuidToBytes(uuid).length; size += OVERHEAD_BYTES_PER_FIELD + uuidLen Loading core/java/android/bluetooth/le/TransportBlock.java 0 → 100644 +155 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 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.bluetooth.le; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; /** * Wrapper for Transport Discovery Data Transport Blocks. * This class represents a Transport Block from a Transport Discovery Data. * * @see TransportDiscoveryData * @see AdvertiseData */ public final class TransportBlock implements Parcelable { private static final String TAG = "TransportBlock"; private final int mOrgId; private final int mTdsFlags; private final int mTransportDataLength; private final byte[] mTransportData; /** * Creates an instance of TransportBlock from raw data. * * @param orgId the Organization ID * @param tdsFlags the TDS flags * @param transportDataLength the total length of the Transport Data * @param transportData the Transport Data */ public TransportBlock(int orgId, int tdsFlags, int transportDataLength, @Nullable byte[] transportData) { mOrgId = orgId; mTdsFlags = tdsFlags; mTransportDataLength = transportDataLength; mTransportData = transportData; } private TransportBlock(Parcel in) { mOrgId = in.readInt(); mTdsFlags = in.readInt(); mTransportDataLength = in.readInt(); mTransportData = new byte[mTransportDataLength]; in.readByteArray(mTransportData); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mOrgId); dest.writeInt(mTdsFlags); dest.writeInt(mTransportDataLength); dest.writeByteArray(mTransportData); } /** * @hide */ @Override public int describeContents() { return 0; } public static final @NonNull Creator<TransportBlock> CREATOR = new Creator<TransportBlock>() { @Override public TransportBlock createFromParcel(Parcel in) { return new TransportBlock(in); } @Override public TransportBlock[] newArray(int size) { return new TransportBlock[size]; } }; /** * Gets the Organization ID of the Transport Block which corresponds to one of the * the Bluetooth SIG Assigned Numbers. */ public int getOrgId() { return mOrgId; } /** * Gets the TDS flags of the Transport Block which represents the role of the device and * information about its state and supported features. */ public int getTdsFlags() { return mTdsFlags; } /** * Gets the total number of octets in the Transport Data field in this Transport Block. */ public int getTransportDataLength() { return mTransportDataLength; } /** * Gets the Transport Data of the Transport Block which contains organization-specific data. */ @Nullable public byte[] getTransportData() { return mTransportData; } /** * Converts this TransportBlock to byte array * * @return byte array representation of this Transport Block or null if the conversion failed */ @Nullable public byte[] toByteArray() { try { ByteBuffer buffer = ByteBuffer.allocate(totalBytes()); buffer.put((byte) mOrgId); buffer.put((byte) mTdsFlags); buffer.put((byte) mTransportDataLength); if (mTransportData != null) { buffer.put(mTransportData); } return buffer.array(); } catch (BufferOverflowException e) { Log.e(TAG, "Error converting to byte array: " + e.toString()); return null; } } /** * @return total byte count of this TransportBlock */ public int totalBytes() { // 3 uint8 + byte[] length int size = 3 + mTransportDataLength; return size; } } core/java/android/bluetooth/le/TransportDiscoveryData.java 0 → 100644 +168 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 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.bluetooth.le; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import java.nio.BufferOverflowException; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Wrapper for Transport Discovery Data AD Type. * This class contains the Transport Discovery Data AD Type Code as well as * a list of potential Transport Blocks. * * @see AdvertiseData */ public final class TransportDiscoveryData implements Parcelable { private static final String TAG = "TransportDiscoveryData"; private final int mTransportDataType; private final List<TransportBlock> mTransportBlocks; /** * Creates a TransportDiscoveryData instance. * * @param transportDataType the Transport Discovery Data AD Type * @param transportBlocks the list of Transport Blocks */ public TransportDiscoveryData(int transportDataType, @NonNull List<TransportBlock> transportBlocks) { mTransportDataType = transportDataType; mTransportBlocks = transportBlocks; } /** * Creates a TransportDiscoveryData instance from byte arrays. * * Uses the transport discovery data bytes and parses them into an usable class. * * @param transportDiscoveryData the raw discovery data */ public TransportDiscoveryData(@NonNull byte[] transportDiscoveryData) { ByteBuffer byteBuffer = ByteBuffer.wrap(transportDiscoveryData); mTransportBlocks = new ArrayList(); if (byteBuffer.remaining() > 0) { mTransportDataType = byteBuffer.get(); } else { mTransportDataType = -1; } try { while (byteBuffer.remaining() > 0) { int orgId = byteBuffer.get(); int tdsFlags = byteBuffer.get(); int transportDataLength = byteBuffer.get(); byte[] transportData = new byte[transportDataLength]; byteBuffer.get(transportData, 0, transportDataLength); mTransportBlocks.add(new TransportBlock(orgId, tdsFlags, transportDataLength, transportData)); } } catch (BufferUnderflowException e) { Log.e(TAG, "Error while parsing data: " + e.toString()); } } private TransportDiscoveryData(Parcel in) { mTransportDataType = in.readInt(); mTransportBlocks = in.createTypedArrayList(TransportBlock.CREATOR); } /** * @hide */ @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mTransportDataType); dest.writeTypedList(mTransportBlocks); } public static final @NonNull Creator<TransportDiscoveryData> CREATOR = new Creator<TransportDiscoveryData>() { @Override public TransportDiscoveryData createFromParcel(Parcel in) { return new TransportDiscoveryData(in); } @Override public TransportDiscoveryData[] newArray(int size) { return new TransportDiscoveryData[size]; } }; /** * Gets the transport data type. */ public int getTransportDataType() { return mTransportDataType; } /** * @return the list of {@link TransportBlock} in this TransportDiscoveryData * or an empty list if there are no Transport Blocks */ @NonNull public List<TransportBlock> getTransportBlocks() { if (mTransportBlocks == null) { return Collections.emptyList(); } return mTransportBlocks; } /** * Converts this TransportDiscoveryData to byte array * * @return byte array representation of this Transport Discovery Data or null if the * conversion failed */ @Nullable public byte[] toByteArray() { try { ByteBuffer buffer = ByteBuffer.allocate(totalBytes()); buffer.put((byte) mTransportDataType); for (TransportBlock transportBlock : getTransportBlocks()) { buffer.put(transportBlock.toByteArray()); } return buffer.array(); } catch (BufferOverflowException e) { Log.e(TAG, "Error converting to byte array: " + e.toString()); return null; } } /** * @return total byte count of this TransportDataDiscovery */ public int totalBytes() { int size = 1; // Counting Transport Data Type here. for (TransportBlock transportBlock : getTransportBlocks()) { size += transportBlock.totalBytes(); } return size; } } Loading
core/api/current.txt +27 −0 Original line number Diff line number Diff line Loading @@ -9546,6 +9546,7 @@ package android.bluetooth.le { method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData(); method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids(); method public java.util.List<android.os.ParcelUuid> getServiceUuids(); method @NonNull public java.util.List<android.bluetooth.le.TransportDiscoveryData> getTransportDiscoveryData(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseData> CREATOR; } Loading @@ -9556,6 +9557,7 @@ package android.bluetooth.le { method public android.bluetooth.le.AdvertiseData.Builder addServiceData(android.os.ParcelUuid, byte[]); method @NonNull public android.bluetooth.le.AdvertiseData.Builder addServiceSolicitationUuid(@NonNull android.os.ParcelUuid); method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid); method @NonNull public android.bluetooth.le.AdvertiseData.Builder addTransportDiscoveryData(@NonNull android.bluetooth.le.TransportDiscoveryData); method public android.bluetooth.le.AdvertiseData build(); method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean); method public android.bluetooth.le.AdvertiseData.Builder setIncludeTxPowerLevel(boolean); Loading Loading @@ -9815,6 +9817,31 @@ package android.bluetooth.le { method public android.bluetooth.le.ScanSettings.Builder setScanMode(int); } public final class TransportBlock implements android.os.Parcelable { ctor public TransportBlock(int, int, int, @Nullable byte[]); method public int describeContents(); method public int getOrgId(); method public int getTdsFlags(); method @Nullable public byte[] getTransportData(); method public int getTransportDataLength(); method @Nullable public byte[] toByteArray(); method public int totalBytes(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportBlock> CREATOR; } public final class TransportDiscoveryData implements android.os.Parcelable { ctor public TransportDiscoveryData(int, @NonNull java.util.List<android.bluetooth.le.TransportBlock>); ctor public TransportDiscoveryData(@NonNull byte[]); method public int describeContents(); method @NonNull public java.util.List<android.bluetooth.le.TransportBlock> getTransportBlocks(); method public int getTransportDataType(); method @Nullable public byte[] toByteArray(); method public int totalBytes(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportDiscoveryData> CREATOR; } } package android.companion {
core/java/android/bluetooth/le/AdvertiseData.java +53 −5 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.util.ArrayMap; import android.util.SparseArray; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; Loading @@ -47,6 +48,9 @@ public final class AdvertiseData implements Parcelable { @NonNull private final List<ParcelUuid> mServiceSolicitationUuids; @Nullable private final List<TransportDiscoveryData> mTransportDiscoveryData; private final SparseArray<byte[]> mManufacturerSpecificData; private final Map<ParcelUuid, byte[]> mServiceData; private final boolean mIncludeTxPowerLevel; Loading @@ -54,12 +58,14 @@ public final class AdvertiseData implements Parcelable { private AdvertiseData(List<ParcelUuid> serviceUuids, List<ParcelUuid> serviceSolicitationUuids, List<TransportDiscoveryData> transportDiscoveryData, SparseArray<byte[]> manufacturerData, Map<ParcelUuid, byte[]> serviceData, boolean includeTxPowerLevel, boolean includeDeviceName) { mServiceUuids = serviceUuids; mServiceSolicitationUuids = serviceSolicitationUuids; mTransportDiscoveryData = transportDiscoveryData; mManufacturerSpecificData = manufacturerData; mServiceData = serviceData; mIncludeTxPowerLevel = includeTxPowerLevel; Loading @@ -82,6 +88,17 @@ public final class AdvertiseData implements Parcelable { return mServiceSolicitationUuids; } /** * Returns a list of {@link TransportDiscoveryData} within the advertisement. */ @NonNull public List<TransportDiscoveryData> getTransportDiscoveryData() { if (mTransportDiscoveryData == null) { return Collections.emptyList(); } return mTransportDiscoveryData; } /** * Returns an array of manufacturer Id and the corresponding manufacturer specific data. The * manufacturer id is a non-negative number assigned by Bluetooth SIG. Loading Loading @@ -116,8 +133,8 @@ public final class AdvertiseData implements Parcelable { */ @Override public int hashCode() { return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mManufacturerSpecificData, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel); return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mTransportDiscoveryData, mManufacturerSpecificData, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel); } /** Loading @@ -134,6 +151,7 @@ public final class AdvertiseData implements Parcelable { AdvertiseData other = (AdvertiseData) obj; return Objects.equals(mServiceUuids, other.mServiceUuids) && Objects.equals(mServiceSolicitationUuids, other.mServiceSolicitationUuids) && Objects.equals(mTransportDiscoveryData, other.mTransportDiscoveryData) && BluetoothLeUtils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) && BluetoothLeUtils.equals(mServiceData, other.mServiceData) Loading @@ -144,7 +162,8 @@ public final class AdvertiseData implements Parcelable { @Override public String toString() { return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mServiceSolicitationUuids=" + mServiceSolicitationUuids + ", mManufacturerSpecificData=" + mServiceSolicitationUuids + ", mTransportDiscoveryData=" + mTransportDiscoveryData + ", mManufacturerSpecificData=" + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData=" + BluetoothLeUtils.toString(mServiceData) + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" Loading @@ -162,6 +181,8 @@ public final class AdvertiseData implements Parcelable { dest.writeTypedArray(mServiceSolicitationUuids.toArray( new ParcelUuid[mServiceSolicitationUuids.size()]), flags); dest.writeTypedList(mTransportDiscoveryData); // mManufacturerSpecificData could not be null. dest.writeInt(mManufacturerSpecificData.size()); for (int i = 0; i < mManufacturerSpecificData.size(); ++i) { Loading Loading @@ -197,6 +218,12 @@ public final class AdvertiseData implements Parcelable { builder.addServiceSolicitationUuid(uuid); } List<TransportDiscoveryData> transportDiscoveryData = in.createTypedArrayList(TransportDiscoveryData.CREATOR); for (TransportDiscoveryData tdd : transportDiscoveryData) { builder.addTransportDiscoveryData(tdd); } int manufacturerSize = in.readInt(); for (int i = 0; i < manufacturerSize; ++i) { int manufacturerId = in.readInt(); Loading @@ -223,6 +250,9 @@ public final class AdvertiseData implements Parcelable { private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>(); @NonNull private List<ParcelUuid> mServiceSolicitationUuids = new ArrayList<ParcelUuid>(); @Nullable private List<TransportDiscoveryData> mTransportDiscoveryData = new ArrayList<TransportDiscoveryData>(); private SparseArray<byte[]> mManufacturerSpecificData = new SparseArray<byte[]>(); private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>(); private boolean mIncludeTxPowerLevel; Loading Loading @@ -256,6 +286,7 @@ public final class AdvertiseData implements Parcelable { mServiceSolicitationUuids.add(serviceSolicitationUuid); return this; } /** * Add service data to advertise data. * Loading @@ -273,6 +304,23 @@ public final class AdvertiseData implements Parcelable { return this; } /** * Add Transport Discovery Data to advertise data. * * @param transportDiscoveryData Transport Discovery Data, consisting of one or more * Transport Blocks. Transport Discovery Data AD Type Code is already included. * @throws IllegalArgumentException If the {@code transportDiscoveryData} is empty */ @NonNull public Builder addTransportDiscoveryData( @NonNull TransportDiscoveryData transportDiscoveryData) { if (transportDiscoveryData == null) { throw new IllegalArgumentException("transportDiscoveryData is null"); } mTransportDiscoveryData.add(transportDiscoveryData); return this; } /** * Add manufacturer specific data. * <p> Loading Loading @@ -319,8 +367,8 @@ public final class AdvertiseData implements Parcelable { */ public AdvertiseData build() { return new AdvertiseData(mServiceUuids, mServiceSolicitationUuids, mManufacturerSpecificData, mServiceData, mIncludeTxPowerLevel, mIncludeDeviceName); mTransportDiscoveryData, mManufacturerSpecificData, mServiceData, mIncludeTxPowerLevel, mIncludeDeviceName); } } }
core/java/android/bluetooth/le/BluetoothLeAdvertiser.java +3 −0 Original line number Diff line number Diff line Loading @@ -567,6 +567,9 @@ public final class BluetoothLeAdvertiser { + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT; } } for (TransportDiscoveryData transportDiscoveryData : data.getTransportDiscoveryData()) { size += OVERHEAD_BYTES_PER_FIELD + transportDiscoveryData.totalBytes(); } for (ParcelUuid uuid : data.getServiceData().keySet()) { int uuidLen = BluetoothUuid.uuidToBytes(uuid).length; size += OVERHEAD_BYTES_PER_FIELD + uuidLen Loading
core/java/android/bluetooth/le/TransportBlock.java 0 → 100644 +155 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 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.bluetooth.le; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; /** * Wrapper for Transport Discovery Data Transport Blocks. * This class represents a Transport Block from a Transport Discovery Data. * * @see TransportDiscoveryData * @see AdvertiseData */ public final class TransportBlock implements Parcelable { private static final String TAG = "TransportBlock"; private final int mOrgId; private final int mTdsFlags; private final int mTransportDataLength; private final byte[] mTransportData; /** * Creates an instance of TransportBlock from raw data. * * @param orgId the Organization ID * @param tdsFlags the TDS flags * @param transportDataLength the total length of the Transport Data * @param transportData the Transport Data */ public TransportBlock(int orgId, int tdsFlags, int transportDataLength, @Nullable byte[] transportData) { mOrgId = orgId; mTdsFlags = tdsFlags; mTransportDataLength = transportDataLength; mTransportData = transportData; } private TransportBlock(Parcel in) { mOrgId = in.readInt(); mTdsFlags = in.readInt(); mTransportDataLength = in.readInt(); mTransportData = new byte[mTransportDataLength]; in.readByteArray(mTransportData); } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mOrgId); dest.writeInt(mTdsFlags); dest.writeInt(mTransportDataLength); dest.writeByteArray(mTransportData); } /** * @hide */ @Override public int describeContents() { return 0; } public static final @NonNull Creator<TransportBlock> CREATOR = new Creator<TransportBlock>() { @Override public TransportBlock createFromParcel(Parcel in) { return new TransportBlock(in); } @Override public TransportBlock[] newArray(int size) { return new TransportBlock[size]; } }; /** * Gets the Organization ID of the Transport Block which corresponds to one of the * the Bluetooth SIG Assigned Numbers. */ public int getOrgId() { return mOrgId; } /** * Gets the TDS flags of the Transport Block which represents the role of the device and * information about its state and supported features. */ public int getTdsFlags() { return mTdsFlags; } /** * Gets the total number of octets in the Transport Data field in this Transport Block. */ public int getTransportDataLength() { return mTransportDataLength; } /** * Gets the Transport Data of the Transport Block which contains organization-specific data. */ @Nullable public byte[] getTransportData() { return mTransportData; } /** * Converts this TransportBlock to byte array * * @return byte array representation of this Transport Block or null if the conversion failed */ @Nullable public byte[] toByteArray() { try { ByteBuffer buffer = ByteBuffer.allocate(totalBytes()); buffer.put((byte) mOrgId); buffer.put((byte) mTdsFlags); buffer.put((byte) mTransportDataLength); if (mTransportData != null) { buffer.put(mTransportData); } return buffer.array(); } catch (BufferOverflowException e) { Log.e(TAG, "Error converting to byte array: " + e.toString()); return null; } } /** * @return total byte count of this TransportBlock */ public int totalBytes() { // 3 uint8 + byte[] length int size = 3 + mTransportDataLength; return size; } }
core/java/android/bluetooth/le/TransportDiscoveryData.java 0 → 100644 +168 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 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.bluetooth.le; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import java.nio.BufferOverflowException; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Wrapper for Transport Discovery Data AD Type. * This class contains the Transport Discovery Data AD Type Code as well as * a list of potential Transport Blocks. * * @see AdvertiseData */ public final class TransportDiscoveryData implements Parcelable { private static final String TAG = "TransportDiscoveryData"; private final int mTransportDataType; private final List<TransportBlock> mTransportBlocks; /** * Creates a TransportDiscoveryData instance. * * @param transportDataType the Transport Discovery Data AD Type * @param transportBlocks the list of Transport Blocks */ public TransportDiscoveryData(int transportDataType, @NonNull List<TransportBlock> transportBlocks) { mTransportDataType = transportDataType; mTransportBlocks = transportBlocks; } /** * Creates a TransportDiscoveryData instance from byte arrays. * * Uses the transport discovery data bytes and parses them into an usable class. * * @param transportDiscoveryData the raw discovery data */ public TransportDiscoveryData(@NonNull byte[] transportDiscoveryData) { ByteBuffer byteBuffer = ByteBuffer.wrap(transportDiscoveryData); mTransportBlocks = new ArrayList(); if (byteBuffer.remaining() > 0) { mTransportDataType = byteBuffer.get(); } else { mTransportDataType = -1; } try { while (byteBuffer.remaining() > 0) { int orgId = byteBuffer.get(); int tdsFlags = byteBuffer.get(); int transportDataLength = byteBuffer.get(); byte[] transportData = new byte[transportDataLength]; byteBuffer.get(transportData, 0, transportDataLength); mTransportBlocks.add(new TransportBlock(orgId, tdsFlags, transportDataLength, transportData)); } } catch (BufferUnderflowException e) { Log.e(TAG, "Error while parsing data: " + e.toString()); } } private TransportDiscoveryData(Parcel in) { mTransportDataType = in.readInt(); mTransportBlocks = in.createTypedArrayList(TransportBlock.CREATOR); } /** * @hide */ @Override public int describeContents() { return 0; } @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mTransportDataType); dest.writeTypedList(mTransportBlocks); } public static final @NonNull Creator<TransportDiscoveryData> CREATOR = new Creator<TransportDiscoveryData>() { @Override public TransportDiscoveryData createFromParcel(Parcel in) { return new TransportDiscoveryData(in); } @Override public TransportDiscoveryData[] newArray(int size) { return new TransportDiscoveryData[size]; } }; /** * Gets the transport data type. */ public int getTransportDataType() { return mTransportDataType; } /** * @return the list of {@link TransportBlock} in this TransportDiscoveryData * or an empty list if there are no Transport Blocks */ @NonNull public List<TransportBlock> getTransportBlocks() { if (mTransportBlocks == null) { return Collections.emptyList(); } return mTransportBlocks; } /** * Converts this TransportDiscoveryData to byte array * * @return byte array representation of this Transport Discovery Data or null if the * conversion failed */ @Nullable public byte[] toByteArray() { try { ByteBuffer buffer = ByteBuffer.allocate(totalBytes()); buffer.put((byte) mTransportDataType); for (TransportBlock transportBlock : getTransportBlocks()) { buffer.put(transportBlock.toByteArray()); } return buffer.array(); } catch (BufferOverflowException e) { Log.e(TAG, "Error converting to byte array: " + e.toString()); return null; } } /** * @return total byte count of this TransportDataDiscovery */ public int totalBytes() { int size = 1; // Counting Transport Data Type here. for (TransportBlock transportBlock : getTransportBlocks()) { size += transportBlock.totalBytes(); } return size; } }