Loading src/com/android/bluetooth/gatt/AppScanStats.java +45 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,9 @@ import com.android.bluetooth.btservice.BluetoothProto; class LastScan { long duration; long suspendDuration; long suspendStartTime; boolean isSuspended; long timestamp; boolean opportunistic; boolean timeout; Loading @@ -67,6 +70,9 @@ import com.android.bluetooth.btservice.BluetoothProto; this.filtered = filtered; this.results = 0; this.scannerId = scannerId; this.suspendDuration = 0; this.suspendStartTime = 0; this.isSuspended = false; } } Loading @@ -90,6 +96,7 @@ import com.android.bluetooth.btservice.BluetoothProto; long maxScanTime = 0; long mScanStartTime = 0; long mTotalScanTime = 0; long mTotalSuspendTime = 0; List<LastScan> lastScans = new ArrayList<LastScan>(NUM_SCAN_DURATIONS_KEPT); HashMap<Integer, LastScan> ongoingScans = new HashMap<Integer, LastScan>(); long startTime = 0; Loading Loading @@ -168,6 +175,10 @@ import com.android.bluetooth.btservice.BluetoothProto; stopTime = SystemClock.elapsedRealtime(); long scanDuration = stopTime - scan.timestamp; scan.duration = scanDuration; if (scan.isSuspended) { scan.suspendDuration += stopTime - scan.suspendStartTime; mTotalSuspendTime += scan.suspendDuration; } ongoingScans.remove(scannerId); if (lastScans.size() >= NUM_SCAN_DURATIONS_KEPT) { lastScans.remove(0); Loading @@ -194,6 +205,26 @@ import com.android.bluetooth.btservice.BluetoothProto; } } synchronized void recordScanSuspend(int scannerId) { LastScan scan = getScanFromScannerId(scannerId); if (scan == null || scan.isSuspended) { return; } scan.suspendStartTime = SystemClock.elapsedRealtime(); scan.isSuspended = true; } synchronized void recordScanResume(int scannerId) { LastScan scan = getScanFromScannerId(scannerId); if (scan == null || !scan.isSuspended) { return; } scan.isSuspended = false; stopTime = SystemClock.elapsedRealtime(); scan.suspendDuration += stopTime - scan.suspendStartTime; mTotalSuspendTime += scan.suspendDuration; } synchronized void setScanTimeout(int scannerId) { if (!isScanning()) return; Loading Loading @@ -281,6 +312,9 @@ import com.android.bluetooth.btservice.BluetoothProto; maxScan + " / " + avgScan + " / " + totalScanTime + "\n"); if (mTotalSuspendTime != 0) { sb.append(" Total time suspended : " + mTotalSuspendTime + "ms\n"); } sb.append(" Total number of results : " + results + "\n"); Loading @@ -301,6 +335,10 @@ import com.android.bluetooth.btservice.BluetoothProto; sb.append(scan.results + " results"); sb.append(" (" + scan.scannerId + ")"); sb.append("\n"); if (scan.suspendDuration != 0) { sb.append(" └" + " Suspended Time: " + scan.suspendDuration + "ms\n"); } } } Loading @@ -315,9 +353,16 @@ import com.android.bluetooth.btservice.BluetoothProto; if (scan.background) sb.append("Back "); if (scan.timeout) sb.append("Forced "); if (scan.filtered) sb.append("Filter "); if (scan.isSuspended) sb.append("Suspended "); sb.append(scan.results + " results"); sb.append(" (" + scan.scannerId + ")"); sb.append("\n"); if (scan.suspendStartTime != 0) { long duration = scan.suspendDuration + (scan.isSuspended ? (elapsedRt - scan.suspendStartTime) : 0); sb.append(" └" + " Suspended Time: " + duration + "ms\n"); } } } Loading src/com/android/bluetooth/gatt/ScanManager.java +90 −1 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; Loading @@ -34,6 +35,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.util.Log; import android.view.Display; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; Loading Loading @@ -69,7 +71,8 @@ public class ScanManager { private static final int MSG_STOP_BLE_SCAN = 1; private static final int MSG_FLUSH_BATCH_RESULTS = 2; private static final int MSG_SCAN_TIMEOUT = 3; private static final int MSG_SUSPEND_SCANS = 4; private static final int MSG_RESUME_SCANS = 5; private static final String ACTION_REFRESH_BATCHED_SCAN = "com.android.bluetooth.gatt.REFRESH_BATCHED_SCAN"; Loading @@ -89,15 +92,22 @@ public class ScanManager { private Set<ScanClient> mRegularScanClients; private Set<ScanClient> mBatchClients; private Set<ScanClient> mSuspendedScanClients; private CountDownLatch mLatch; private DisplayManager mDm; ScanManager(GattService service) { mRegularScanClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); mBatchClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); mSuspendedScanClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); mService = service; mScanNative = new ScanNative(); curUsedTrackableAdvertisements = 0; mDm = (DisplayManager) mService.getSystemService(Context.DISPLAY_SERVICE); mDm.registerDisplayListener(mDisplayListener, null); } void start() { Loading @@ -109,6 +119,7 @@ public class ScanManager { void cleanup() { mRegularScanClients.clear(); mBatchClients.clear(); mSuspendedScanClients.clear(); mScanNative.cleanup(); if (mHandler != null) { Loading Loading @@ -215,6 +226,12 @@ public class ScanManager { case MSG_SCAN_TIMEOUT: mScanNative.regularScanTimeout(client); break; case MSG_SUSPEND_SCANS: handleSuspendScans(); break; case MSG_RESUME_SCANS: handleResumeScans(); break; default: // Shouldn't happen. Log.e(TAG, "received an unkown message : " + msg.what); Loading @@ -223,6 +240,7 @@ public class ScanManager { void handleStartScan(ScanClient client) { Utils.enforceAdminPermission(mService); boolean isFiltered = (client.filters != null) && !client.filters.isEmpty(); if (DBG) Log.d(TAG, "handling starting scan"); if (!isScanSupported(client)) { Loading @@ -234,6 +252,15 @@ public class ScanManager { Log.e(TAG, "Scan already started"); return; } if (!mScanNative.isOpportunisticScanClient(client) && !isScreenOn() && !isFiltered) { Log.e(TAG, "Cannot start unfiltered scan in screen-off. This scan will be resumed later: " + client.scannerId); mSuspendedScanClients.add(client); return; } // Begin scan operations. if (isBatchClient(client)) { mBatchClients.add(client); Loading @@ -258,6 +285,10 @@ public class ScanManager { Utils.enforceAdminPermission(mService); if (client == null) return; if (mSuspendedScanClients.contains(client)) { mSuspendedScanClients.remove(client); } if (mRegularScanClients.contains(client)) { mScanNative.stopRegularScan(client); Loading Loading @@ -305,6 +336,30 @@ public class ScanManager { return settings.getCallbackType() == ScanSettings.CALLBACK_TYPE_ALL_MATCHES && settings.getReportDelayMillis() == 0; } void handleSuspendScans() { for (ScanClient client : mRegularScanClients) { if (!mScanNative.isOpportunisticScanClient(client) && (client.filters == null || client.filters.isEmpty())) { /*Suspend unfiltered scans*/ if (client.stats != null) { client.stats.recordScanSuspend(client.scannerId); } handleStopScan(client); mSuspendedScanClients.add(client); } } } void handleResumeScans() { for (ScanClient client : mSuspendedScanClients) { if (client.stats != null) { client.stats.recordScanResume(client.scannerId); } handleStartScan(client); } mSuspendedScanClients.clear(); } } /** Loading Loading @@ -1163,4 +1218,38 @@ public class ScanManager { private native void gattClientReadScanReportsNative(int client_if, int scan_type); } private boolean isScreenOn() { Display[] displays = mDm.getDisplays(); if (displays == null) { return false; } for (Display display : displays) { if (display.getState() == Display.STATE_ON) { return true; } } return false; } private final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() { @Override public void onDisplayAdded(int displayId) {} @Override public void onDisplayRemoved(int displayId) {} @Override public void onDisplayChanged(int displayId) { if (isScreenOn()) { sendMessage(MSG_RESUME_SCANS, null); } else { sendMessage(MSG_SUSPEND_SCANS, null); } } }; } Loading
src/com/android/bluetooth/gatt/AppScanStats.java +45 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,9 @@ import com.android.bluetooth.btservice.BluetoothProto; class LastScan { long duration; long suspendDuration; long suspendStartTime; boolean isSuspended; long timestamp; boolean opportunistic; boolean timeout; Loading @@ -67,6 +70,9 @@ import com.android.bluetooth.btservice.BluetoothProto; this.filtered = filtered; this.results = 0; this.scannerId = scannerId; this.suspendDuration = 0; this.suspendStartTime = 0; this.isSuspended = false; } } Loading @@ -90,6 +96,7 @@ import com.android.bluetooth.btservice.BluetoothProto; long maxScanTime = 0; long mScanStartTime = 0; long mTotalScanTime = 0; long mTotalSuspendTime = 0; List<LastScan> lastScans = new ArrayList<LastScan>(NUM_SCAN_DURATIONS_KEPT); HashMap<Integer, LastScan> ongoingScans = new HashMap<Integer, LastScan>(); long startTime = 0; Loading Loading @@ -168,6 +175,10 @@ import com.android.bluetooth.btservice.BluetoothProto; stopTime = SystemClock.elapsedRealtime(); long scanDuration = stopTime - scan.timestamp; scan.duration = scanDuration; if (scan.isSuspended) { scan.suspendDuration += stopTime - scan.suspendStartTime; mTotalSuspendTime += scan.suspendDuration; } ongoingScans.remove(scannerId); if (lastScans.size() >= NUM_SCAN_DURATIONS_KEPT) { lastScans.remove(0); Loading @@ -194,6 +205,26 @@ import com.android.bluetooth.btservice.BluetoothProto; } } synchronized void recordScanSuspend(int scannerId) { LastScan scan = getScanFromScannerId(scannerId); if (scan == null || scan.isSuspended) { return; } scan.suspendStartTime = SystemClock.elapsedRealtime(); scan.isSuspended = true; } synchronized void recordScanResume(int scannerId) { LastScan scan = getScanFromScannerId(scannerId); if (scan == null || !scan.isSuspended) { return; } scan.isSuspended = false; stopTime = SystemClock.elapsedRealtime(); scan.suspendDuration += stopTime - scan.suspendStartTime; mTotalSuspendTime += scan.suspendDuration; } synchronized void setScanTimeout(int scannerId) { if (!isScanning()) return; Loading Loading @@ -281,6 +312,9 @@ import com.android.bluetooth.btservice.BluetoothProto; maxScan + " / " + avgScan + " / " + totalScanTime + "\n"); if (mTotalSuspendTime != 0) { sb.append(" Total time suspended : " + mTotalSuspendTime + "ms\n"); } sb.append(" Total number of results : " + results + "\n"); Loading @@ -301,6 +335,10 @@ import com.android.bluetooth.btservice.BluetoothProto; sb.append(scan.results + " results"); sb.append(" (" + scan.scannerId + ")"); sb.append("\n"); if (scan.suspendDuration != 0) { sb.append(" └" + " Suspended Time: " + scan.suspendDuration + "ms\n"); } } } Loading @@ -315,9 +353,16 @@ import com.android.bluetooth.btservice.BluetoothProto; if (scan.background) sb.append("Back "); if (scan.timeout) sb.append("Forced "); if (scan.filtered) sb.append("Filter "); if (scan.isSuspended) sb.append("Suspended "); sb.append(scan.results + " results"); sb.append(" (" + scan.scannerId + ")"); sb.append("\n"); if (scan.suspendStartTime != 0) { long duration = scan.suspendDuration + (scan.isSuspended ? (elapsedRt - scan.suspendStartTime) : 0); sb.append(" └" + " Suspended Time: " + duration + "ms\n"); } } } Loading
src/com/android/bluetooth/gatt/ScanManager.java +90 −1 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.hardware.display.DisplayManager; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; Loading @@ -34,6 +35,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.util.Log; import android.view.Display; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; Loading Loading @@ -69,7 +71,8 @@ public class ScanManager { private static final int MSG_STOP_BLE_SCAN = 1; private static final int MSG_FLUSH_BATCH_RESULTS = 2; private static final int MSG_SCAN_TIMEOUT = 3; private static final int MSG_SUSPEND_SCANS = 4; private static final int MSG_RESUME_SCANS = 5; private static final String ACTION_REFRESH_BATCHED_SCAN = "com.android.bluetooth.gatt.REFRESH_BATCHED_SCAN"; Loading @@ -89,15 +92,22 @@ public class ScanManager { private Set<ScanClient> mRegularScanClients; private Set<ScanClient> mBatchClients; private Set<ScanClient> mSuspendedScanClients; private CountDownLatch mLatch; private DisplayManager mDm; ScanManager(GattService service) { mRegularScanClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); mBatchClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); mSuspendedScanClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); mService = service; mScanNative = new ScanNative(); curUsedTrackableAdvertisements = 0; mDm = (DisplayManager) mService.getSystemService(Context.DISPLAY_SERVICE); mDm.registerDisplayListener(mDisplayListener, null); } void start() { Loading @@ -109,6 +119,7 @@ public class ScanManager { void cleanup() { mRegularScanClients.clear(); mBatchClients.clear(); mSuspendedScanClients.clear(); mScanNative.cleanup(); if (mHandler != null) { Loading Loading @@ -215,6 +226,12 @@ public class ScanManager { case MSG_SCAN_TIMEOUT: mScanNative.regularScanTimeout(client); break; case MSG_SUSPEND_SCANS: handleSuspendScans(); break; case MSG_RESUME_SCANS: handleResumeScans(); break; default: // Shouldn't happen. Log.e(TAG, "received an unkown message : " + msg.what); Loading @@ -223,6 +240,7 @@ public class ScanManager { void handleStartScan(ScanClient client) { Utils.enforceAdminPermission(mService); boolean isFiltered = (client.filters != null) && !client.filters.isEmpty(); if (DBG) Log.d(TAG, "handling starting scan"); if (!isScanSupported(client)) { Loading @@ -234,6 +252,15 @@ public class ScanManager { Log.e(TAG, "Scan already started"); return; } if (!mScanNative.isOpportunisticScanClient(client) && !isScreenOn() && !isFiltered) { Log.e(TAG, "Cannot start unfiltered scan in screen-off. This scan will be resumed later: " + client.scannerId); mSuspendedScanClients.add(client); return; } // Begin scan operations. if (isBatchClient(client)) { mBatchClients.add(client); Loading @@ -258,6 +285,10 @@ public class ScanManager { Utils.enforceAdminPermission(mService); if (client == null) return; if (mSuspendedScanClients.contains(client)) { mSuspendedScanClients.remove(client); } if (mRegularScanClients.contains(client)) { mScanNative.stopRegularScan(client); Loading Loading @@ -305,6 +336,30 @@ public class ScanManager { return settings.getCallbackType() == ScanSettings.CALLBACK_TYPE_ALL_MATCHES && settings.getReportDelayMillis() == 0; } void handleSuspendScans() { for (ScanClient client : mRegularScanClients) { if (!mScanNative.isOpportunisticScanClient(client) && (client.filters == null || client.filters.isEmpty())) { /*Suspend unfiltered scans*/ if (client.stats != null) { client.stats.recordScanSuspend(client.scannerId); } handleStopScan(client); mSuspendedScanClients.add(client); } } } void handleResumeScans() { for (ScanClient client : mSuspendedScanClients) { if (client.stats != null) { client.stats.recordScanResume(client.scannerId); } handleStartScan(client); } mSuspendedScanClients.clear(); } } /** Loading Loading @@ -1163,4 +1218,38 @@ public class ScanManager { private native void gattClientReadScanReportsNative(int client_if, int scan_type); } private boolean isScreenOn() { Display[] displays = mDm.getDisplays(); if (displays == null) { return false; } for (Display display : displays) { if (display.getState() == Display.STATE_ON) { return true; } } return false; } private final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() { @Override public void onDisplayAdded(int displayId) {} @Override public void onDisplayRemoved(int displayId) {} @Override public void onDisplayChanged(int displayId) { if (isScreenOn()) { sendMessage(MSG_RESUME_SCANS, null); } else { sendMessage(MSG_SUSPEND_SCANS, null); } } }; }