ContextMap.java revision 7a068c2a0861e12a3916cec313cf105395871999
103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta/*
203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Copyright (C) 2013 The Android Open Source Project
303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta *
403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Licensed under the Apache License, Version 2.0 (the "License");
503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * you may not use this file except in compliance with the License.
603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * You may obtain a copy of the License at
703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta *
803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta *      http://www.apache.org/licenses/LICENSE-2.0
903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta *
1003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Unless required by applicable law or agreed to in writing, software
1103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * distributed under the License is distributed on an "AS IS" BASIS,
1203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * See the License for the specific language governing permissions and
1403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * limitations under the License.
1503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */
166af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachpackage com.android.bluetooth.gatt;
1703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
188a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panickerimport android.content.Context;
198a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panickerimport android.os.Binder;
206af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport android.os.IBinder;
216af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport android.os.IBinder.DeathRecipient;
226af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport android.os.IInterface;
236af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport android.os.RemoteException;
2403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport android.util.Log;
2503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.ArrayList;
266af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport java.util.HashSet;
2703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.Iterator;
2803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.List;
296af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport java.util.NoSuchElementException;
3003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.Set;
3103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.UUID;
32f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Aroraimport java.util.HashMap;
33f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Aroraimport java.util.Map;
3403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
353122e5171ef26ff487f10826786606df848ca25eAjay Panickerimport com.android.bluetooth.btservice.BluetoothProto;
3603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta/**
3703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Helper class that keeps track of registered GATT applications.
3803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * This class manages application callbacks and keeps track of GATT connections.
3903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * @hide
4003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */
4103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta/*package*/ class ContextMap<T> {
4203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    private static final String TAG = GattServiceConfig.TAG_PREFIX + "ContextMap";
433122e5171ef26ff487f10826786606df848ca25eAjay Panicker    static final int NUM_SCAN_EVENTS_KEPT = 20;
448a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
458a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    /**
4603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Connection class helps map connection IDs to device addresses.
4703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
4803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    class Connection {
4903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        int connId;
5003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        String address;
5103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        int appId;
52337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker        long startTime;
5303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
5403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Connection(int connId, String address,int appId) {
5503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            this.connId = connId;
5603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            this.address = address;
5703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            this.appId = appId;
58337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker            this.startTime = System.currentTimeMillis();
5903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
6003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
6103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
6203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
6303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Application entry mapping UUIDs to appIDs and callbacks.
6403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
6503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    class App {
6603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        /** The UUID of the application */
6703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        UUID uuid;
6803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
6903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        /** The id of the application */
7003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        int id;
7103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
728a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        /** The package name of the application */
738a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        String name;
748a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
7503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        /** Application callbacks */
7603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        T callback;
7703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
786af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        /** Death receipient */
796af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        private IBinder.DeathRecipient mDeathRecipient;
806af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach
81934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        /** Flag to signal that transport is congested */
82934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        Boolean isCongested = false;
83934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham
84934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        /** Internal callback info queue, waiting to be send on congestion clear */
85934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        private List<CallbackInfo> congestionQueue = new ArrayList<CallbackInfo>();
86934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham
8703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        /**
8803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta         * Creates a new app context.
8903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta         */
908a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        App(UUID uuid, T callback, String name) {
9103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            this.uuid = uuid;
9203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            this.callback = callback;
938a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            this.name = name;
9403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
956af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach
966af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        /**
976af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach         * Link death recipient
986af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach         */
996af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        void linkToDeath(IBinder.DeathRecipient deathRecipient) {
1006af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            try {
1016af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                IBinder binder = ((IInterface)callback).asBinder();
1026af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                binder.linkToDeath(deathRecipient, 0);
1036af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                mDeathRecipient = deathRecipient;
1046af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            } catch (RemoteException e) {
1056af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                Log.e(TAG, "Unable to link deathRecipient for app id " + id);
1066af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            }
1076af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        }
1086af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach
1096af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        /**
1106af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach         * Unlink death recipient
1116af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach         */
1126af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        void unlinkToDeath() {
1136af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            if (mDeathRecipient != null) {
1146af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                try {
1156af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    IBinder binder = ((IInterface)callback).asBinder();
1166af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    binder.unlinkToDeath(mDeathRecipient,0);
1176af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                } catch (NoSuchElementException e) {
1186af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    Log.e(TAG, "Unable to unlink deathRecipient for app id " + id);
1196af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                }
1206af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            }
1216af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        }
122934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham
123934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        void queueCallback(CallbackInfo callbackInfo) {
124934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham            congestionQueue.add(callbackInfo);
125934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        }
126934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham
127934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        CallbackInfo popQueuedCallback() {
128934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham            if (congestionQueue.size() == 0) return null;
129934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham            return congestionQueue.remove(0);
130934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        }
13103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
13203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
13303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /** Our internal application list */
13403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    List<App> mApps = new ArrayList<App>();
13503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
1368a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    /** Internal map to keep track of logging information by app name */
1377a068c2a0861e12a3916cec313cf105395871999Ajay Panicker    HashMap<String, AppScanStats> mAppScanStats = new HashMap<String, AppScanStats>();
1387a068c2a0861e12a3916cec313cf105395871999Ajay Panicker
1397a068c2a0861e12a3916cec313cf105395871999Ajay Panicker    /** Internal list of scan events to use with the proto */
1407a068c2a0861e12a3916cec313cf105395871999Ajay Panicker    ArrayList<BluetoothProto.ScanEvent> mScanEvents =
1417a068c2a0861e12a3916cec313cf105395871999Ajay Panicker        new ArrayList<BluetoothProto.ScanEvent>(NUM_SCAN_EVENTS_KEPT);
1428a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
14303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /** Internal list of connected devices **/
14403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    Set<Connection> mConnections = new HashSet<Connection>();
14503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
14603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
14703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Add an entry to the application context list.
14803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
1498a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    void add(UUID uuid, T callback, Context context) {
1508a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        String appName = context.getPackageManager().getNameForUid(
1518a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                             Binder.getCallingUid());
1528a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        if (appName == null) {
1538a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            // Assign an app name if one isn't found
1548a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            appName = "Unknown App (UID: " + Binder.getCallingUid() + ")";
1558a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        }
1566af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        synchronized (mApps) {
1578a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            mApps.add(new App(uuid, callback, appName));
1587a068c2a0861e12a3916cec313cf105395871999Ajay Panicker            AppScanStats appScanStats = mAppScanStats.get(appName);
1597a068c2a0861e12a3916cec313cf105395871999Ajay Panicker            if (appScanStats == null) {
1607a068c2a0861e12a3916cec313cf105395871999Ajay Panicker                appScanStats = new AppScanStats(appName, this);
1617a068c2a0861e12a3916cec313cf105395871999Ajay Panicker                mAppScanStats.put(appName, appScanStats);
1628a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            }
1637a068c2a0861e12a3916cec313cf105395871999Ajay Panicker            appScanStats.isRegistered = true;
1646af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        }
16503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
16603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
16703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
1683f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach     * Remove the context for a given UUID
1693f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach     */
1703f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach    void remove(UUID uuid) {
1713f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach        synchronized (mApps) {
1723f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach            Iterator<App> i = mApps.iterator();
1738a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            while (i.hasNext()) {
1743f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach                App entry = i.next();
1753f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach                if (entry.uuid.equals(uuid)) {
1763f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach                    entry.unlinkToDeath();
1777a068c2a0861e12a3916cec313cf105395871999Ajay Panicker                    mAppScanStats.get(entry.name).isRegistered = false;
1783f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach                    i.remove();
1793f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach                    break;
1803f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach                }
1813f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach            }
1823f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach        }
1833f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach    }
1843f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach
1853f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach    /**
18603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Remove the context for a given application ID.
18703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
18803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    void remove(int id) {
1896af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        synchronized (mApps) {
1906af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            Iterator<App> i = mApps.iterator();
1918a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            while (i.hasNext()) {
1926af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                App entry = i.next();
1936af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                if (entry.id == id) {
1946af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    entry.unlinkToDeath();
1957a068c2a0861e12a3916cec313cf105395871999Ajay Panicker                    mAppScanStats.get(entry.name).isRegistered = false;
1966af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    i.remove();
1976af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    break;
1986af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                }
19903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            }
20003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
20103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
20203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
20303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
20403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Add a new connection for a given application ID.
20503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
20603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    void addConnection(int id, int connId, String address) {
2076af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        synchronized (mConnections) {
2086af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            App entry = getById(id);
2096af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            if (entry != null){
2106af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                mConnections.add(new Connection(connId, address, id));
2116af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            }
21203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
21303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
21403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
21503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
21603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Remove a connection with the given ID.
21703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
21803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    void removeConnection(int id, int connId) {
2196af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        synchronized (mConnections) {
2206af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            Iterator<Connection> i = mConnections.iterator();
2218a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            while (i.hasNext()) {
2226af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                Connection connection = i.next();
2236af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                if (connection.connId == connId) {
2246af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    i.remove();
2256af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    break;
2266af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                }
22703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            }
22803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
22903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
23003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
23103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
23203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Get an application context by ID.
23303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
23403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    App getById(int id) {
23503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<App> i = mApps.iterator();
2368a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
23703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            App entry = i.next();
23803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            if (entry.id == id) return entry;
23903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
24003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Log.e(TAG, "Context not found for ID " + id);
24103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return null;
24203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
24303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
24403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
24503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Get an application context by UUID.
24603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
24703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    App getByUuid(UUID uuid) {
24803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<App> i = mApps.iterator();
2498a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
25003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            App entry = i.next();
25103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            if (entry.uuid.equals(uuid)) return entry;
25203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
25303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Log.e(TAG, "Context not found for UUID " + uuid);
25403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return null;
25503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
25603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
25703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
2588a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker     * Get an application context by the calling Apps name.
2598a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker     */
2608a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    App getByName(String name) {
2618a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        Iterator<App> i = mApps.iterator();
2628a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
2638a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            App entry = i.next();
2648a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            if (entry.name.equals(name)) return entry;
2658a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        }
2668a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        Log.e(TAG, "Context not found for name " + name);
2678a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        return null;
2688a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    }
2698a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
2708a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    /**
2718a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker     * Get Logging info by ID
2728a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker     */
2737a068c2a0861e12a3916cec313cf105395871999Ajay Panicker    AppScanStats getAppScanStatsById(int id) {
2748a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        App temp = getById(id);
2758a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        if (temp != null) {
2767a068c2a0861e12a3916cec313cf105395871999Ajay Panicker            return mAppScanStats.get(temp.name);
2778a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        }
2788a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        return null;
2798a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    }
2808a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
2818a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    /**
2823122e5171ef26ff487f10826786606df848ca25eAjay Panicker     * Get Logging info by application name
2833122e5171ef26ff487f10826786606df848ca25eAjay Panicker     */
2847a068c2a0861e12a3916cec313cf105395871999Ajay Panicker    AppScanStats getAppScanStatsByName(String name) {
2857a068c2a0861e12a3916cec313cf105395871999Ajay Panicker        return mAppScanStats.get(name);
2863122e5171ef26ff487f10826786606df848ca25eAjay Panicker    }
2873122e5171ef26ff487f10826786606df848ca25eAjay Panicker
2883122e5171ef26ff487f10826786606df848ca25eAjay Panicker    /**
28903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Get the device addresses for all connected devices
29003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
29103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    Set<String> getConnectedDevices() {
29203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Set<String> addresses = new HashSet<String>();
29303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<Connection> i = mConnections.iterator();
2948a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
29503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            Connection connection = i.next();
29603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            addresses.add(connection.address);
29703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
29803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return addresses;
29903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
30003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
30103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
30203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Get an application context by a connection ID.
30303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
30403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    App getByConnId(int connId) {
30503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<Connection> ii = mConnections.iterator();
3068a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (ii.hasNext()) {
30703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            Connection connection = ii.next();
30803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            if (connection.connId == connId){
30903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta                return getById(connection.appId);
31003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            }
31103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
31203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return null;
31303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
31403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
31503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
31603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Returns a connection ID for a given device address.
31703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
31803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    Integer connIdByAddress(int id, String address) {
31903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        App entry = getById(id);
32003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        if (entry == null) return null;
32103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
32203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<Connection> i = mConnections.iterator();
3238a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
32403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            Connection connection = i.next();
32503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            if (connection.address.equals(address) && connection.appId == id)
32603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta                return connection.connId;
32703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
32803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return null;
32903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
33003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
33103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
33203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Returns the device address for a given connection ID.
33303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
33403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    String addressByConnId(int connId) {
33503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<Connection> i = mConnections.iterator();
3368a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
33703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            Connection connection = i.next();
33803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            if (connection.connId == connId) return connection.address;
33903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
34003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return null;
34103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
34203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
34303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    List<Connection> getConnectionByApp(int appId) {
34403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        List<Connection> currentConnections = new ArrayList<Connection>();
34503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<Connection> i = mConnections.iterator();
3468a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
34703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            Connection connection = i.next();
34803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            if (connection.appId == appId)
34903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta                currentConnections.add(connection);
35003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
35103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return currentConnections;
35203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
35303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
35403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
35503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Erases all application context entries.
35603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
35703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    void clear() {
3586af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        synchronized (mApps) {
3596af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            Iterator<App> i = mApps.iterator();
3608a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            while (i.hasNext()) {
3616af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                App entry = i.next();
3626af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                entry.unlinkToDeath();
3636af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                i.remove();
3646af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            }
3656af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        }
3666af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach
3676af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        synchronized (mConnections) {
3686af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            mConnections.clear();
3696af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        }
37003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
37103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
37203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
373f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora     * Returns connect device map with addr and appid
374f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora     */
375f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora    Map<Integer, String> getConnectedMap(){
376f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora        Map<Integer, String> connectedmap = new HashMap<Integer, String>();
377f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora        for(Connection conn: mConnections){
378f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora            connectedmap.put(conn.appId, conn.address);
379f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora        }
380f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora        return connectedmap;
381f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora    }
382f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora
3837a068c2a0861e12a3916cec313cf105395871999Ajay Panicker    void addScanEvent(BluetoothProto.ScanEvent event) {
3847a068c2a0861e12a3916cec313cf105395871999Ajay Panicker        synchronized(mScanEvents) {
3857a068c2a0861e12a3916cec313cf105395871999Ajay Panicker            if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT)
3867a068c2a0861e12a3916cec313cf105395871999Ajay Panicker                mScanEvents.remove(0);
3877a068c2a0861e12a3916cec313cf105395871999Ajay Panicker            mScanEvents.add(event);
3887a068c2a0861e12a3916cec313cf105395871999Ajay Panicker        }
3897a068c2a0861e12a3916cec313cf105395871999Ajay Panicker    }
3907a068c2a0861e12a3916cec313cf105395871999Ajay Panicker
391f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora    /**
39203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Logs debug information.
39303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
394a02de6484f9b6cac6b8c811edae11be55746b555Andre Eisenbach    void dump(StringBuilder sb) {
3957a068c2a0861e12a3916cec313cf105395871999Ajay Panicker        sb.append("  Entries: " + mAppScanStats.size() + "\n\n");
3968a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
3977a068c2a0861e12a3916cec313cf105395871999Ajay Panicker        Iterator<Map.Entry<String, AppScanStats>> it = mAppScanStats.entrySet().iterator();
3985c07523b0b5d32176d7ff3ab28555123123261ddAjay Panicker        while (it.hasNext()) {
3997a068c2a0861e12a3916cec313cf105395871999Ajay Panicker            Map.Entry<String, AppScanStats> entry = it.next();
40003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
4018a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            String name = entry.getKey();
4027a068c2a0861e12a3916cec313cf105395871999Ajay Panicker            AppScanStats appScanStats = entry.getValue();
4037a068c2a0861e12a3916cec313cf105395871999Ajay Panicker            appScanStats.dumpToString(sb);
40403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
40503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
4063122e5171ef26ff487f10826786606df848ca25eAjay Panicker
4073122e5171ef26ff487f10826786606df848ca25eAjay Panicker    void dumpProto(BluetoothProto.BluetoothLog proto) {
4083122e5171ef26ff487f10826786606df848ca25eAjay Panicker        synchronized(mScanEvents) {
4093122e5171ef26ff487f10826786606df848ca25eAjay Panicker            for (BluetoothProto.ScanEvent event : mScanEvents) {
4103122e5171ef26ff487f10826786606df848ca25eAjay Panicker                proto.addScanEvent(event);
4113122e5171ef26ff487f10826786606df848ca25eAjay Panicker            }
4123122e5171ef26ff487f10826786606df848ca25eAjay Panicker        }
4133122e5171ef26ff487f10826786606df848ca25eAjay Panicker    }
41403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta}
415