• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.bluetooth.le;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.util.Log;
24 
25 import java.nio.BufferOverflowException;
26 import java.nio.BufferUnderflowException;
27 import java.nio.ByteBuffer;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collections;
31 import java.util.List;
32 
33 /**
34  * Wrapper for Transport Discovery Data AD Type.
35  * This class contains the Transport Discovery Data AD Type Code as well as
36  * a list of potential Transport Blocks.
37  *
38  * @see AdvertiseData
39  */
40 public final class TransportDiscoveryData implements Parcelable {
41     private static final String TAG = "TransportDiscoveryData";
42     private final int mTransportDataType;
43     private final List<TransportBlock> mTransportBlocks;
44 
45     /**
46      * Creates a TransportDiscoveryData instance.
47      *
48      * @param transportDataType the Transport Discovery Data AD Type
49      * @param transportBlocks the list of Transport Blocks
50      */
TransportDiscoveryData(int transportDataType, @NonNull List<TransportBlock> transportBlocks)51     public TransportDiscoveryData(int transportDataType,
52             @NonNull List<TransportBlock> transportBlocks) {
53         mTransportDataType = transportDataType;
54         mTransportBlocks = transportBlocks;
55     }
56 
57     /**
58      * Creates a TransportDiscoveryData instance from byte arrays.
59      *
60      * Uses the transport discovery data bytes and parses them into an usable class.
61      *
62      * @param transportDiscoveryData the raw discovery data
63      */
TransportDiscoveryData(@onNull byte[] transportDiscoveryData)64     public TransportDiscoveryData(@NonNull byte[] transportDiscoveryData) {
65         ByteBuffer byteBuffer = ByteBuffer.wrap(transportDiscoveryData);
66         mTransportBlocks = new ArrayList();
67         if (byteBuffer.remaining() > 0) {
68             mTransportDataType = byteBuffer.get();
69         } else {
70             mTransportDataType = -1;
71         }
72         try {
73             while (byteBuffer.remaining() > 0) {
74                 int orgId = byteBuffer.get();
75                 int tdsFlags = byteBuffer.get();
76                 int transportDataLength = byteBuffer.get();
77                 byte[] transportData = new byte[transportDataLength];
78                 byteBuffer.get(transportData, 0, transportDataLength);
79                 mTransportBlocks.add(new TransportBlock(orgId, tdsFlags,
80                         transportDataLength, transportData));
81             }
82         } catch (BufferUnderflowException e) {
83             Log.e(TAG, "Error while parsing data: " + e.toString());
84         }
85     }
86 
TransportDiscoveryData(Parcel in)87     private TransportDiscoveryData(Parcel in) {
88         mTransportDataType = in.readInt();
89         mTransportBlocks = in.createTypedArrayList(TransportBlock.CREATOR);
90     }
91 
92     /**
93      * @hide
94      */
95     @Override
describeContents()96     public int describeContents() {
97         return 0;
98     }
99 
100     /**
101      * @hide
102      */
103     @Override
equals(@ullable Object obj)104     public boolean equals(@Nullable Object obj) {
105         if (this == obj) {
106             return true;
107         }
108         if (obj == null || getClass() != obj.getClass()) {
109             return false;
110         }
111         TransportDiscoveryData other = (TransportDiscoveryData) obj;
112         return Arrays.equals(toByteArray(), other.toByteArray());
113     }
114 
115     @Override
writeToParcel(@onNull Parcel dest, int flags)116     public void writeToParcel(@NonNull Parcel dest, int flags) {
117         dest.writeInt(mTransportDataType);
118         dest.writeTypedList(mTransportBlocks);
119     }
120 
121     public static final @NonNull Creator<TransportDiscoveryData> CREATOR =
122             new Creator<TransportDiscoveryData>() {
123                 @Override
124                 public TransportDiscoveryData createFromParcel(Parcel in) {
125                     return new TransportDiscoveryData(in);
126                 }
127 
128                 @Override
129                 public TransportDiscoveryData[] newArray(int size) {
130                     return new TransportDiscoveryData[size];
131                 }
132     };
133 
134     /**
135      * Gets the transport data type.
136      */
getTransportDataType()137     public int getTransportDataType() {
138         return mTransportDataType;
139     }
140 
141     /**
142      * @return the list of {@link TransportBlock} in this TransportDiscoveryData
143      *         or an empty list if there are no Transport Blocks
144      */
145     @NonNull
getTransportBlocks()146     public List<TransportBlock> getTransportBlocks() {
147         if (mTransportBlocks == null) {
148             return Collections.emptyList();
149         }
150         return mTransportBlocks;
151     }
152 
153     /**
154      * Converts this TransportDiscoveryData to byte array
155      *
156      * @return byte array representation of this Transport Discovery Data or null if the
157      *         conversion failed
158      */
159     @Nullable
toByteArray()160     public byte[] toByteArray() {
161         try {
162             ByteBuffer buffer = ByteBuffer.allocate(totalBytes());
163             buffer.put((byte) mTransportDataType);
164             for (TransportBlock transportBlock : getTransportBlocks()) {
165                 buffer.put(transportBlock.toByteArray());
166             }
167             return buffer.array();
168         } catch (BufferOverflowException e) {
169             Log.e(TAG, "Error converting to byte array: " + e.toString());
170             return null;
171         }
172     }
173 
174     /**
175      * @return total byte count of this TransportDataDiscovery
176      */
totalBytes()177     public int totalBytes() {
178         int size = 1; // Counting Transport Data Type here.
179         for (TransportBlock transportBlock : getTransportBlocks()) {
180             size += transportBlock.totalBytes();
181         }
182         return size;
183     }
184 }
185