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 package com.android.bluetooth.gatt; 17 18 import android.util.Log; 19 20 import java.util.List; 21 import java.util.Map; 22 import java.util.UUID; 23 import java.util.concurrent.ConcurrentHashMap; 24 import java.util.concurrent.CopyOnWriteArrayList; 25 26 class HandleMap { 27 private static final String TAG = GattServiceConfig.TAG_PREFIX + "HandleMap"; 28 29 public static final int TYPE_UNDEFINED = 0; 30 public static final int TYPE_SERVICE = 1; 31 public static final int TYPE_CHARACTERISTIC = 2; 32 public static final int TYPE_DESCRIPTOR = 3; 33 34 static class Entry { 35 public int serverIf = 0; 36 public int type = TYPE_UNDEFINED; 37 public int handle = 0; 38 public UUID uuid = null; 39 public int instance = 0; 40 public int serviceType = 0; 41 public int serviceHandle = 0; 42 public int charHandle = 0; 43 public boolean started = false; 44 public boolean advertisePreferred = false; 45 Entry(int serverIf, int handle, UUID uuid, int serviceType, int instance)46 Entry(int serverIf, int handle, UUID uuid, int serviceType, int instance) { 47 this.serverIf = serverIf; 48 this.type = TYPE_SERVICE; 49 this.handle = handle; 50 this.uuid = uuid; 51 this.instance = instance; 52 this.serviceType = serviceType; 53 } 54 Entry( int serverIf, int handle, UUID uuid, int serviceType, int instance, boolean advertisePreferred)55 Entry( 56 int serverIf, 57 int handle, 58 UUID uuid, 59 int serviceType, 60 int instance, 61 boolean advertisePreferred) { 62 this.serverIf = serverIf; 63 this.type = TYPE_SERVICE; 64 this.handle = handle; 65 this.uuid = uuid; 66 this.instance = instance; 67 this.serviceType = serviceType; 68 this.advertisePreferred = advertisePreferred; 69 } 70 Entry(int serverIf, int type, int handle, UUID uuid, int serviceHandle)71 Entry(int serverIf, int type, int handle, UUID uuid, int serviceHandle) { 72 this.serverIf = serverIf; 73 this.type = type; 74 this.handle = handle; 75 this.uuid = uuid; 76 this.serviceHandle = serviceHandle; 77 } 78 Entry(int serverIf, int type, int handle, UUID uuid, int serviceHandle, int charHandle)79 Entry(int serverIf, int type, int handle, UUID uuid, int serviceHandle, int charHandle) { 80 this.serverIf = serverIf; 81 this.type = type; 82 this.handle = handle; 83 this.uuid = uuid; 84 this.serviceHandle = serviceHandle; 85 this.charHandle = charHandle; 86 } 87 } 88 89 List<Entry> mEntries = null; 90 Map<Integer, Integer> mRequestMap = null; 91 int mLastCharacteristic = 0; 92 HandleMap()93 HandleMap() { 94 mEntries = new CopyOnWriteArrayList<Entry>(); 95 mRequestMap = new ConcurrentHashMap<Integer, Integer>(); 96 } 97 clear()98 void clear() { 99 mEntries.clear(); 100 mRequestMap.clear(); 101 } 102 addService( int serverIf, int handle, UUID uuid, int serviceType, int instance, boolean advertisePreferred)103 void addService( 104 int serverIf, 105 int handle, 106 UUID uuid, 107 int serviceType, 108 int instance, 109 boolean advertisePreferred) { 110 mEntries.add(new Entry(serverIf, handle, uuid, serviceType, instance, advertisePreferred)); 111 } 112 addCharacteristic(int serverIf, int handle, UUID uuid, int serviceHandle)113 void addCharacteristic(int serverIf, int handle, UUID uuid, int serviceHandle) { 114 mLastCharacteristic = handle; 115 mEntries.add(new Entry(serverIf, TYPE_CHARACTERISTIC, handle, uuid, serviceHandle)); 116 } 117 addDescriptor(int serverIf, int handle, UUID uuid, int serviceHandle)118 void addDescriptor(int serverIf, int handle, UUID uuid, int serviceHandle) { 119 mEntries.add( 120 new Entry( 121 serverIf, 122 TYPE_DESCRIPTOR, 123 handle, 124 uuid, 125 serviceHandle, 126 mLastCharacteristic)); 127 } 128 setStarted(int serverIf, int handle, boolean started)129 void setStarted(int serverIf, int handle, boolean started) { 130 for (Entry entry : mEntries) { 131 if (entry.type != TYPE_SERVICE 132 || entry.serverIf != serverIf 133 || entry.handle != handle) { 134 continue; 135 } 136 137 entry.started = started; 138 return; 139 } 140 } 141 getByHandle(int handle)142 Entry getByHandle(int handle) { 143 for (Entry entry : mEntries) { 144 if (entry.handle == handle) { 145 return entry; 146 } 147 } 148 Log.e(TAG, "getByHandle() - Handle " + handle + " not found!"); 149 return null; 150 } 151 checkServiceExists(UUID uuid, int handle)152 boolean checkServiceExists(UUID uuid, int handle) { 153 for (Entry entry : mEntries) { 154 if (entry.type == TYPE_SERVICE && entry.handle == handle && entry.uuid.equals(uuid)) { 155 return true; 156 } 157 } 158 return false; 159 } 160 deleteService(int serverIf, int serviceHandle)161 void deleteService(int serverIf, int serviceHandle) { 162 mEntries.removeIf( 163 entry -> 164 ((entry.serverIf == serverIf) 165 && (entry.handle == serviceHandle 166 || entry.serviceHandle == serviceHandle))); 167 } 168 getEntries()169 List<Entry> getEntries() { 170 return mEntries; 171 } 172 addRequest(int requestId, int handle)173 void addRequest(int requestId, int handle) { 174 mRequestMap.put(requestId, handle); 175 } 176 deleteRequest(int requestId)177 void deleteRequest(int requestId) { 178 mRequestMap.remove(requestId); 179 } 180 getByRequestId(int requestId)181 Entry getByRequestId(int requestId) { 182 Integer handle = mRequestMap.get(requestId); 183 if (handle == null) { 184 Log.e(TAG, "getByRequestId() - Request ID " + requestId + " not found!"); 185 return null; 186 } 187 return getByHandle(handle); 188 } 189 190 /** Logs debug information. */ dump(StringBuilder sb)191 void dump(StringBuilder sb) { 192 sb.append(" Entries: " + mEntries.size() + "\n"); 193 sb.append(" Requests: " + mRequestMap.size() + "\n"); 194 195 for (Entry entry : mEntries) { 196 sb.append(" " + entry.serverIf + ": [" + entry.handle + "] "); 197 switch (entry.type) { 198 case TYPE_SERVICE: 199 sb.append("Service " + entry.uuid); 200 sb.append(", started " + entry.started); 201 break; 202 203 case TYPE_CHARACTERISTIC: 204 sb.append(" Characteristic " + entry.uuid); 205 break; 206 207 case TYPE_DESCRIPTOR: 208 sb.append(" Descriptor " + entry.uuid); 209 break; 210 } 211 212 sb.append("\n"); 213 } 214 } 215 } 216