1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.bluetooth.le_scan; 18 19 import android.annotation.Nullable; 20 import android.os.RemoteException; 21 import android.util.Log; 22 23 import com.android.bluetooth.gatt.FilterParams; 24 import com.android.internal.annotations.VisibleForTesting; 25 26 import java.util.concurrent.CountDownLatch; 27 import java.util.concurrent.TimeUnit; 28 29 /** BLE Scan Native Interface to/from JNI. */ 30 public class ScanNativeInterface { 31 private static final String TAG = ScanNativeInterface.class.getSimpleName(); 32 33 private static ScanNativeInterface sInterface; 34 35 private CountDownLatch mLatch = new CountDownLatch(1); 36 @Nullable private ScanController mScanController; 37 ScanNativeInterface()38 private ScanNativeInterface() {} 39 40 /** 41 * This class is a singleton because native library should only be loaded once 42 * 43 * @return default instance 44 */ getInstance()45 public static ScanNativeInterface getInstance() { 46 synchronized (ScanNativeInterface.class) { 47 if (sInterface == null) { 48 sInterface = new ScanNativeInterface(); 49 } 50 } 51 return sInterface; 52 } 53 54 /** Set singleton instance. */ 55 @VisibleForTesting setInstance(ScanNativeInterface instance)56 public static void setInstance(ScanNativeInterface instance) { 57 synchronized (ScanNativeInterface.class) { 58 sInterface = instance; 59 } 60 } 61 init(ScanController scanController)62 void init(ScanController scanController) { 63 mScanController = scanController; 64 initializeNative(); 65 } 66 cleanup()67 void cleanup() { 68 cleanupNative(); 69 } 70 71 /* Native methods */ initializeNative()72 private native void initializeNative(); 73 cleanupNative()74 private native void cleanupNative(); 75 76 /************************** Regular scan related native methods **************************/ registerScannerNative(long appUuidLsb, long appUuidMsb)77 private native void registerScannerNative(long appUuidLsb, long appUuidMsb); 78 unregisterScannerNative(int scannerId)79 private native void unregisterScannerNative(int scannerId); 80 gattClientScanNative(boolean start)81 private native void gattClientScanNative(boolean start); 82 gattSetScanParametersNative( int clientIf1m, int scanInterval1m, int scanWindow1m, int clientIfCoded, int scanIntervalCoded, int scanWindowCoded, int scanPhy)83 private native void gattSetScanParametersNative( 84 int clientIf1m, 85 int scanInterval1m, 86 int scanWindow1m, 87 int clientIfCoded, 88 int scanIntervalCoded, 89 int scanWindowCoded, 90 int scanPhy); 91 92 /************************** Filter related native methods ********************************/ gattClientScanFilterAddNative( int clientId, ScanFilterQueue.Entry[] entries, int filterIndex)93 private native void gattClientScanFilterAddNative( 94 int clientId, ScanFilterQueue.Entry[] entries, int filterIndex); 95 gattClientScanFilterParamAddNative(FilterParams filtValue)96 private native void gattClientScanFilterParamAddNative(FilterParams filtValue); 97 98 // Note this effectively remove scan filters for ALL clients. gattClientScanFilterParamClearAllNative(int clientIf)99 private native void gattClientScanFilterParamClearAllNative(int clientIf); 100 gattClientScanFilterParamDeleteNative(int clientIf, int filtIndex)101 private native void gattClientScanFilterParamDeleteNative(int clientIf, int filtIndex); 102 gattClientScanFilterClearNative(int clientIf, int filterIndex)103 private native void gattClientScanFilterClearNative(int clientIf, int filterIndex); 104 gattClientScanFilterEnableNative(int clientIf, boolean enable)105 private native void gattClientScanFilterEnableNative(int clientIf, boolean enable); 106 107 /************************** MSFT scan related native methods *****************************/ gattClientIsMsftSupportedNative()108 private native boolean gattClientIsMsftSupportedNative(); 109 gattClientMsftAdvMonitorAddNative( MsftAdvMonitor.Monitor msft_adv_monitor, MsftAdvMonitor.Pattern[] msft_adv_monitor_patterns, MsftAdvMonitor.Address msft_adv_monitor_address, int filter_index)110 private native void gattClientMsftAdvMonitorAddNative( 111 MsftAdvMonitor.Monitor msft_adv_monitor, 112 MsftAdvMonitor.Pattern[] msft_adv_monitor_patterns, 113 MsftAdvMonitor.Address msft_adv_monitor_address, 114 int filter_index); 115 gattClientMsftAdvMonitorRemoveNative(int filter_index, int monitor_handle)116 private native void gattClientMsftAdvMonitorRemoveNative(int filter_index, int monitor_handle); 117 gattClientMsftAdvMonitorEnableNative(boolean enable)118 private native void gattClientMsftAdvMonitorEnableNative(boolean enable); 119 120 /************************** Batch related native methods *********************************/ gattClientConfigBatchScanStorageNative( int clientIf, int maxFullReportsPercent, int maxTruncatedReportsPercent, int notifyThresholdPercent)121 private native void gattClientConfigBatchScanStorageNative( 122 int clientIf, 123 int maxFullReportsPercent, 124 int maxTruncatedReportsPercent, 125 int notifyThresholdPercent); 126 gattClientStartBatchScanNative( int clientIf, int scanMode, int scanIntervalUnit, int scanWindowUnit, int addressType, int discardRule)127 private native void gattClientStartBatchScanNative( 128 int clientIf, 129 int scanMode, 130 int scanIntervalUnit, 131 int scanWindowUnit, 132 int addressType, 133 int discardRule); 134 gattClientStopBatchScanNative(int clientIf)135 private native void gattClientStopBatchScanNative(int clientIf); 136 gattClientReadScanReportsNative(int clientIf, int scanType)137 private native void gattClientReadScanReportsNative(int clientIf, int scanType); 138 139 /** Register BLE scanner */ registerScanner(long appUuidLsb, long appUuidMsb)140 public void registerScanner(long appUuidLsb, long appUuidMsb) { 141 registerScannerNative(appUuidLsb, appUuidMsb); 142 } 143 144 /** Unregister BLE scanner */ unregisterScanner(int scannerId)145 public void unregisterScanner(int scannerId) { 146 unregisterScannerNative(scannerId); 147 } 148 149 /** Enable/disable BLE scan */ gattClientScan(boolean start)150 public void gattClientScan(boolean start) { 151 gattClientScanNative(start); 152 } 153 154 /** Configure BLE scan parameters */ gattSetScanParameters( int clientIf1m, int scanInterval1m, int scanWindow1m, int clientIfCoded, int scanIntervalCoded, int scanWindowCoded, int scanPhy)155 public void gattSetScanParameters( 156 int clientIf1m, 157 int scanInterval1m, 158 int scanWindow1m, 159 int clientIfCoded, 160 int scanIntervalCoded, 161 int scanWindowCoded, 162 int scanPhy) { 163 gattSetScanParametersNative( 164 clientIf1m, 165 scanInterval1m, 166 scanWindow1m, 167 clientIfCoded, 168 scanIntervalCoded, 169 scanWindowCoded, 170 scanPhy); 171 } 172 173 /** Add BLE scan filter */ gattClientScanFilterAdd( int clientId, ScanFilterQueue.Entry[] entries, int filterIndex)174 public void gattClientScanFilterAdd( 175 int clientId, ScanFilterQueue.Entry[] entries, int filterIndex) { 176 gattClientScanFilterAddNative(clientId, entries, filterIndex); 177 } 178 179 /** Add BLE scan filter parameters */ gattClientScanFilterParamAdd(FilterParams filtValue)180 public void gattClientScanFilterParamAdd(FilterParams filtValue) { 181 gattClientScanFilterParamAddNative(filtValue); 182 } 183 184 /** Clear all BLE scan filter parameters */ 185 // Note this effectively remove scan filters for ALL clients. gattClientScanFilterParamClearAll(int clientIf)186 public void gattClientScanFilterParamClearAll(int clientIf) { 187 gattClientScanFilterParamClearAllNative(clientIf); 188 } 189 190 /** Delete BLE scan filter parameters */ gattClientScanFilterParamDelete(int clientIf, int filtIndex)191 public void gattClientScanFilterParamDelete(int clientIf, int filtIndex) { 192 gattClientScanFilterParamDeleteNative(clientIf, filtIndex); 193 } 194 195 /** Clear BLE scan filter */ gattClientScanFilterClear(int clientIf, int filterIndex)196 public void gattClientScanFilterClear(int clientIf, int filterIndex) { 197 gattClientScanFilterClearNative(clientIf, filterIndex); 198 } 199 200 /** Enable/disable BLE scan filter */ gattClientScanFilterEnable(int clientIf, boolean enable)201 public void gattClientScanFilterEnable(int clientIf, boolean enable) { 202 gattClientScanFilterEnableNative(clientIf, enable); 203 } 204 205 /** Check if MSFT HCI extension is supported */ gattClientIsMsftSupported()206 public boolean gattClientIsMsftSupported() { 207 return gattClientIsMsftSupportedNative(); 208 } 209 210 /** Add a MSFT Advertisement Monitor */ gattClientMsftAdvMonitorAdd( MsftAdvMonitor.Monitor msft_adv_monitor, MsftAdvMonitor.Pattern[] msft_adv_monitor_patterns, MsftAdvMonitor.Address msft_adv_monitor_address, int filter_index)211 public void gattClientMsftAdvMonitorAdd( 212 MsftAdvMonitor.Monitor msft_adv_monitor, 213 MsftAdvMonitor.Pattern[] msft_adv_monitor_patterns, 214 MsftAdvMonitor.Address msft_adv_monitor_address, 215 int filter_index) { 216 gattClientMsftAdvMonitorAddNative( 217 msft_adv_monitor, 218 msft_adv_monitor_patterns, 219 msft_adv_monitor_address, 220 filter_index); 221 } 222 223 /** Remove a MSFT Advertisement Monitor */ gattClientMsftAdvMonitorRemove(int filter_index)224 public void gattClientMsftAdvMonitorRemove(int filter_index) { 225 int monitor_handle = mScanController.msftMonitorHandleFromFilterIndex(filter_index); 226 if (monitor_handle < 0) return; 227 gattClientMsftAdvMonitorRemoveNative(filter_index, monitor_handle); 228 } 229 230 /** Enable a MSFT Advertisement Monitor */ gattClientMsftAdvMonitorEnable(boolean enable)231 public void gattClientMsftAdvMonitorEnable(boolean enable) { 232 gattClientMsftAdvMonitorEnableNative(enable); 233 } 234 235 /** Configure BLE batch scan storage */ gattClientConfigBatchScanStorage( int clientIf, int maxFullReportsPercent, int maxTruncatedReportsPercent, int notifyThresholdPercent)236 public void gattClientConfigBatchScanStorage( 237 int clientIf, 238 int maxFullReportsPercent, 239 int maxTruncatedReportsPercent, 240 int notifyThresholdPercent) { 241 gattClientConfigBatchScanStorageNative( 242 clientIf, 243 maxFullReportsPercent, 244 maxTruncatedReportsPercent, 245 notifyThresholdPercent); 246 } 247 248 /** Enable BLE batch scan with the parameters */ gattClientStartBatchScan( int clientIf, int scanMode, int scanIntervalUnit, int scanWindowUnit, int addressType, int discardRule)249 public void gattClientStartBatchScan( 250 int clientIf, 251 int scanMode, 252 int scanIntervalUnit, 253 int scanWindowUnit, 254 int addressType, 255 int discardRule) { 256 gattClientStartBatchScanNative( 257 clientIf, scanMode, scanIntervalUnit, scanWindowUnit, addressType, discardRule); 258 } 259 260 /** Disable BLE batch scan */ gattClientStopBatchScan(int clientIf)261 public void gattClientStopBatchScan(int clientIf) { 262 gattClientStopBatchScanNative(clientIf); 263 } 264 265 /** Read BLE batch scan reports */ gattClientReadScanReports(int clientIf, int scanType)266 public void gattClientReadScanReports(int clientIf, int scanType) { 267 gattClientReadScanReportsNative(clientIf, scanType); 268 } 269 callbackDone()270 void callbackDone() { 271 mLatch.countDown(); 272 } 273 resetCountDownLatch()274 void resetCountDownLatch() { 275 mLatch = new CountDownLatch(1); 276 } 277 278 // Returns true if mLatch reaches 0, false if timeout or interrupted. waitForCallback(int timeoutMs)279 boolean waitForCallback(int timeoutMs) { 280 try { 281 return mLatch.await(timeoutMs, TimeUnit.MILLISECONDS); 282 } catch (InterruptedException e) { 283 return false; 284 } 285 } 286 287 /* Callbacks */ 288 onScanResult( int eventType, int addressType, String address, int primaryPhy, int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt, byte[] advData, String originalAddress)289 void onScanResult( 290 int eventType, 291 int addressType, 292 String address, 293 int primaryPhy, 294 int secondaryPhy, 295 int advertisingSid, 296 int txPower, 297 int rssi, 298 int periodicAdvInt, 299 byte[] advData, 300 String originalAddress) { 301 if (mScanController == null) { 302 Log.e(TAG, "ScanController is null!"); 303 return; 304 } 305 mScanController.onScanResult( 306 eventType, 307 addressType, 308 address, 309 primaryPhy, 310 secondaryPhy, 311 advertisingSid, 312 txPower, 313 rssi, 314 periodicAdvInt, 315 advData, 316 originalAddress); 317 } 318 onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb)319 void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) 320 throws RemoteException { 321 if (mScanController == null) { 322 Log.e(TAG, "ScanController is null!"); 323 return; 324 } 325 mScanController.onScannerRegistered(status, scannerId, uuidLsb, uuidMsb); 326 } 327 onScanFilterEnableDisabled(int action, int status, int clientIf)328 void onScanFilterEnableDisabled(int action, int status, int clientIf) { 329 if (mScanController == null) { 330 Log.e(TAG, "ScanController is null!"); 331 return; 332 } 333 mScanController.onScanFilterEnableDisabled(action, status, clientIf); 334 } 335 onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace)336 void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { 337 if (mScanController == null) { 338 Log.e(TAG, "ScanController is null!"); 339 return; 340 } 341 mScanController.onScanFilterParamsConfigured(action, status, clientIf, availableSpace); 342 } 343 onScanFilterConfig( int action, int status, int clientIf, int filterType, int availableSpace)344 void onScanFilterConfig( 345 int action, int status, int clientIf, int filterType, int availableSpace) { 346 if (mScanController == null) { 347 Log.e(TAG, "ScanController is null!"); 348 return; 349 } 350 mScanController.onScanFilterConfig(action, status, clientIf, filterType, availableSpace); 351 } 352 onBatchScanStorageConfigured(int status, int clientIf)353 void onBatchScanStorageConfigured(int status, int clientIf) { 354 if (mScanController == null) { 355 Log.e(TAG, "ScanController is null!"); 356 return; 357 } 358 mScanController.onBatchScanStorageConfigured(status, clientIf); 359 } 360 onBatchScanStartStopped(int startStopAction, int status, int clientIf)361 void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { 362 if (mScanController == null) { 363 Log.e(TAG, "ScanController is null!"); 364 return; 365 } 366 mScanController.onBatchScanStartStopped(startStopAction, status, clientIf); 367 } 368 onBatchScanReports( int status, int scannerId, int reportType, int numRecords, byte[] recordData)369 void onBatchScanReports( 370 int status, int scannerId, int reportType, int numRecords, byte[] recordData) 371 throws RemoteException { 372 if (mScanController == null) { 373 Log.e(TAG, "ScanController is null!"); 374 return; 375 } 376 mScanController.onBatchScanReports(status, scannerId, reportType, numRecords, recordData); 377 } 378 onBatchScanThresholdCrossed(int clientIf)379 void onBatchScanThresholdCrossed(int clientIf) { 380 if (mScanController == null) { 381 Log.e(TAG, "ScanController is null!"); 382 return; 383 } 384 mScanController.onBatchScanThresholdCrossed(clientIf); 385 } 386 387 @Nullable createOnTrackAdvFoundLostObject( int clientIf, int advPacketLen, byte[] advPacket, int scanResponseLen, byte[] scanResponse, int filtIndex, int advState, int advInfoPresent, String address, int addrType, int txPower, int rssiValue, int timeStamp)388 AdvtFilterOnFoundOnLostInfo createOnTrackAdvFoundLostObject( 389 int clientIf, 390 int advPacketLen, 391 byte[] advPacket, 392 int scanResponseLen, 393 byte[] scanResponse, 394 int filtIndex, 395 int advState, 396 int advInfoPresent, 397 String address, 398 int addrType, 399 int txPower, 400 int rssiValue, 401 int timeStamp) { 402 if (mScanController == null) { 403 Log.e(TAG, "ScanController is null!"); 404 return null; 405 } 406 return mScanController.createOnTrackAdvFoundLostObject( 407 clientIf, 408 advPacketLen, 409 advPacket, 410 scanResponseLen, 411 scanResponse, 412 filtIndex, 413 advState, 414 advInfoPresent, 415 address, 416 addrType, 417 txPower, 418 rssiValue, 419 timeStamp); 420 } 421 onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo)422 void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { 423 if (mScanController == null) { 424 Log.e(TAG, "ScanController is null!"); 425 return; 426 } 427 mScanController.onTrackAdvFoundLost(trackingInfo); 428 } 429 onScanParamSetupCompleted(int status, int scannerId)430 void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { 431 if (mScanController == null) { 432 Log.e(TAG, "ScanController is null!"); 433 return; 434 } 435 mScanController.onScanParamSetupCompleted(status, scannerId); 436 } 437 onMsftAdvMonitorAdd(int filter_index, int monitor_handle, int status)438 void onMsftAdvMonitorAdd(int filter_index, int monitor_handle, int status) { 439 if (mScanController == null) { 440 Log.e(TAG, "ScanController is null!"); 441 return; 442 } 443 mScanController.onMsftAdvMonitorAdd(filter_index, monitor_handle, status); 444 } 445 onMsftAdvMonitorRemove(int filter_index, int status)446 void onMsftAdvMonitorRemove(int filter_index, int status) { 447 if (mScanController == null) { 448 Log.e(TAG, "ScanController is null!"); 449 return; 450 } 451 mScanController.onMsftAdvMonitorRemove(filter_index, status); 452 } 453 onMsftAdvMonitorEnable(int status)454 void onMsftAdvMonitorEnable(int status) { 455 if (mScanController == null) { 456 Log.e(TAG, "ScanController is null!"); 457 return; 458 } 459 mScanController.onMsftAdvMonitorEnable(status); 460 } 461 } 462