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