ContextMap.java revision 8a0bc0a61e97f8923cb362e1dbb7ff66ffe51507
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;
288a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panickerimport java.util.LinkedList;
2903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.List;
306af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport java.util.NoSuchElementException;
3103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.Set;
3203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.UUID;
33f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Aroraimport java.util.HashMap;
34f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Aroraimport java.util.Map;
3503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
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";
4303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
4403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
458a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker     * ScanStats class helps keep track of information about scans
468a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker     * on a per application basis.
478a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker     */
488a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    class ScanStats {
498a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        static final int NUM_SCAN_DURATIONS_KEPT = 5;
508a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
518a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        int scansStarted = 0;
528a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        int scansStopped = 0;
538a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        boolean isScanning = false;
548a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        boolean isRegistered = false;
558a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        long minScanTime = Long.MAX_VALUE;
568a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        long maxScanTime = 0;
578a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        long totalScanTime = 0;
588a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        List<Long> lastScans = new ArrayList<Long>(NUM_SCAN_DURATIONS_KEPT + 1);
598a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        long startTime = 0;
608a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        long stopTime = 0;
618a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
628a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        void startScan() {
638a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            this.scansStarted++;
648a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            isScanning = true;
658a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            startTime = System.currentTimeMillis();
668a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        }
678a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
688a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        void stopScan() {
698a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            this.scansStopped++;
708a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            isScanning = false;
718a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            stopTime = System.currentTimeMillis();
728a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            long currTime = stopTime - startTime;
738a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
748a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            minScanTime = Math.min(currTime, minScanTime);
758a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            maxScanTime = Math.max(currTime, maxScanTime);
768a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            totalScanTime += currTime;
778a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            lastScans.add(currTime);
788a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            if (lastScans.size() > NUM_SCAN_DURATIONS_KEPT) {
798a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                lastScans.remove(0);
808a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            }
818a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        }
828a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    }
838a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
848a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    /**
8503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Connection class helps map connection IDs to device addresses.
8603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
8703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    class Connection {
8803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        int connId;
8903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        String address;
9003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        int appId;
9103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
9203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Connection(int connId, String address,int appId) {
9303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            this.connId = connId;
9403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            this.address = address;
9503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            this.appId = appId;
9603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
9703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
9803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
9903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
10003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Application entry mapping UUIDs to appIDs and callbacks.
10103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
10203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    class App {
10303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        /** The UUID of the application */
10403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        UUID uuid;
10503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
10603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        /** The id of the application */
10703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        int id;
10803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
1098a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        /** The package name of the application */
1108a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        String name;
1118a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
11203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        /** Application callbacks */
11303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        T callback;
11403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
1156af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        /** Death receipient */
1166af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        private IBinder.DeathRecipient mDeathRecipient;
1176af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach
118934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        /** Flag to signal that transport is congested */
119934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        Boolean isCongested = false;
120934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham
121934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        /** Internal callback info queue, waiting to be send on congestion clear */
122934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        private List<CallbackInfo> congestionQueue = new ArrayList<CallbackInfo>();
123934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham
12403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        /**
12503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta         * Creates a new app context.
12603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta         */
1278a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        App(UUID uuid, T callback, String name) {
12803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            this.uuid = uuid;
12903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            this.callback = callback;
1308a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            this.name = name;
13103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
1326af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach
1336af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        /**
1346af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach         * Link death recipient
1356af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach         */
1366af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        void linkToDeath(IBinder.DeathRecipient deathRecipient) {
1376af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            try {
1386af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                IBinder binder = ((IInterface)callback).asBinder();
1396af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                binder.linkToDeath(deathRecipient, 0);
1406af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                mDeathRecipient = deathRecipient;
1416af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            } catch (RemoteException e) {
1426af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                Log.e(TAG, "Unable to link deathRecipient for app id " + id);
1436af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            }
1446af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        }
1456af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach
1466af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        /**
1476af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach         * Unlink death recipient
1486af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach         */
1496af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        void unlinkToDeath() {
1506af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            if (mDeathRecipient != null) {
1516af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                try {
1526af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    IBinder binder = ((IInterface)callback).asBinder();
1536af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    binder.unlinkToDeath(mDeathRecipient,0);
1546af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                } catch (NoSuchElementException e) {
1556af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    Log.e(TAG, "Unable to unlink deathRecipient for app id " + id);
1566af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                }
1576af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            }
1586af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        }
159934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham
160934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        void queueCallback(CallbackInfo callbackInfo) {
161934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham            congestionQueue.add(callbackInfo);
162934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        }
163934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham
164934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        CallbackInfo popQueuedCallback() {
165934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham            if (congestionQueue.size() == 0) return null;
166934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham            return congestionQueue.remove(0);
167934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham        }
16803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
16903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
17003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /** Our internal application list */
17103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    List<App> mApps = new ArrayList<App>();
17203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
1738a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    /** Internal map to keep track of logging information by app name */
1748a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    HashMap<String, ScanStats> mScanStats = new HashMap<String, ScanStats>();
1758a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
17603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /** Internal list of connected devices **/
17703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    Set<Connection> mConnections = new HashSet<Connection>();
17803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
17903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
18003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Add an entry to the application context list.
18103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
1828a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    void add(UUID uuid, T callback, Context context) {
1838a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        String appName = context.getPackageManager().getNameForUid(
1848a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                             Binder.getCallingUid());
1858a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        if (appName == null) {
1868a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            // Assign an app name if one isn't found
1878a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            appName = "Unknown App (UID: " + Binder.getCallingUid() + ")";
1888a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        }
1896af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        synchronized (mApps) {
1908a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            mApps.add(new App(uuid, callback, appName));
1918a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            ScanStats scanStats = mScanStats.get(appName);
1928a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            if (scanStats == null) {
1938a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                scanStats = new ScanStats();
1948a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                mScanStats.put(appName, scanStats);
1958a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            }
1968a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            scanStats.isRegistered = true;
1976af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        }
19803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
19903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
20003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
2013f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach     * Remove the context for a given UUID
2023f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach     */
2033f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach    void remove(UUID uuid) {
2043f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach        synchronized (mApps) {
2053f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach            Iterator<App> i = mApps.iterator();
2068a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            while (i.hasNext()) {
2073f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach                App entry = i.next();
2083f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach                if (entry.uuid.equals(uuid)) {
2093f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach                    entry.unlinkToDeath();
2108a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                    mScanStats.get(entry.name).isRegistered = false;
2113f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach                    i.remove();
2123f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach                    break;
2133f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach                }
2143f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach            }
2153f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach        }
2163f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach    }
2173f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach
2183f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach    /**
21903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Remove the context for a given application ID.
22003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
22103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    void remove(int id) {
2226af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        synchronized (mApps) {
2236af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            Iterator<App> i = mApps.iterator();
2248a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            while (i.hasNext()) {
2256af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                App entry = i.next();
2266af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                if (entry.id == id) {
2276af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    entry.unlinkToDeath();
2288a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                    mScanStats.get(entry.name).isRegistered = false;
2296af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    i.remove();
2306af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    break;
2316af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                }
23203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            }
23303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
23403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
23503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
23603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
23703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Add a new connection for a given application ID.
23803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
23903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    void addConnection(int id, int connId, String address) {
2406af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        synchronized (mConnections) {
2416af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            App entry = getById(id);
2426af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            if (entry != null){
2436af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                mConnections.add(new Connection(connId, address, id));
2446af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            }
24503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
24603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
24703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
24803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
24903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Remove a connection with the given ID.
25003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
25103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    void removeConnection(int id, int connId) {
2526af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        synchronized (mConnections) {
2536af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            Iterator<Connection> i = mConnections.iterator();
2548a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            while (i.hasNext()) {
2556af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                Connection connection = i.next();
2566af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                if (connection.connId == connId) {
2576af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    i.remove();
2586af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                    break;
2596af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                }
26003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            }
26103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
26203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
26303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
26403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
26503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Get an application context by ID.
26603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
26703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    App getById(int id) {
26803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<App> i = mApps.iterator();
2698a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
27003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            App entry = i.next();
27103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            if (entry.id == id) return entry;
27203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
27303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Log.e(TAG, "Context not found for ID " + id);
27403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return null;
27503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
27603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
27703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
27803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Get an application context by UUID.
27903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
28003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    App getByUuid(UUID uuid) {
28103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<App> i = mApps.iterator();
2828a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
28303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            App entry = i.next();
28403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            if (entry.uuid.equals(uuid)) return entry;
28503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
28603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Log.e(TAG, "Context not found for UUID " + uuid);
28703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return null;
28803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
28903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
29003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
2918a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker     * Get an application context by the calling Apps name.
2928a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker     */
2938a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    App getByName(String name) {
2948a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        Iterator<App> i = mApps.iterator();
2958a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
2968a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            App entry = i.next();
2978a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            if (entry.name.equals(name)) return entry;
2988a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        }
2998a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        Log.e(TAG, "Context not found for name " + name);
3008a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        return null;
3018a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    }
3028a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
3038a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    /**
3048a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker     * Get Logging info by ID
3058a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker     */
3068a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    ScanStats getScanStatsById(int id) {
3078a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        App temp = getById(id);
3088a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        if (temp != null) {
3098a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            return mScanStats.get(temp.name);
3108a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        }
3118a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        return null;
3128a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    }
3138a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
3148a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker    /**
31503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Get the device addresses for all connected devices
31603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
31703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    Set<String> getConnectedDevices() {
31803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Set<String> addresses = new HashSet<String>();
31903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<Connection> i = mConnections.iterator();
3208a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
32103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            Connection connection = i.next();
32203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            addresses.add(connection.address);
32303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
32403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return addresses;
32503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
32603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
32703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
32803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Get an application context by a connection ID.
32903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
33003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    App getByConnId(int connId) {
33103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<Connection> ii = mConnections.iterator();
3328a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (ii.hasNext()) {
33303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            Connection connection = ii.next();
33403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            if (connection.connId == connId){
33503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta                return getById(connection.appId);
33603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            }
33703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
33803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return null;
33903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
34003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
34103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
34203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Returns a connection ID for a given device address.
34303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
34403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    Integer connIdByAddress(int id, String address) {
34503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        App entry = getById(id);
34603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        if (entry == null) return null;
34703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
34803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<Connection> i = mConnections.iterator();
3498a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
35003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            Connection connection = i.next();
35103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            if (connection.address.equals(address) && connection.appId == id)
35203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta                return connection.connId;
35303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
35403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return null;
35503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
35603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
35703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
35803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Returns the device address for a given connection ID.
35903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
36003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    String addressByConnId(int connId) {
36103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<Connection> i = mConnections.iterator();
3628a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
36303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            Connection connection = i.next();
36403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            if (connection.connId == connId) return connection.address;
36503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
36603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return null;
36703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
36803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
36903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    List<Connection> getConnectionByApp(int appId) {
37003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        List<Connection> currentConnections = new ArrayList<Connection>();
37103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        Iterator<Connection> i = mConnections.iterator();
3728a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
37303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            Connection connection = i.next();
37403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            if (connection.appId == appId)
37503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta                currentConnections.add(connection);
37603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
37703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        return currentConnections;
37803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
37903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
38003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
38103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Erases all application context entries.
38203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
38303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    void clear() {
3846af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        synchronized (mApps) {
3856af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            Iterator<App> i = mApps.iterator();
3868a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            while (i.hasNext()) {
3876af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                App entry = i.next();
3886af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                entry.unlinkToDeath();
3896af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach                i.remove();
3906af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            }
3916af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        }
3926af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach
3936af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        synchronized (mConnections) {
3946af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach            mConnections.clear();
3956af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach        }
39603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
39703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
39803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    /**
399f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora     * Returns connect device map with addr and appid
400f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora     */
401f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora    Map<Integer, String> getConnectedMap(){
402f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora        Map<Integer, String> connectedmap = new HashMap<Integer, String>();
403f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora        for(Connection conn: mConnections){
404f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora            connectedmap.put(conn.appId, conn.address);
405f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora        }
406f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora        return connectedmap;
407f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora    }
408f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora
409f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora    /**
41003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     * Logs debug information.
41103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta     */
412a02de6484f9b6cac6b8c811edae11be55746b555Andre Eisenbach    void dump(StringBuilder sb) {
4138a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        long currTime = System.currentTimeMillis();
41403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
4158a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        sb.append("  Entries: " + mScanStats.size() + "\n\n");
4168a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4178a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        Iterator<Map.Entry<String,ScanStats>> i = mScanStats.entrySet().iterator();
4188a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker        while (i.hasNext()) {
4198a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            Map.Entry<String, ScanStats> entry = i.next();
42003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
4218a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            String name = entry.getKey();
4228a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            ScanStats scanStats = entry.getValue();
42303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta
4248a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            long maxScanTime = scanStats.maxScanTime;
4258a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            long minScanTime = scanStats.minScanTime;
4268a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            long currScanTime = 0;
4278a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4288a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            if (scanStats.isScanning) {
4298a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                currScanTime = currTime - scanStats.startTime;
4308a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                minScanTime = Math.min(currScanTime, minScanTime);
4318a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                maxScanTime = Math.max(currScanTime, maxScanTime);
4328a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            }
4338a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4348a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            if (minScanTime == Long.MAX_VALUE) {
4358a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                minScanTime = 0;
4368a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            }
4378a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4388a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            long lastScan = 0;
4398a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            if (scanStats.stopTime != 0) {
4408a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                lastScan = currTime - scanStats.stopTime;
4418a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            }
4428a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4438a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            long avgScanTime = 0;
4448a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            if (scanStats.scansStarted > 0) {
4458a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                avgScanTime = (scanStats.totalScanTime + currScanTime) /
4468a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                              scanStats.scansStarted;
4478a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            }
4488a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4498a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            sb.append("  Application Name: " + name);
4508a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            if (scanStats.isRegistered) sb.append(" (Registered)");
4518a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            sb.append("\n");
4528a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4538a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            sb.append("  LE scans (started/stopped)       : " +
4548a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                      scanStats.scansStarted + " / " +
4558a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                      scanStats.scansStopped + "\n");
4568a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            sb.append("  Scan time in ms (min/max/avg)    : " +
4578a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                      minScanTime + " / " +
4588a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                      maxScanTime + " / " +
4598a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                      avgScanTime + "\n");
4608a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4618a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            sb.append("  Time since last scan ended in ms : " + lastScan + "\n");
4628a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4638a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            sb.append("  Last " + scanStats.lastScans.size() +
4648a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                      " scans in ms (oldest first): ");
4658a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            for (Long time : scanStats.lastScans) {
4668a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                sb.append(time + " ");
4678a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            }
4688a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            sb.append("\n");
4698a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4708a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            if (scanStats.isRegistered) {
4718a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                App appEntry = getByName(name);
4728a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                sb.append("  Application ID                   : " +
4738a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                          appEntry.id + "\n");
4748a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                sb.append("  UUID                             : " +
4758a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                          appEntry.uuid + "\n");
4768a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4778a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                if (scanStats.isScanning) {
4788a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                    sb.append("  Current scan duration            : " +
4798a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                              currScanTime + "\n");
4808a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                }
4818a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4828a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                List<Connection> connections = getConnectionByApp(appEntry.id);
4838a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                sb.append("  Connections: " + connections.size() + "\n");
4848a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker
4858a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                Iterator<Connection> ii = connections.iterator();
4868a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                while(ii.hasNext()) {
4878a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                    Connection connection = ii.next();
4888a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                    sb.append("    " + connection.connId + ": " +
4898a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                              connection.address + "\n");
4908a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker                }
49103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta            }
4928a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker            sb.append("\n");
49303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta        }
49403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta    }
49503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta}
496