• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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