zhuguifei
2025-12-30 61eee1173c00a7ba9d9c748d28fe3acdb33b9441
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
package com.blakequ.bluetooth_manager_lib.device.adrecord;
 
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
 
import java.util.Arrays;
 
/**
 * Created by Dave Smith
 * Double Encore, Inc.
 * <p>
 * Expanded by Alexandros Schillings
 */
public final class AdRecord implements Parcelable {
    //    02 # Number of bytes that follow in first AD structure
    //    01 # Flags AD type
    //    1A # Flags value 0x1A = 000011010
    //       bit 0 (OFF) LE Limited Discoverable Mode
    //       bit 1 (ON) LE General Discoverable Mode
    //       bit 2 (OFF) BR/EDR Not Supported
    //       bit 3 (ON) Simultaneous LE and BR/EDR to Same Device Capable (controller)
    //       bit 4 (ON) Simultaneous LE and BR/EDR to Same Device Capable (Host)
    //    1A # Number of bytes that follow in second (and last) AD structure
    //    FF # Manufacturer specific data AD type
    //    4C 00 # Company identifier code (0x004C == Apple)
    //    02 # Byte 0 of iBeacon advertisement indicator
    //    15 # Byte 1 of iBeacon advertisement indicator
    //    e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 # iBeacon proximity uuid
    //    00 00 # major
    //    00 00 # minor
    //    c5 # The 2's complement of the calibrated Tx Power
 
 
    /**
     * General FLAGS
     * <p>
     * Description: Flags
     * <p>
     * Information:
     * Bit 0: LE Limited Discoverable Mode
     * Bit 1: LE General Discoverable Mode
     * Bit 2: BR/EDR Not Supported (i.e. bit 37 of LMP Extended Feature bits Page 0)
     * Bit 3: Simultaneous LE and BR/EDR to Same Device Capable (Controller) (i.e. bit 49 of LMP Extended Feature bits Page 0)
     * Bit 4: Simultaneous LE and BR/EDR to Same Device Capable (Host) (i.e. bit 66 of LMP Extended Feature bits Page 1)
     * Bits 5-7 Reserved
     */
    public static final int TYPE_FLAGS = 0x01;
    // SERVICE
    public static final int TYPE_UUID16_INC = 0x02;
    public static final int TYPE_UUID16 = 0x03;
    public static final int TYPE_UUID32_INC = 0x04;
    public static final int TYPE_UUID32 = 0x05;
    public static final int TYPE_UUID128_INC = 0x06;
    public static final int TYPE_UUID128 = 0x07;
    // Local name
    public static final int TYPE_LOCAL_NAME_SHORT = 0x08;
    public static final int TYPE_LOCAL_NAME_COMPLETE = 0x09;
    // TX Power Level
    public static final int TYPE_TX_POWER_LEVEL = 0x0A;
    // SIMPLE PAIRING OPTIONAL OOB TAGS
    public static final int TYPE_DEVICE_CLASS = 0x0D;
    public static final int TYPE_SIMPLE_PAIRING_HASH_C = 0x0E;
    public static final int TYPE_SIMPLE_PAIRING_RANDOMIZER_R = 0x0F;
    // SECURITY MANAGER TK VALUE
    public static final int TYPE_TK_VALUE = 0x10;
    /* SECURITY MANAGER OOB FLAGS
     *
     * Description: Flag (1 octet)
     *
     * Information:
     * Bit 0: OOB Flags Field: (0 = OOB data not present, 1 = OOB data present)
     * Bit 1: LE supported (Host) (i.e. bit 65 of LMP Extended Feature bits Page 1
     * Bit 2: Simultaneous LE and BR/EDR to Same Device Capable (Host) (i.e. bit 66 of LMP Extended Feature bits Page 1)
     * Bit 3: Address type (0 = Public Address, 1 = Random Address)
     * Bits 4-7 Reserved
     */
    public static final int TYPE_SECURITY_MANAGER_OOB_FLAGS = 0x11;
    /* SLAVE CONNECTION INTERVAL RANGE
     *
     * Description: Slave Connection Interval Range
     *
     * Information:
     * The first 2 octets defines the minimum value for the connection interval in the following manner:
     *    connInterval min = Conn_Interval_Min * 1.25 ms
     *    Conn_Interval_Min range: 0x0006 to 0x0C80
     *    Value of 0xFFFF indicates no specific minimum.
     *    Values outside the range are reserved. (excluding 0xFFFF)
     *
     * The second 2 octets defines the maximum value for the connection interval in the following manner:
     *  connInterval max = Conn_Interval_Max * 1.25 ms
     *  Conn_Interval_Max range: 0x0006 to 0x0C80
     *  Conn_Interval_Max shall be equal to or greater
     *  than the Conn_Interval_Min.
     *  Value of 0xFFFF indicates no specific maximum.
     *  Values outside the range are reserved (excluding 0xFFFF)
     */
    public static final int TYPE_CONNECTION_INTERVAL_RANGE = 0x12;
    // SERVICE SOLICITATION
    public static final int TYPE_SERVICE_UUIDS_LIST_16BIT = 0x14;
    public static final int TYPE_SERVICE_UUIDS_LIST_128BIT = 0x15;
    /* SERVICE DATA
     *
     * Description: Service Data (2 or more octets)
     * Information: The first 2 octets contain the 16 bit Service UUID followed by additional service data
     */
    public static final int TYPE_SERVICE_DATA = 0x16;
    /* MANUFACTURER SPECIFIC DATA
     *
     * Description: Manufacturer Specific Data (2 or more octets)
     * Information: The first 2 octets contain the Company Identifier Code followed by additional manufacturer specific data
     */
    public static final int TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;
    public static final Creator<AdRecord> CREATOR = new Creator<AdRecord>() {
        public AdRecord createFromParcel(final Parcel in) {
            return new AdRecord(in);
        }
 
        public AdRecord[] newArray(final int size) {
            return new AdRecord[size];
        }
    };
    private static final String PARCEL_RECORD_DATA = "record_data";
    private static final String PARCEL_RECORD_TYPE = "record_type";
    private static final String PARCEL_RECORD_LENGTH = "record_length";
    /* Model Object Definition */
    private final int mLength;
    private final int mType;
    private final byte[] mData;
 
    public AdRecord(final int length, final int type, final byte[] data) {
        mLength = length;
        mType = type;
        mData = data;
    }
 
    public AdRecord(final Parcel in) {
        final Bundle b = in.readBundle(getClass().getClassLoader());
        mLength = b.getInt(PARCEL_RECORD_LENGTH);
        mType = b.getInt(PARCEL_RECORD_TYPE);
        mData = b.getByteArray(PARCEL_RECORD_DATA);
    }
 
    @Override
    public int describeContents() {
        return 0;
    }
 
    public byte[] getData() {
        return mData;
    }
 
    public String getHumanReadableType() {
        return getHumanReadableAdType(mType);
    }
 
    public int getLength() {
        return mLength;
    }
 
    public int getType() {
        return mType;
    }
 
    @Override
    public String toString() {
        return "AdRecord [mLength=" + mLength + ", mType=" + mType + ", mData=" + Arrays.toString(mData) + ", getHumanReadableType()=" + getHumanReadableType() + "]";
    }
 
    @Override
    public void writeToParcel(final Parcel parcel, final int arg1) {
        final Bundle b = new Bundle(getClass().getClassLoader());
 
        b.putInt(PARCEL_RECORD_LENGTH, mLength);
        b.putInt(PARCEL_RECORD_TYPE, mType);
        b.putByteArray(PARCEL_RECORD_DATA, mData);
 
        parcel.writeBundle(b);
    }
 
    private static String getHumanReadableAdType(final int type) {
        switch (type) {
            case TYPE_CONNECTION_INTERVAL_RANGE:
                return "Slave Connection Interval Range";
            case TYPE_DEVICE_CLASS:
                return "Class of device";
            case TYPE_FLAGS:
                return "Flags";
            case TYPE_MANUFACTURER_SPECIFIC_DATA:
                return "Manufacturer Specific Data";
            case TYPE_LOCAL_NAME_COMPLETE:
                return "Name (Complete)";
            case TYPE_LOCAL_NAME_SHORT:
                return "Name (Short)";
            case TYPE_SECURITY_MANAGER_OOB_FLAGS:
                return "Security Manager OOB Flags";
            case TYPE_SERVICE_UUIDS_LIST_128BIT:
                return "Service UUIDs (128bit)";
            case TYPE_SERVICE_UUIDS_LIST_16BIT:
                return "Service UUIDs (16bit)";
            case TYPE_SERVICE_DATA:
                return "Service Data";
            case TYPE_SIMPLE_PAIRING_HASH_C:
                return "Simple Pairing Hash C";
            case TYPE_SIMPLE_PAIRING_RANDOMIZER_R:
                return "Simple Pairing Randomizer R";
            case TYPE_TK_VALUE:
                return "TK Value";
            case TYPE_TX_POWER_LEVEL:
                return "Transmission Power Level";
            case TYPE_UUID128:
                return "Complete list of 128-bit UUIDs available";
            case TYPE_UUID128_INC:
                return "More 128-bit UUIDs available";
            case TYPE_UUID16:
                return "Complete list of 16-bit UUIDs available";
            case TYPE_UUID16_INC:
                return "More 16-bit UUIDs available";
            case TYPE_UUID32:
                return "Complete list of 32-bit UUIDs available";
            case TYPE_UUID32_INC:
                return "More 32-bit UUIDs available";
            default:
                return "Unknown AdRecord Structure: " + type;
        }
    }
}