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