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 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 55 Entry(int serverIf, int type, int handle, UUID uuid, int serviceHandle) { 56 this.serverIf = serverIf; 57 this.type = type; 58 this.handle = handle; 59 this.uuid = uuid; 60 this.instance = instance; 61 this.serviceHandle = serviceHandle; 62 } 63 64 Entry(int serverIf, int type, int handle, UUID uuid, int serviceHandle, int charHandle) { 65 this.serverIf = serverIf; 66 this.type = type; 67 this.handle = handle; 68 this.uuid = uuid; 69 this.instance = instance; 70 this.serviceHandle = serviceHandle; 71 this.charHandle = charHandle; 72 } 73 } 74 75 List<Entry> mEntries = null; 76 Map<Integer, Integer> mRequestMap = null; 77 int mLastCharacteristic = 0; 78 79 HandleMap() { 80 mEntries = new ArrayList<Entry>(); 81 mRequestMap = new HashMap<Integer, Integer>(); 82 } 83 84 void clear() { 85 mEntries.clear(); 86 mRequestMap.clear(); 87 } 88 89 void addService(int serverIf, int handle, UUID uuid, int serviceType, int instance) { 90 mEntries.add(new Entry(serverIf, handle, uuid, serviceType, instance)); 91 } 92 93 void addCharacteristic(int serverIf, int handle, UUID uuid, int serviceHandle) { 94 mLastCharacteristic = handle; 95 mEntries.add(new Entry(serverIf, TYPE_CHARACTERISTIC, handle, uuid, serviceHandle)); 96 } 97 98 void addDescriptor(int serverIf, int handle, UUID uuid, int serviceHandle) { 99 mEntries.add(new Entry(serverIf, TYPE_DESCRIPTOR, handle, uuid, serviceHandle, mLastCharacteristic)); 100 } 101 102 void setStarted(int serverIf, int handle, boolean started) { 103 for(Entry entry : mEntries) { 104 if (entry.type != TYPE_SERVICE || 105 entry.serverIf != serverIf || 106 entry.handle != handle) 107 continue; 108 109 entry.started = started; 110 return; 111 } 112 } 113 114 Entry getByHandle(int handle) { 115 for(Entry entry : mEntries) { 116 if (entry.handle == handle) 117 return entry; 118 } 119 Log.e(TAG, "getByHandle() - Handle " + handle + " not found!"); 120 return null; 121 } 122 123 int getServiceHandle(UUID uuid, int serviceType, int instance) { 124 for(Entry entry : mEntries) { 125 if (entry.type == TYPE_SERVICE && 126 entry.serviceType == serviceType && 127 entry.instance == instance && 128 entry.uuid.equals(uuid)) { 129 return entry.handle; 130 } 131 } 132 Log.e(TAG, "getServiceHandle() - UUID " + uuid + " not found!"); 133 return 0; 134 } 135 136 int getCharacteristicHandle(int serviceHandle, UUID uuid, int instance) { 137 for(Entry entry : mEntries) { 138 if (entry.type == TYPE_CHARACTERISTIC && 139 entry.serviceHandle == serviceHandle && 140 entry.instance == instance && 141 entry.uuid.equals(uuid)) { 142 return entry.handle; 143 } 144 } 145 Log.e(TAG, "getCharacteristicHandle() - Service " + serviceHandle 146 + ", UUID " + uuid + " not found!"); 147 return 0; 148 } 149 150 void deleteService(int serverIf, int serviceHandle) { 151 for(Iterator <Entry> it = mEntries.iterator(); it.hasNext();) { 152 Entry entry = it.next(); 153 if (entry.serverIf != serverIf) continue; 154 155 if (entry.handle == serviceHandle || 156 entry.serviceHandle == serviceHandle) 157 it.remove(); 158 } 159 } 160 161 List<Entry> getEntries() { 162 return mEntries; 163 } 164 165 void addRequest(int requestId, int handle) { 166 mRequestMap.put(requestId, handle); 167 } 168 169 void deleteRequest(int requestId) { 170 mRequestMap.remove(requestId); 171 } 172 173 Entry getByRequestId(int requestId) { 174 Integer handle = mRequestMap.get(requestId); 175 if (handle == null) { 176 Log.e(TAG, "getByRequestId() - Request ID " + requestId + " not found!"); 177 return null; 178 } 179 return getByHandle(handle); 180 } 181 182 183 /** 184 * Logs debug information. 185 */ 186 void dump() { 187 StringBuilder b = new StringBuilder(); 188 b.append( "-------------- GATT Handle Map -----------------"); 189 b.append("\nEntries: " + mEntries.size()); 190 b.append("\nRequests: " + mRequestMap.size()); 191 192 for (Entry entry : mEntries) { 193 b.append("\n" + entry.serverIf + ": [" + entry.handle + "] "); 194 switch(entry.type) { 195 case TYPE_SERVICE: 196 b.append("Service " + entry.uuid); 197 b.append(", started " + entry.started); 198 break; 199 200 case TYPE_CHARACTERISTIC: 201 b.append(" Characteristic " + entry.uuid); 202 break; 203 204 case TYPE_DESCRIPTOR: 205 b.append(" Descriptor " + entry.uuid); 206 break; 207 } 208 } 209 210 b.append("\n------------------------------------------------"); 211 Log.d(TAG, b.toString()); 212 } 213 } 214