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