ContextMap.java revision 03b8386de26ba6500af2d66687bff9b01f2cbbd7
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
17     package com.android.bluetooth.gatt;
18
19
20import android.util.Log;
21import java.util.ArrayList;
22import java.util.Iterator;
23import java.util.List;
24import java.util.HashSet;
25import java.util.Set;
26import java.util.UUID;
27
28/**
29 * Helper class that keeps track of registered GATT applications.
30 * This class manages application callbacks and keeps track of GATT connections.
31 * @hide
32 */
33/*package*/ class ContextMap<T> {
34    private static final String TAG = GattServiceConfig.TAG_PREFIX + "ContextMap";
35
36    /**
37     * Connection class helps map connection IDs to device addresses.
38     */
39    class Connection {
40        int connId;
41        String address;
42        int appId;
43
44        Connection(int connId, String address,int appId) {
45            this.connId = connId;
46            this.address = address;
47            this.appId = appId;
48        }
49    }
50
51    /**
52     * Application entry mapping UUIDs to appIDs and callbacks.
53     */
54    class App {
55        /** The UUID of the application */
56        UUID uuid;
57
58        /** The id of the application */
59        int id;
60
61        /** Application callbacks */
62        T callback;
63
64        /**
65         * Creates a new app context.
66         */
67        App(UUID uuid, T callback) {
68            this.uuid = uuid;
69            this.callback = callback;
70        }
71    }
72
73    /** Our internal application list */
74    List<App> mApps = new ArrayList<App>();
75
76    /** Internal list of connected devices **/
77    Set<Connection> mConnections = new HashSet<Connection>();
78
79    /**
80     * Add an entry to the application context list.
81     */
82    void add(UUID uuid, T callback) {
83        mApps.add(new App(uuid, callback));
84    }
85
86    /**
87     * Remove the context for a given application ID.
88     */
89    void remove(int id) {
90        Iterator<App> i = mApps.iterator();
91        while(i.hasNext()) {
92            App entry = i.next();
93            if (entry.id == id) {
94                i.remove();
95                break;
96            }
97        }
98    }
99
100    /**
101     * Add a new connection for a given application ID.
102     */
103    void addConnection(int id, int connId, String address) {
104        App entry = getById(id);
105        if (entry != null){
106            mConnections.add(new Connection(connId, address, id));
107        }
108    }
109
110    /**
111     * Remove a connection with the given ID.
112     */
113    void removeConnection(int id, int connId) {
114        Iterator<Connection> i = mConnections.iterator();
115        while(i.hasNext()) {
116            Connection connection = i.next();
117            if (connection.connId == connId) {
118                i.remove();
119                break;
120            }
121        }
122    }
123
124    /**
125     * Get an application context by ID.
126     */
127    App getById(int id) {
128        Iterator<App> i = mApps.iterator();
129        while(i.hasNext()) {
130            App entry = i.next();
131            if (entry.id == id) return entry;
132        }
133        Log.e(TAG, "Context not found for ID " + id);
134        return null;
135    }
136
137    /**
138     * Get an application context by UUID.
139     */
140    App getByUuid(UUID uuid) {
141        Iterator<App> i = mApps.iterator();
142        while(i.hasNext()) {
143            App entry = i.next();
144            if (entry.uuid.equals(uuid)) return entry;
145        }
146        Log.e(TAG, "Context not found for UUID " + uuid);
147        return null;
148    }
149
150    /**
151     * Get the device addresses for all connected devices
152     */
153    Set<String> getConnectedDevices() {
154        Set<String> addresses = new HashSet<String>();
155        Iterator<Connection> i = mConnections.iterator();
156        while(i.hasNext()) {
157            Connection connection = i.next();
158            addresses.add(connection.address);
159        }
160        return addresses;
161    }
162
163    /**
164     * Get an application context by a connection ID.
165     */
166    App getByConnId(int connId) {
167        Iterator<Connection> ii = mConnections.iterator();
168        while(ii.hasNext()) {
169            Connection connection = ii.next();
170            if (connection.connId == connId){
171                return getById(connection.appId);
172            }
173        }
174        return null;
175    }
176
177    /**
178     * Returns a connection ID for a given device address.
179     */
180    Integer connIdByAddress(int id, String address) {
181        App entry = getById(id);
182        if (entry == null) return null;
183
184        Iterator<Connection> i = mConnections.iterator();
185        while(i.hasNext()) {
186            Connection connection = i.next();
187            if (connection.address.equals(address) && connection.appId == id)
188                return connection.connId;
189        }
190        return null;
191    }
192
193    /**
194     * Returns the device address for a given connection ID.
195     */
196    String addressByConnId(int connId) {
197        Iterator<Connection> i = mConnections.iterator();
198        while(i.hasNext()) {
199            Connection connection = i.next();
200            if (connection.connId == connId) return connection.address;
201        }
202        return null;
203    }
204
205    List<Connection> getConnectionByApp(int appId) {
206        List<Connection> currentConnections = new ArrayList<Connection>();
207        Iterator<Connection> i = mConnections.iterator();
208        while(i.hasNext()) {
209            Connection connection = i.next();
210            if (connection.appId == appId)
211                currentConnections.add(connection);
212        }
213        return currentConnections;
214    }
215
216    /**
217     * Erases all application context entries.
218     */
219    void clear() {
220        mApps.clear();
221        mConnections.clear();
222    }
223
224    /**
225     * Logs debug information.
226     */
227    void dump() {
228        StringBuilder b = new StringBuilder();
229        b.append(  "-------------- GATT Context Map ----------------");
230        b.append("\nEntries: " + mApps.size());
231
232        Iterator<App> i = mApps.iterator();
233        while(i.hasNext()) {
234            App entry = i.next();
235            List<Connection> connections = getConnectionByApp(entry.id);
236
237            b.append("\n\nApplication Id: " + entry.id);
238            b.append("\nUUID: " + entry.uuid);
239            b.append("\nConnections: " + connections.size());
240
241            Iterator<Connection> ii = connections.iterator();
242            while(ii.hasNext()) {
243                Connection connection = ii.next();
244                b.append("\n  " + connection.connId + ": " + connection.address);
245            }
246        }
247
248        b.append("\n------------------------------------------------");
249        Log.d(TAG, b.toString());
250    }
251}
252