ScanFilterQueue.java revision a61c69cd9e1fb148f56f16b1b768bed427b3b51d
1/*
2 * Copyright (C) 2013 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
17package com.android.bluetooth.gatt;
18
19import android.bluetooth.le.ScanFilter;
20
21import java.util.Arrays;
22import java.util.HashSet;
23import java.util.Iterator;
24import java.util.Objects;
25import java.util.Set;
26import java.util.UUID;
27
28/**
29 * Helper class used to manage advertisement package filters.
30 *
31 * @hide
32 */
33/* package */class ScanFilterQueue {
34    public static final int TYPE_DEVICE_ADDRESS = 0;
35    public static final int TYPE_SERVICE_DATA = 1;
36    public static final int TYPE_SERVICE_UUID = 2;
37    public static final int TYPE_SOLICIT_UUID = 3;
38    public static final int TYPE_LOCAL_NAME = 4;
39    public static final int TYPE_MANUFACTURER_DATA = 5;
40
41    // Values defined in bluedroid.
42    private static final byte DEVICE_TYPE_ALL = 0;
43
44    class Entry {
45        public String address;
46        public byte addr_type;
47        public byte type;
48        public UUID uuid;
49        public UUID uuid_mask;
50        public String name;
51        public int company;
52        public int company_mask;
53        public byte[] data;
54        public byte[] data_mask;
55
56        @Override
57        public int hashCode() {
58            return Objects.hash(address, addr_type, type, uuid, uuid_mask, name, company,
59                    company_mask, data, data_mask);
60        }
61
62        @Override
63        public boolean equals(Object obj) {
64            if (this == obj) {
65                return true;
66            }
67            if (obj == null || getClass() != obj.getClass()) {
68                return false;
69            }
70            Entry other = (Entry) obj;
71            return Objects.equals(address, other.address) &&
72                    addr_type == other.addr_type && type == other.type &&
73                    Objects.equals(uuid, other.uuid) &&
74                    Objects.equals(uuid_mask, other.uuid_mask) &&
75                    Objects.equals(name, other.name) &&
76                            company == other.company && company_mask == other.company_mask &&
77                    Objects.deepEquals(data, other.data) &&
78                    Objects.deepEquals(data_mask, other.data_mask);
79        }
80    }
81
82    private Set<Entry> mEntries = new HashSet<Entry>();
83
84    void addDeviceAddress(String address, byte type) {
85        Entry entry = new Entry();
86        entry.type = TYPE_DEVICE_ADDRESS;
87        entry.address = address;
88        entry.addr_type = type;
89        mEntries.add(entry);
90    }
91
92    void addServiceChanged() {
93        Entry entry = new Entry();
94        entry.type = TYPE_SERVICE_DATA;
95        mEntries.add(entry);
96    }
97
98    void addUuid(UUID uuid) {
99        Entry entry = new Entry();
100        entry.type = TYPE_SERVICE_UUID;
101        entry.uuid = uuid;
102        entry.uuid_mask = new UUID(0, 0);
103        mEntries.add(entry);
104    }
105
106    void addUuid(UUID uuid, UUID uuid_mask) {
107        Entry entry = new Entry();
108        entry.type = TYPE_SERVICE_UUID;
109        entry.uuid = uuid;
110        entry.uuid_mask = uuid_mask;
111        mEntries.add(entry);
112    }
113
114    void addSolicitUuid(UUID uuid) {
115        Entry entry = new Entry();
116        entry.type = TYPE_SOLICIT_UUID;
117        entry.uuid = uuid;
118        mEntries.add(entry);
119    }
120
121    void addName(String name) {
122        Entry entry = new Entry();
123        entry.type = TYPE_LOCAL_NAME;
124        entry.name = name;
125        mEntries.add(entry);
126    }
127
128    void addManufacturerData(int company, byte[] data) {
129        Entry entry = new Entry();
130        entry.type = TYPE_MANUFACTURER_DATA;
131        entry.company = company;
132        entry.company_mask = 0xFFFF;
133        entry.data = data;
134        entry.data_mask = new byte[data.length];
135        Arrays.fill(entry.data_mask, (byte) 0xFF);
136        mEntries.add(entry);
137    }
138
139    void addManufacturerData(int company, int company_mask, byte[] data, byte[] data_mask) {
140        Entry entry = new Entry();
141        entry.type = TYPE_MANUFACTURER_DATA;
142        entry.company = company;
143        entry.company_mask = company_mask;
144        entry.data = data;
145        entry.data_mask = data_mask;
146        mEntries.add(entry);
147    }
148
149    Entry pop() {
150        if (isEmpty()) {
151            return null;
152        }
153        Iterator<Entry> iterator = mEntries.iterator();
154        Entry entry = iterator.next();
155        iterator.remove();
156        return entry;
157    }
158
159    boolean isEmpty() {
160        return mEntries.isEmpty();
161    }
162
163    void clearUuids() {
164        for (Iterator<Entry> it = mEntries.iterator(); it.hasNext();) {
165            Entry entry = it.next();
166            if (entry.type == TYPE_SERVICE_UUID)
167                it.remove();
168        }
169    }
170
171    void clear() {
172        mEntries.clear();
173    }
174
175    /**
176     * Compute feature selection based on the filters presented.
177     */
178    int getFeatureSelection() {
179        int selc = 0;
180        for (Entry entry : mEntries) {
181            System.out.println("entry selc value " + (1 << entry.type));
182            selc |= (1 << entry.type);
183        }
184        return selc;
185    }
186
187    /**
188     * Add ScanFilter to scan filter queue.
189     */
190    void addScanFilter(ScanFilter filter) {
191        if (filter == null)
192            return;
193        if (filter.getLocalName() != null) {
194            addName(filter.getLocalName());
195        }
196        if (filter.getDeviceAddress() != null) {
197            addDeviceAddress(filter.getDeviceAddress(), DEVICE_TYPE_ALL);
198        }
199        if (filter.getServiceUuid() != null) {
200            if (filter.getServiceUuidMask() == null) {
201                addUuid(filter.getServiceUuid().getUuid());
202            } else {
203                addUuid(filter.getServiceUuid().getUuid(),
204                        filter.getServiceUuidMask().getUuid());
205            }
206        }
207        if (filter.getManufacturerData() != null) {
208            if (filter.getManufacturerDataMask() == null) {
209                addManufacturerData(filter.getManufacturerId(), filter.getManufacturerData());
210            } else {
211                addManufacturerData(filter.getManufacturerId(), 0xFFFF,
212                        filter.getManufacturerData(), filter.getManufacturerDataMask());
213            }
214        }
215    }
216}
217