• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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