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 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 public int serverIf = 0; 37 public int type = TYPE_UNDEFINED; 38 public int handle = 0; 39 public UUID uuid = null; 40 public int instance = 0; 41 public int serviceType = 0; 42 public int serviceHandle = 0; 43 public int charHandle = 0; 44 public boolean started = false; 45 public boolean advertisePreferred = false; 46 Entry(int serverIf, int handle, UUID uuid, int serviceType, int instance)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 Entry(int serverIf, int handle, UUID uuid, int serviceType, int instance, boolean advertisePreferred)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 Entry(int serverIf, int type, int handle, UUID uuid, int serviceHandle)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 Entry(int serverIf, int type, int handle, UUID uuid, int serviceHandle, int charHandle)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 HandleMap()89 HandleMap() { 90 mEntries = new CopyOnWriteArrayList<Entry>(); 91 mRequestMap = new ConcurrentHashMap<Integer, Integer>(); 92 } 93 clear()94 void clear() { 95 mEntries.clear(); 96 mRequestMap.clear(); 97 } 98 addService(int serverIf, int handle, UUID uuid, int serviceType, int instance, boolean advertisePreferred)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 addCharacteristic(int serverIf, int handle, UUID uuid, int serviceHandle)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 addDescriptor(int serverIf, int handle, UUID uuid, int serviceHandle)109 void addDescriptor(int serverIf, int handle, UUID uuid, int serviceHandle) { 110 mEntries.add(new Entry(serverIf, TYPE_DESCRIPTOR, handle, uuid, serviceHandle, 111 mLastCharacteristic)); 112 } 113 setStarted(int serverIf, int handle, boolean started)114 void setStarted(int serverIf, int handle, boolean started) { 115 for (Entry entry : mEntries) { 116 if (entry.type != TYPE_SERVICE || entry.serverIf != serverIf 117 || entry.handle != handle) { 118 continue; 119 } 120 121 entry.started = started; 122 return; 123 } 124 } 125 getByHandle(int handle)126 Entry getByHandle(int handle) { 127 for (Entry entry : mEntries) { 128 if (entry.handle == handle) { 129 return entry; 130 } 131 } 132 Log.e(TAG, "getByHandle() - Handle " + handle + " not found!"); 133 return null; 134 } 135 checkServiceExists(UUID uuid, int handle)136 boolean checkServiceExists(UUID uuid, int handle) { 137 for (Entry entry : mEntries) { 138 if (entry.type == TYPE_SERVICE && entry.handle == handle && entry.uuid.equals(uuid)) { 139 return true; 140 } 141 } 142 return false; 143 } 144 deleteService(int serverIf, int serviceHandle)145 void deleteService(int serverIf, int serviceHandle) { 146 mEntries.removeIf(entry -> ((entry.serverIf == serverIf) 147 && (entry.handle == serviceHandle || entry.serviceHandle == serviceHandle))); 148 } 149 getEntries()150 List<Entry> getEntries() { 151 return mEntries; 152 } 153 addRequest(int requestId, int handle)154 void addRequest(int requestId, int handle) { 155 mRequestMap.put(requestId, handle); 156 } 157 deleteRequest(int requestId)158 void deleteRequest(int requestId) { 159 mRequestMap.remove(requestId); 160 } 161 getByRequestId(int requestId)162 Entry getByRequestId(int requestId) { 163 Integer handle = mRequestMap.get(requestId); 164 if (handle == null) { 165 Log.e(TAG, "getByRequestId() - Request ID " + requestId + " not found!"); 166 return null; 167 } 168 return getByHandle(handle); 169 } 170 171 172 /** 173 * Logs debug information. 174 */ dump(StringBuilder sb)175 void dump(StringBuilder sb) { 176 sb.append(" Entries: " + mEntries.size() + "\n"); 177 sb.append(" Requests: " + mRequestMap.size() + "\n"); 178 179 for (Entry entry : mEntries) { 180 sb.append(" " + entry.serverIf + ": [" + entry.handle + "] "); 181 switch (entry.type) { 182 case TYPE_SERVICE: 183 sb.append("Service " + entry.uuid); 184 sb.append(", started " + entry.started); 185 break; 186 187 case TYPE_CHARACTERISTIC: 188 sb.append(" Characteristic " + entry.uuid); 189 break; 190 191 case TYPE_DESCRIPTOR: 192 sb.append(" Descriptor " + entry.uuid); 193 break; 194 } 195 196 sb.append("\n"); 197 } 198 } 199 } 200