• 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. This class contains the Transport Discovery Data AD
35  * Type Code as well as a list of potential Transport Blocks.
36  *
37  * @see AdvertiseData
38  */
39 public final class TransportDiscoveryData implements Parcelable {
40     private static final String TAG = TransportDiscoveryData.class.getSimpleName();
41 
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(
52             int transportDataType, @NonNull List<TransportBlock> transportBlocks) {
53         mTransportDataType = transportDataType;
54         mTransportBlocks = transportBlocks;
55     }
56 
57     /**
58      * Creates a TransportDiscoveryData instance from byte arrays.
59      *
60      * <p>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(
80                         new TransportBlock(orgId, tdsFlags, 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     /** @hide */
93     @Override
describeContents()94     public int describeContents() {
95         return 0;
96     }
97 
98     /** @hide */
99     @Override
equals(@ullable Object obj)100     public boolean equals(@Nullable Object obj) {
101         if (this == obj) {
102             return true;
103         }
104         if (obj == null || getClass() != obj.getClass()) {
105             return false;
106         }
107         TransportDiscoveryData other = (TransportDiscoveryData) obj;
108         return Arrays.equals(toByteArray(), other.toByteArray());
109     }
110 
111     /** @hide */
112     @Override
hashCode()113     public int hashCode() {
114         return Arrays.hashCode(toByteArray());
115     }
116 
117     @Override
writeToParcel(@onNull Parcel dest, int flags)118     public void writeToParcel(@NonNull Parcel dest, int flags) {
119         dest.writeInt(mTransportDataType);
120         dest.writeTypedList(mTransportBlocks);
121     }
122 
123     public static final @NonNull Creator<TransportDiscoveryData> CREATOR =
124             new Creator<TransportDiscoveryData>() {
125                 @Override
126                 public TransportDiscoveryData createFromParcel(Parcel in) {
127                     return new TransportDiscoveryData(in);
128                 }
129 
130                 @Override
131                 public TransportDiscoveryData[] newArray(int size) {
132                     return new TransportDiscoveryData[size];
133                 }
134             };
135 
136     /** Gets the transport data type. */
getTransportDataType()137     public int getTransportDataType() {
138         return mTransportDataType;
139     }
140 
141     /**
142      * @return the list of {@link TransportBlock} in this TransportDiscoveryData or an empty list if
143      *     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 conversion
157      *     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     @Override
toString()175     public String toString() {
176         return BluetoothLeUtils.toString(toByteArray());
177     }
178 
179     /**
180      * @return total byte count of this TransportDataDiscovery
181      */
totalBytes()182     public int totalBytes() {
183         int size = 1; // Counting Transport Data Type here.
184         for (TransportBlock transportBlock : getTransportBlocks()) {
185             size += transportBlock.totalBytes();
186         }
187         return size;
188     }
189 }
190