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