ContextMap.java revision 337ee9418b0122e6a89ff38cd49f031ba80aa24c
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 18f0202e094a55e51d1e1399f18ad255fb636dd381Ajay Panickerimport android.bluetooth.le.ScanSettings; 198a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panickerimport android.content.Context; 208a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panickerimport android.os.Binder; 216af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport android.os.IBinder; 226af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport android.os.IBinder.DeathRecipient; 236af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport android.os.IInterface; 246af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport android.os.RemoteException; 2503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport android.util.Log; 265c07523b0b5d32176d7ff3ab28555123123261ddAjay Panickerimport java.text.DateFormat; 275c07523b0b5d32176d7ff3ab28555123123261ddAjay Panickerimport java.text.SimpleDateFormat; 2803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.ArrayList; 295c07523b0b5d32176d7ff3ab28555123123261ddAjay Panickerimport java.util.Date; 306af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport java.util.HashSet; 3103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.Iterator; 328a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panickerimport java.util.LinkedList; 3303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.List; 346af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbachimport java.util.NoSuchElementException; 3503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.Set; 3603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Battaimport java.util.UUID; 37f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Aroraimport java.util.HashMap; 38f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Aroraimport java.util.Map; 3903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 403122e5171ef26ff487f10826786606df848ca25eAjay Panickerimport com.android.bluetooth.btservice.BluetoothProto; 413122e5171ef26ff487f10826786606df848ca25eAjay Panicker 4203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta/** 4303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Helper class that keeps track of registered GATT applications. 4403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * This class manages application callbacks and keeps track of GATT connections. 4503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * @hide 4603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 4703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta/*package*/ class ContextMap<T> { 4803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta private static final String TAG = GattServiceConfig.TAG_PREFIX + "ContextMap"; 4903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 505c07523b0b5d32176d7ff3ab28555123123261ddAjay Panicker static final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); 513122e5171ef26ff487f10826786606df848ca25eAjay Panicker static final int NUM_SCAN_EVENTS_KEPT = 20; 523122e5171ef26ff487f10826786606df848ca25eAjay Panicker ArrayList<BluetoothProto.ScanEvent> mScanEvents = 533122e5171ef26ff487f10826786606df848ca25eAjay Panicker new ArrayList<BluetoothProto.ScanEvent>(NUM_SCAN_EVENTS_KEPT); 543122e5171ef26ff487f10826786606df848ca25eAjay Panicker 5503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 568a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker * ScanStats class helps keep track of information about scans 578a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker * on a per application basis. 588a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker */ 598a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker class ScanStats { 60337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker 61337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker class LastScan { 62337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker long durration; 63337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker long timestamp; 64337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker boolean opportunistic; 65337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker boolean background; 66337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker 67337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker public LastScan(long timestamp, long durration, 68337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker boolean opportunistic, boolean background) { 69337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker this.durration = durration; 70337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker this.timestamp = timestamp; 71337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker this.opportunistic = opportunistic; 72337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker this.background = background; 73337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker } 74337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker } 75337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker 768a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker static final int NUM_SCAN_DURATIONS_KEPT = 5; 778a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker 783122e5171ef26ff487f10826786606df848ca25eAjay Panicker String appName; 798a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker int scansStarted = 0; 808a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker int scansStopped = 0; 818a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker boolean isScanning = false; 828a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker boolean isRegistered = false; 83f0202e094a55e51d1e1399f18ad255fb636dd381Ajay Panicker boolean isOpportunisticScan = false; 84f0202e094a55e51d1e1399f18ad255fb636dd381Ajay Panicker boolean isBackgroundScan = false; 858a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker long minScanTime = Long.MAX_VALUE; 868a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker long maxScanTime = 0; 878a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker long totalScanTime = 0; 88337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker List<LastScan> lastScans = new ArrayList<LastScan>(NUM_SCAN_DURATIONS_KEPT + 1); 898a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker long startTime = 0; 908a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker long stopTime = 0; 918a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker 923122e5171ef26ff487f10826786606df848ca25eAjay Panicker public ScanStats(String name) { 933122e5171ef26ff487f10826786606df848ca25eAjay Panicker appName = name; 943122e5171ef26ff487f10826786606df848ca25eAjay Panicker } 953122e5171ef26ff487f10826786606df848ca25eAjay Panicker 96a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker synchronized void recordScanStart(ScanSettings settings) { 97ef437b17ba8b192488cb77ffd39daa3e83ba4aeaAjay Panicker if (isScanning) 98ef437b17ba8b192488cb77ffd39daa3e83ba4aeaAjay Panicker return; 99ef437b17ba8b192488cb77ffd39daa3e83ba4aeaAjay Panicker 1008a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker this.scansStarted++; 1018a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker isScanning = true; 1028a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker startTime = System.currentTimeMillis(); 103ef437b17ba8b192488cb77ffd39daa3e83ba4aeaAjay Panicker 104f0202e094a55e51d1e1399f18ad255fb636dd381Ajay Panicker if (settings != null) { 105f0202e094a55e51d1e1399f18ad255fb636dd381Ajay Panicker isOpportunisticScan = settings.getScanMode() == ScanSettings.SCAN_MODE_OPPORTUNISTIC; 106f0202e094a55e51d1e1399f18ad255fb636dd381Ajay Panicker isBackgroundScan = (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0; 107f0202e094a55e51d1e1399f18ad255fb636dd381Ajay Panicker } 1083122e5171ef26ff487f10826786606df848ca25eAjay Panicker 1093122e5171ef26ff487f10826786606df848ca25eAjay Panicker BluetoothProto.ScanEvent scanEvent = new BluetoothProto.ScanEvent(); 1103122e5171ef26ff487f10826786606df848ca25eAjay Panicker scanEvent.setScanEventType(BluetoothProto.ScanEvent.SCAN_EVENT_START); 1113122e5171ef26ff487f10826786606df848ca25eAjay Panicker scanEvent.setScanTechnologyType(BluetoothProto.ScanEvent.SCAN_TECH_TYPE_LE); 1123122e5171ef26ff487f10826786606df848ca25eAjay Panicker scanEvent.setInitiator(appName); 1133122e5171ef26ff487f10826786606df848ca25eAjay Panicker scanEvent.setEventTimeMillis(System.currentTimeMillis()); 1145c07523b0b5d32176d7ff3ab28555123123261ddAjay Panicker 115337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker lastScans.add(new LastScan(startTime, 0, false, false)); 116337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker 117337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker if (settings != null) { 118337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker isOpportunisticScan = settings.getScanMode() == ScanSettings.SCAN_MODE_OPPORTUNISTIC; 119337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker isBackgroundScan = (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0; 1205c07523b0b5d32176d7ff3ab28555123123261ddAjay Panicker } 1215c07523b0b5d32176d7ff3ab28555123123261ddAjay Panicker 1223122e5171ef26ff487f10826786606df848ca25eAjay Panicker synchronized(mScanEvents) { 1233122e5171ef26ff487f10826786606df848ca25eAjay Panicker if(mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) 1243122e5171ef26ff487f10826786606df848ca25eAjay Panicker mScanEvents.remove(0); 1253122e5171ef26ff487f10826786606df848ca25eAjay Panicker mScanEvents.add(scanEvent); 1263122e5171ef26ff487f10826786606df848ca25eAjay Panicker } 1278a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker } 1288a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker 129a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker synchronized void recordScanStop() { 130ef437b17ba8b192488cb77ffd39daa3e83ba4aeaAjay Panicker if (!isScanning) 131ef437b17ba8b192488cb77ffd39daa3e83ba4aeaAjay Panicker return; 132ef437b17ba8b192488cb77ffd39daa3e83ba4aeaAjay Panicker 1338a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker this.scansStopped++; 1348a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker isScanning = false; 1358a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker stopTime = System.currentTimeMillis(); 1368a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker long currTime = stopTime - startTime; 1378a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker 1388a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker minScanTime = Math.min(currTime, minScanTime); 1398a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker maxScanTime = Math.max(currTime, maxScanTime); 1408a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker totalScanTime += currTime; 141337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker 142337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker LastScan curr = lastScans.get(lastScans.size() - 1); 143337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker curr.durration = currTime; 144337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker curr.opportunistic = isOpportunisticScan; 145337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker curr.background = isBackgroundScan; 146337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker 147337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker isOpportunisticScan = false; 148337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker isBackgroundScan = false; 149337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker 1508a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker if (lastScans.size() > NUM_SCAN_DURATIONS_KEPT) { 1518a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker lastScans.remove(0); 1528a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker } 1533122e5171ef26ff487f10826786606df848ca25eAjay Panicker 1543122e5171ef26ff487f10826786606df848ca25eAjay Panicker BluetoothProto.ScanEvent scanEvent = new BluetoothProto.ScanEvent(); 1553122e5171ef26ff487f10826786606df848ca25eAjay Panicker scanEvent.setScanEventType(BluetoothProto.ScanEvent.SCAN_EVENT_STOP); 1563122e5171ef26ff487f10826786606df848ca25eAjay Panicker scanEvent.setScanTechnologyType(BluetoothProto.ScanEvent.SCAN_TECH_TYPE_LE); 1573122e5171ef26ff487f10826786606df848ca25eAjay Panicker scanEvent.setInitiator(appName); 1583122e5171ef26ff487f10826786606df848ca25eAjay Panicker scanEvent.setEventTimeMillis(System.currentTimeMillis()); 1593122e5171ef26ff487f10826786606df848ca25eAjay Panicker synchronized(mScanEvents) { 1603122e5171ef26ff487f10826786606df848ca25eAjay Panicker if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) 1613122e5171ef26ff487f10826786606df848ca25eAjay Panicker mScanEvents.remove(0); 1623122e5171ef26ff487f10826786606df848ca25eAjay Panicker mScanEvents.add(scanEvent); 1633122e5171ef26ff487f10826786606df848ca25eAjay Panicker } 1648a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker } 165a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker 166a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker synchronized void dumpToString(StringBuilder sb) { 167a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker long currTime = System.currentTimeMillis(); 168a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker long maxScan = maxScanTime; 169a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker long minScan = minScanTime; 170a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker long currScan = 0; 171a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker 172a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker if (isScanning) { 173a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker currScan = currTime - startTime; 174a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker minScan = Math.min(currScan, minScan); 175a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker maxScan = Math.max(currScan, maxScan); 176a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker } 177a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker 178a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker if (minScan == Long.MAX_VALUE) { 179a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker minScan = 0; 180a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker } 181a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker 182a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker long lastScan = 0; 183a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker if (stopTime != 0) { 184a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker lastScan = currTime - stopTime; 185a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker } 186a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker 187a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker long avgScan = 0; 188a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker if (scansStarted > 0) { 189a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker avgScan = (totalScanTime + currScan) / scansStarted; 190a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker } 191a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker 192a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker sb.append(" " + appName); 193a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker if (isRegistered) sb.append(" (Registered)"); 194a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker if (isOpportunisticScan) sb.append(" (Opportunistic)"); 195a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker if (isBackgroundScan) sb.append(" (Background)"); 196a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker sb.append("\n"); 197a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker 198337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker sb.append(" LE scans (started/stopped) : " + 199a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker scansStarted + " / " + 200a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker scansStopped + "\n"); 201337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker sb.append(" Scan time in ms (min/max/avg/total): " + 202a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker minScan + " / " + 203a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker maxScan + " / " + 204337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker avgScan + " / " + 205337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker totalScanTime + "\n"); 206a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker 207a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker if (lastScans.size() != 0) { 208337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker int lastScansSize = scansStopped < NUM_SCAN_DURATIONS_KEPT ? 209337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker scansStopped : NUM_SCAN_DURATIONS_KEPT; 210337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker sb.append(" Last " + lastScansSize + 211337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker " scans :\n"); 212337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker 213337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker for (int i = 0; i < lastScansSize; i++) { 214337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker LastScan scan = lastScans.get(i); 215337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker Date timestamp = new Date(scan.timestamp); 216a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker sb.append(" " + dateFormat.format(timestamp) + " - "); 217337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker sb.append(scan.durration + "ms "); 218337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker if (scan.opportunistic) sb.append("Opp "); 219337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker if (scan.background) sb.append("Back"); 220337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker sb.append("\n"); 221a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker } 222a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker } 223a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker 224a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker if (isRegistered) { 225a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker App appEntry = getByName(appName); 226337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker sb.append(" Application ID : " + 227a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker appEntry.id + "\n"); 228337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker sb.append(" UUID : " + 229a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker appEntry.uuid + "\n"); 230a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker 231a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker if (isScanning) { 232337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker sb.append(" Current scan duration in ms : " + 233a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker currScan + "\n"); 234a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker } 235a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker 236a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker List<Connection> connections = getConnectionByApp(appEntry.id); 237a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker sb.append(" Connections: " + connections.size() + "\n"); 238a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker 239a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker Iterator<Connection> ii = connections.iterator(); 240a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker while(ii.hasNext()) { 241a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker Connection connection = ii.next(); 242337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker long connectionTime = System.currentTimeMillis() - connection.startTime; 243a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker sb.append(" " + connection.connId + ": " + 244337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker connection.address + " " + connectionTime + "ms\n"); 245a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker } 246a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker } 247a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker sb.append("\n"); 248a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker } 2498a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker } 2508a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker 2518a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker /** 25203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Connection class helps map connection IDs to device addresses. 25303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 25403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta class Connection { 25503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta int connId; 25603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta String address; 25703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta int appId; 258337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker long startTime; 25903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 26003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Connection(int connId, String address,int appId) { 26103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta this.connId = connId; 26203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta this.address = address; 26303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta this.appId = appId; 264337ee9418b0122e6a89ff38cd49f031ba80aa24cAjay Panicker this.startTime = System.currentTimeMillis(); 26503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 26603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 26703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 26803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 26903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Application entry mapping UUIDs to appIDs and callbacks. 27003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 27103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta class App { 27203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** The UUID of the application */ 27303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta UUID uuid; 27403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 27503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** The id of the application */ 27603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta int id; 27703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 2788a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker /** The package name of the application */ 2798a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker String name; 2808a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker 28103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** Application callbacks */ 28203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta T callback; 28303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 2846af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach /** Death receipient */ 2856af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach private IBinder.DeathRecipient mDeathRecipient; 2866af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach 287934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham /** Flag to signal that transport is congested */ 288934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham Boolean isCongested = false; 289934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham 290934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham /** Internal callback info queue, waiting to be send on congestion clear */ 291934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham private List<CallbackInfo> congestionQueue = new ArrayList<CallbackInfo>(); 292934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham 29303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 29403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Creates a new app context. 29503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 2968a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker App(UUID uuid, T callback, String name) { 29703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta this.uuid = uuid; 29803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta this.callback = callback; 2998a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker this.name = name; 30003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 3016af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach 3026af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach /** 3036af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach * Link death recipient 3046af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach */ 3056af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach void linkToDeath(IBinder.DeathRecipient deathRecipient) { 3066af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach try { 3076af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach IBinder binder = ((IInterface)callback).asBinder(); 3086af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach binder.linkToDeath(deathRecipient, 0); 3096af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach mDeathRecipient = deathRecipient; 3106af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } catch (RemoteException e) { 3116af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach Log.e(TAG, "Unable to link deathRecipient for app id " + id); 3126af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } 3136af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } 3146af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach 3156af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach /** 3166af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach * Unlink death recipient 3176af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach */ 3186af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach void unlinkToDeath() { 3196af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach if (mDeathRecipient != null) { 3206af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach try { 3216af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach IBinder binder = ((IInterface)callback).asBinder(); 3226af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach binder.unlinkToDeath(mDeathRecipient,0); 3236af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } catch (NoSuchElementException e) { 3246af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach Log.e(TAG, "Unable to unlink deathRecipient for app id " + id); 3256af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } 3266af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } 3276af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } 328934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham 329934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham void queueCallback(CallbackInfo callbackInfo) { 330934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham congestionQueue.add(callbackInfo); 331934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham } 332934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham 333934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham CallbackInfo popQueuedCallback() { 334934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham if (congestionQueue.size() == 0) return null; 335934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham return congestionQueue.remove(0); 336934dee789c0c68607a704c5c31ae2e4b956dc227Prerepa Viswanadham } 33703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 33803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 33903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** Our internal application list */ 34003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta List<App> mApps = new ArrayList<App>(); 34103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 3428a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker /** Internal map to keep track of logging information by app name */ 3438a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker HashMap<String, ScanStats> mScanStats = new HashMap<String, ScanStats>(); 3448a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker 34503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** Internal list of connected devices **/ 34603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Set<Connection> mConnections = new HashSet<Connection>(); 34703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 34803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 34903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Add an entry to the application context list. 35003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 3518a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker void add(UUID uuid, T callback, Context context) { 3528a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker String appName = context.getPackageManager().getNameForUid( 3538a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker Binder.getCallingUid()); 3548a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker if (appName == null) { 3558a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker // Assign an app name if one isn't found 3568a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker appName = "Unknown App (UID: " + Binder.getCallingUid() + ")"; 3578a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker } 3586af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach synchronized (mApps) { 3598a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker mApps.add(new App(uuid, callback, appName)); 3608a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker ScanStats scanStats = mScanStats.get(appName); 3618a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker if (scanStats == null) { 3623122e5171ef26ff487f10826786606df848ca25eAjay Panicker scanStats = new ScanStats(appName); 3638a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker mScanStats.put(appName, scanStats); 3648a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker } 3658a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker scanStats.isRegistered = true; 3666af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } 36703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 36803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 36903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 3703f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach * Remove the context for a given UUID 3713f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach */ 3723f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach void remove(UUID uuid) { 3733f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach synchronized (mApps) { 3743f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach Iterator<App> i = mApps.iterator(); 3758a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker while (i.hasNext()) { 3763f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach App entry = i.next(); 3773f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach if (entry.uuid.equals(uuid)) { 3783f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach entry.unlinkToDeath(); 3798a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker mScanStats.get(entry.name).isRegistered = false; 3803f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach i.remove(); 3813f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach break; 3823f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach } 3833f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach } 3843f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach } 3853f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach } 3863f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach 3873f8164cd8c4bcce5e79770ee7c02fe00ba9581d5Andre Eisenbach /** 38803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Remove the context for a given application ID. 38903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 39003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta void remove(int id) { 3916af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach synchronized (mApps) { 3926af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach Iterator<App> i = mApps.iterator(); 3938a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker while (i.hasNext()) { 3946af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach App entry = i.next(); 3956af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach if (entry.id == id) { 3966af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach entry.unlinkToDeath(); 3978a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker mScanStats.get(entry.name).isRegistered = false; 3986af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach i.remove(); 3996af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach break; 4006af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } 40103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 40203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 40303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 40403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 40503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 40603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Add a new connection for a given application ID. 40703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 40803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta void addConnection(int id, int connId, String address) { 4096af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach synchronized (mConnections) { 4106af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach App entry = getById(id); 4116af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach if (entry != null){ 4126af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach mConnections.add(new Connection(connId, address, id)); 4136af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } 41403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 41503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 41603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 41703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 41803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Remove a connection with the given ID. 41903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 42003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta void removeConnection(int id, int connId) { 4216af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach synchronized (mConnections) { 4226af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach Iterator<Connection> i = mConnections.iterator(); 4238a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker while (i.hasNext()) { 4246af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach Connection connection = i.next(); 4256af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach if (connection.connId == connId) { 4266af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach i.remove(); 4276af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach break; 4286af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } 42903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 43003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 43103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 43203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 43303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 43403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Get an application context by ID. 43503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 43603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta App getById(int id) { 43703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Iterator<App> i = mApps.iterator(); 4388a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker while (i.hasNext()) { 43903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta App entry = i.next(); 44003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta if (entry.id == id) return entry; 44103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 44203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Log.e(TAG, "Context not found for ID " + id); 44303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta return null; 44403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 44503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 44603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 44703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Get an application context by UUID. 44803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 44903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta App getByUuid(UUID uuid) { 45003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Iterator<App> i = mApps.iterator(); 4518a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker while (i.hasNext()) { 45203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta App entry = i.next(); 45303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta if (entry.uuid.equals(uuid)) return entry; 45403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 45503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Log.e(TAG, "Context not found for UUID " + uuid); 45603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta return null; 45703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 45803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 45903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 4608a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker * Get an application context by the calling Apps name. 4618a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker */ 4628a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker App getByName(String name) { 4638a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker Iterator<App> i = mApps.iterator(); 4648a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker while (i.hasNext()) { 4658a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker App entry = i.next(); 4668a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker if (entry.name.equals(name)) return entry; 4678a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker } 4688a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker Log.e(TAG, "Context not found for name " + name); 4698a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker return null; 4708a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker } 4718a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker 4728a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker /** 4738a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker * Get Logging info by ID 4748a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker */ 4758a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker ScanStats getScanStatsById(int id) { 4768a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker App temp = getById(id); 4778a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker if (temp != null) { 4788a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker return mScanStats.get(temp.name); 4798a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker } 4808a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker return null; 4818a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker } 4828a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker 4838a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker /** 4843122e5171ef26ff487f10826786606df848ca25eAjay Panicker * Get Logging info by application name 4853122e5171ef26ff487f10826786606df848ca25eAjay Panicker */ 4863122e5171ef26ff487f10826786606df848ca25eAjay Panicker ScanStats getScanStatsByName(String name) { 4873122e5171ef26ff487f10826786606df848ca25eAjay Panicker return mScanStats.get(name); 4883122e5171ef26ff487f10826786606df848ca25eAjay Panicker } 4893122e5171ef26ff487f10826786606df848ca25eAjay Panicker 4903122e5171ef26ff487f10826786606df848ca25eAjay Panicker /** 49103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Get the device addresses for all connected devices 49203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 49303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Set<String> getConnectedDevices() { 49403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Set<String> addresses = new HashSet<String>(); 49503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Iterator<Connection> i = mConnections.iterator(); 4968a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker while (i.hasNext()) { 49703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Connection connection = i.next(); 49803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta addresses.add(connection.address); 49903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 50003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta return addresses; 50103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 50203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 50303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 50403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Get an application context by a connection ID. 50503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 50603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta App getByConnId(int connId) { 50703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Iterator<Connection> ii = mConnections.iterator(); 5088a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker while (ii.hasNext()) { 50903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Connection connection = ii.next(); 51003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta if (connection.connId == connId){ 51103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta return getById(connection.appId); 51203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 51303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 51403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta return null; 51503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 51603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 51703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 51803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Returns a connection ID for a given device address. 51903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 52003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Integer connIdByAddress(int id, String address) { 52103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta App entry = getById(id); 52203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta if (entry == null) return null; 52303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 52403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Iterator<Connection> i = mConnections.iterator(); 5258a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker while (i.hasNext()) { 52603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Connection connection = i.next(); 52703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta if (connection.address.equals(address) && connection.appId == id) 52803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta return connection.connId; 52903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 53003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta return null; 53103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 53203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 53303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 53403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Returns the device address for a given connection ID. 53503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 53603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta String addressByConnId(int connId) { 53703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Iterator<Connection> i = mConnections.iterator(); 5388a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker while (i.hasNext()) { 53903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Connection connection = i.next(); 54003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta if (connection.connId == connId) return connection.address; 54103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 54203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta return null; 54303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 54403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 54503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta List<Connection> getConnectionByApp(int appId) { 54603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta List<Connection> currentConnections = new ArrayList<Connection>(); 54703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Iterator<Connection> i = mConnections.iterator(); 5488a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker while (i.hasNext()) { 54903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta Connection connection = i.next(); 55003b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta if (connection.appId == appId) 55103b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta currentConnections.add(connection); 55203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 55303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta return currentConnections; 55403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 55503b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 55603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 55703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Erases all application context entries. 55803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 55903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta void clear() { 5606af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach synchronized (mApps) { 5616af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach Iterator<App> i = mApps.iterator(); 5628a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker while (i.hasNext()) { 5636af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach App entry = i.next(); 5646af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach entry.unlinkToDeath(); 5656af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach i.remove(); 5666af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } 5676af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } 5686af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach 5696af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach synchronized (mConnections) { 5706af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach mConnections.clear(); 5716af1f25031e4378efb1a4fc286974c1038a357baAndre Eisenbach } 57203b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 57303b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 57403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta /** 575f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora * Returns connect device map with addr and appid 576f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora */ 577f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora Map<Integer, String> getConnectedMap(){ 578f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora Map<Integer, String> connectedmap = new HashMap<Integer, String>(); 579f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora for(Connection conn: mConnections){ 580f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora connectedmap.put(conn.appId, conn.address); 581f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora } 582f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora return connectedmap; 583f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora } 584f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora 585f19f1ac64a5fefb248ab15b918d009b926c99ddeNitin Arora /** 58603b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta * Logs debug information. 58703b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta */ 588a02de6484f9b6cac6b8c811edae11be55746b555Andre Eisenbach void dump(StringBuilder sb) { 5898a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker sb.append(" Entries: " + mScanStats.size() + "\n\n"); 5908a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker 5915c07523b0b5d32176d7ff3ab28555123123261ddAjay Panicker Iterator<Map.Entry<String,ScanStats>> it = mScanStats.entrySet().iterator(); 5925c07523b0b5d32176d7ff3ab28555123123261ddAjay Panicker while (it.hasNext()) { 5935c07523b0b5d32176d7ff3ab28555123123261ddAjay Panicker Map.Entry<String, ScanStats> entry = it.next(); 59403b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta 5958a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker String name = entry.getKey(); 5968a0bc0a61e97f8923cb362e1dbb7ff66ffe51507Ajay Panicker ScanStats scanStats = entry.getValue(); 597a0ff3af53c2299fc20d4c1cc2bcced4a0d2ff5c9Ajay Panicker scanStats.dumpToString(sb); 59803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 59903b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta } 6003122e5171ef26ff487f10826786606df848ca25eAjay Panicker 6013122e5171ef26ff487f10826786606df848ca25eAjay Panicker void dumpProto(BluetoothProto.BluetoothLog proto) { 6023122e5171ef26ff487f10826786606df848ca25eAjay Panicker synchronized(mScanEvents) { 6033122e5171ef26ff487f10826786606df848ca25eAjay Panicker for (BluetoothProto.ScanEvent event : mScanEvents) { 6043122e5171ef26ff487f10826786606df848ca25eAjay Panicker proto.addScanEvent(event); 6053122e5171ef26ff487f10826786606df848ca25eAjay Panicker } 6063122e5171ef26ff487f10826786606df848ca25eAjay Panicker } 6073122e5171ef26ff487f10826786606df848ca25eAjay Panicker } 60803b8386de26ba6500af2d66687bff9b01f2cbbd7Ganesh Ganapathi Batta} 609