• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 
17 package com.googlecode.android_scripting.facade.bluetooth;
18 
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.UUID;
23 import java.util.concurrent.Callable;
24 
25 import android.app.Service;
26 import android.bluetooth.BluetoothAdapter;
27 import android.bluetooth.BluetoothDevice;
28 import android.bluetooth.le.BluetoothLeScanner;
29 import android.bluetooth.le.ScanCallback;
30 import android.bluetooth.le.ScanFilter;
31 import android.bluetooth.BluetoothAdapter.LeScanCallback;
32 import android.bluetooth.le.ScanFilter.Builder;
33 import android.bluetooth.le.ScanResult;
34 import android.bluetooth.le.ScanSettings;
35 import android.os.Bundle;
36 import android.os.ParcelUuid;
37 
38 import com.googlecode.android_scripting.Log;
39 import com.googlecode.android_scripting.MainThread;
40 import com.googlecode.android_scripting.facade.EventFacade;
41 import com.googlecode.android_scripting.facade.FacadeManager;
42 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
43 import com.googlecode.android_scripting.rpc.Rpc;
44 import com.googlecode.android_scripting.rpc.RpcOptional;
45 import com.googlecode.android_scripting.rpc.RpcParameter;
46 
47 /**
48  * BluetoothLe Scan functions.
49  */
50 
51 public class BluetoothLeScanFacade extends RpcReceiver {
52 
53     private final EventFacade mEventFacade;
54 
55     private BluetoothAdapter mBluetoothAdapter;
56     private static int ScanCallbackCount;
57     private static int FilterListCount;
58     private static int LeScanCallbackCount;
59     private static int ScanSettingsCount;
60     private final Service mService;
61     private final BluetoothLeScanner mScanner;
62     private android.bluetooth.le.ScanSettings.Builder mScanSettingsBuilder;
63     private Builder mScanFilterBuilder;
64     private final HashMap<Integer, myScanCallback> mScanCallbackList;
65     private final HashMap<Integer, myLeScanCallback> mLeScanCallbackList;
66     private final HashMap<Integer, ArrayList<ScanFilter>> mScanFilterList;
67     private final HashMap<Integer, ScanSettings> mScanSettingsList;
68 
BluetoothLeScanFacade(FacadeManager manager)69     public BluetoothLeScanFacade(FacadeManager manager) {
70         super(manager);
71         mService = manager.getService();
72         mBluetoothAdapter = MainThread.run(mService,
73                 new Callable<BluetoothAdapter>() {
74                     @Override
75                     public BluetoothAdapter call() throws Exception {
76                         return BluetoothAdapter.getDefaultAdapter();
77                     }
78                 });
79         mScanner = mBluetoothAdapter.getBluetoothLeScanner();
80         mEventFacade = manager.getReceiver(EventFacade.class);
81         mScanFilterList = new HashMap<Integer, ArrayList<ScanFilter>>();
82         mLeScanCallbackList = new HashMap<Integer, myLeScanCallback>();
83         mScanSettingsList = new HashMap<Integer, ScanSettings>();
84         mScanCallbackList = new HashMap<Integer, myScanCallback>();
85         mScanFilterBuilder = new Builder();
86         mScanSettingsBuilder = new android.bluetooth.le.ScanSettings.Builder();
87     }
88 
89     /**
90      * Constructs a myScanCallback obj and returns its index
91      *
92      * @return Integer myScanCallback.index
93      */
94     @Rpc(description = "Generate a new myScanCallback Object")
bleGenScanCallback()95     public Integer bleGenScanCallback() {
96         ScanCallbackCount += 1;
97         int index = ScanCallbackCount;
98         myScanCallback mScan = new myScanCallback(index);
99         mScanCallbackList.put(mScan.index, mScan);
100         return mScan.index;
101     }
102 
103     /**
104      * Constructs a myLeScanCallback obj and returns its index
105      *
106      * @return Integer myScanCallback.index
107      */
108     @Rpc(description = "Generate a new myScanCallback Object")
bleGenLeScanCallback()109     public Integer bleGenLeScanCallback() {
110         LeScanCallbackCount += 1;
111         int index = LeScanCallbackCount;
112         myLeScanCallback mScan = new myLeScanCallback(index);
113         mLeScanCallbackList.put(mScan.index, mScan);
114         return mScan.index;
115     }
116 
117     /**
118      * Constructs a new filter list array and returns its index
119      *
120      * @return Integer index
121      */
122     @Rpc(description = "Generate a new Filter list")
bleGenFilterList()123     public Integer bleGenFilterList() {
124         FilterListCount += 1;
125         int index = FilterListCount;
126         mScanFilterList.put(index, new ArrayList<ScanFilter>());
127         return index;
128     }
129 
130     /**
131      * Constructs a new filter list array and returns its index
132      *
133      * @return Integer index
134      */
135     @Rpc(description = "Generate a new Filter list")
bleBuildScanFilter( @pcParametername = "filterIndex") Integer filterIndex )136     public Integer bleBuildScanFilter(
137             @RpcParameter(name = "filterIndex")
138             Integer filterIndex
139             ) {
140         mScanFilterList.get(filterIndex).add(mScanFilterBuilder.build());
141         mScanFilterBuilder = new Builder();
142         return mScanFilterList.get(filterIndex).size()-1;
143     }
144 
145     /**
146      * Constructs a new scan setting and returns its index
147      *
148      * @return Integer index
149      */
150     @Rpc(description = "Generate a new scan settings Object")
bleBuildScanSetting()151     public Integer bleBuildScanSetting() {
152         ScanSettingsCount += 1;
153         int index = ScanSettingsCount;
154         mScanSettingsList.put(index, mScanSettingsBuilder.build());
155         mScanSettingsBuilder = new android.bluetooth.le.ScanSettings.Builder();
156         return index;
157     }
158 
159     /**
160      * Stops a ble scan
161      *
162      * @param index the id of the myScan whose ScanCallback to stop
163      * @throws Exception
164      */
165     @Rpc(description = "Stops an ongoing ble advertisement scan")
bleStopBleScan( @pcParametername = "index") Integer index)166     public void bleStopBleScan(
167             @RpcParameter(name = "index")
168             Integer index) throws Exception {
169         Log.d("bluetooth_le_scan mScanCallback " + index);
170         if (mScanCallbackList.get(index) != null) {
171             myScanCallback mScanCallback = mScanCallbackList.get(index);
172             mScanner.stopScan(mScanCallback);
173         } else {
174             throw new Exception("Invalid index input:" + Integer.toString(index));
175         }
176     }
177 
178     /**
179      * Stops a classic ble scan
180      *
181      * @param index the id of the myScan whose LeScanCallback to stop
182      * @throws Exception
183      */
184     @Rpc(description = "Stops an ongoing classic ble scan")
bleStopClassicBleScan( @pcParametername = "index") Integer index)185     public void bleStopClassicBleScan(
186             @RpcParameter(name = "index")
187             Integer index) throws Exception {
188         Log.d("bluetooth_le_scan mLeScanCallback " + index);
189         if (mLeScanCallbackList.get(index) != null) {
190             myLeScanCallback mLeScanCallback = mLeScanCallbackList.get(index);
191             mBluetoothAdapter.stopLeScan(mLeScanCallback);
192         } else {
193             throw new Exception("Invalid index input:" + Integer.toString(index));
194         }
195     }
196 
197     /**
198      * Starts a ble scan
199      *
200      * @param index the id of the myScan whose ScanCallback to start
201      * @throws Exception
202      */
203     @Rpc(description = "Starts a ble advertisement scan")
bleStartBleScan( @pcParametername = "filterListIndex") Integer filterListIndex, @RpcParameter(name = "scanSettingsIndex") Integer scanSettingsIndex, @RpcParameter(name = "callbackIndex") Integer callbackIndex )204     public void bleStartBleScan(
205             @RpcParameter(name = "filterListIndex")
206             Integer filterListIndex,
207             @RpcParameter(name = "scanSettingsIndex")
208             Integer scanSettingsIndex,
209             @RpcParameter(name = "callbackIndex")
210             Integer callbackIndex
211             ) throws Exception {
212         Log.d("bluetooth_le_scan starting a background scan");
213         ArrayList<ScanFilter> mScanFilters = new ArrayList<ScanFilter>();
214         mScanFilters.add(new ScanFilter.Builder().build());
215         ScanSettings mScanSettings = new ScanSettings.Builder().build();
216         if (mScanFilterList.get(filterListIndex) != null) {
217             mScanFilters = mScanFilterList.get(filterListIndex);
218         } else {
219             throw new Exception("Invalid filterListIndex input:"
220                     + Integer.toString(filterListIndex));
221         }
222         if (mScanSettingsList.get(scanSettingsIndex) != null) {
223             mScanSettings = mScanSettingsList.get(scanSettingsIndex);
224         } else if (!mScanSettingsList.isEmpty()) {
225             throw new Exception("Invalid scanSettingsIndex input:"
226                     + Integer.toString(scanSettingsIndex));
227         }
228         if (mScanCallbackList.get(callbackIndex) != null) {
229             mScanner.startScan(mScanFilters, mScanSettings, mScanCallbackList.get(callbackIndex));
230         } else {
231             throw new Exception("Invalid filterListIndex input:"
232                     + Integer.toString(filterListIndex));
233         }
234     }
235 
236     /**
237      * Starts a classic ble scan
238      *
239      * @param index the id of the myScan whose ScanCallback to start
240      * @throws Exception
241      */
242     @Rpc(description = "Starts a classic ble advertisement scan")
bleStartClassicBleScan( @pcParametername = "leCallbackIndex") Integer leCallbackIndex )243     public boolean bleStartClassicBleScan(
244             @RpcParameter(name = "leCallbackIndex")
245             Integer leCallbackIndex
246             ) throws Exception {
247         Log.d("bluetooth_le_scan starting a background scan");
248         boolean result = false;
249         if (mLeScanCallbackList.get(leCallbackIndex) != null) {
250             result = mBluetoothAdapter.startLeScan(mLeScanCallbackList.get(leCallbackIndex));
251         } else {
252             throw new Exception("Invalid leCallbackIndex input:"
253                     + Integer.toString(leCallbackIndex));
254         }
255         return result;
256     }
257 
258     /**
259      * Starts a classic ble scan with service Uuids
260      *
261      * @param index the id of the myScan whose ScanCallback to start
262      * @throws Exception
263      */
264     @Rpc(description = "Starts a classic ble advertisement scan with service Uuids")
bleStartClassicBleScanWithServiceUuids( @pcParametername = "leCallbackIndex") Integer leCallbackIndex, @RpcParameter(name = "serviceUuids") String[] serviceUuidList )265     public boolean bleStartClassicBleScanWithServiceUuids(
266             @RpcParameter(name = "leCallbackIndex")
267             Integer leCallbackIndex,
268             @RpcParameter(name = "serviceUuids")
269             String[] serviceUuidList
270             ) throws Exception {
271         Log.d("bluetooth_le_scan starting a background scan");
272         UUID[] serviceUuids = new UUID[serviceUuidList.length];
273         for (int i = 0; i < serviceUuidList.length; i++) {
274             serviceUuids[i] = UUID.fromString(serviceUuidList[i]);
275         }
276         boolean result = false;
277         if (mLeScanCallbackList.get(leCallbackIndex) != null) {
278             result = mBluetoothAdapter.startLeScan(serviceUuids,
279                     mLeScanCallbackList.get(leCallbackIndex));
280         } else {
281             throw new Exception("Invalid leCallbackIndex input:"
282                     + Integer.toString(leCallbackIndex));
283         }
284         return result;
285     }
286 
287     /**
288      * Trigger onBatchScanResults
289      *
290      * @throws Exception
291      */
292     @Rpc(description = "Gets the results of the ble ScanCallback")
bleFlushPendingScanResults( @pcParametername = "callbackIndex") Integer callbackIndex )293     public void bleFlushPendingScanResults(
294             @RpcParameter(name = "callbackIndex")
295             Integer callbackIndex
296             ) throws Exception {
297         if (mScanCallbackList.get(callbackIndex) != null) {
298             mBluetoothAdapter
299                     .getBluetoothLeScanner().flushPendingScanResults(
300                             mScanCallbackList.get(callbackIndex));
301         } else {
302             throw new Exception("Invalid callbackIndex input:"
303                     + Integer.toString(callbackIndex));
304         }
305     }
306 
307     /**
308      * Set scanSettings for ble scan. Note: You have to set all variables at once.
309      *
310      * @param callbackType Bluetooth LE scan callback type
311      * @param reportDelaySeconds Time of delay for reporting the scan result
312      * @param scanMode Bluetooth LE scan mode.
313      * @param scanResultType Bluetooth LE scan result type
314      * @throws Exception
315      */
316 
317     /**
318      * Set the scan setting's callback type
319      * @param callbackType Bluetooth LE scan callback type
320      */
321     @Rpc(description = "Set the scan setting's callback type")
bleSetScanSettingsCallbackType( @pcParametername = "callbackType") Integer callbackType)322     public void bleSetScanSettingsCallbackType(
323             @RpcParameter(name = "callbackType")
324             Integer callbackType) {
325         mScanSettingsBuilder.setCallbackType(callbackType);
326     }
327 
328     /**
329      * Set the scan setting's report delay millis
330      * @param reportDelayMillis Time of delay for reporting the scan result
331      */
332     @Rpc(description = "Set the scan setting's report delay millis")
bleSetScanSettingsReportDelayMillis( @pcParametername = "reportDelayMillis") Long reportDelayMillis)333     public void bleSetScanSettingsReportDelayMillis(
334             @RpcParameter(name = "reportDelayMillis")
335             Long reportDelayMillis) {
336         mScanSettingsBuilder.setReportDelay(reportDelayMillis);
337     }
338 
339     /**
340      * Set the scan setting's scan mode
341      * @param scanMode Bluetooth LE scan mode.
342      */
343     @Rpc(description = "Set the scan setting's scan mode")
bleSetScanSettingsScanMode( @pcParametername = "scanMode") Integer scanMode)344     public void bleSetScanSettingsScanMode(
345             @RpcParameter(name = "scanMode")
346             Integer scanMode) {
347         mScanSettingsBuilder.setScanMode(scanMode);
348     }
349 
350     /**
351      * Set the scan setting's scan result type
352      * @param scanResultType Bluetooth LE scan result type
353      */
354     @Rpc(description = "Set the scan setting's scan result type")
bleSetScanSettingsResultType( @pcParametername = "scanResultType") Integer scanResultType)355     public void bleSetScanSettingsResultType(
356             @RpcParameter(name = "scanResultType")
357             Integer scanResultType) {
358         mScanSettingsBuilder.setScanResultType(scanResultType);
359     }
360     /**
361      * Get ScanSetting's callback type
362      *
363      * @param index the ScanSetting object to use
364      * @return the ScanSetting's callback type
365      * @throws Exception
366      */
367     @Rpc(description = "Get ScanSetting's callback type")
bleGetScanSettingsCallbackType( @pcParametername = "index") Integer index )368     public Integer bleGetScanSettingsCallbackType(
369             @RpcParameter(name = "index")
370             Integer index
371             ) throws Exception {
372         if (mScanSettingsList.get(index) != null) {
373             ScanSettings mScanSettings = mScanSettingsList.get(index);
374             return mScanSettings.getCallbackType();
375         } else {
376             throw new Exception("Invalid index input:" + Integer.toString(index));
377         }
378     }
379 
380     /**
381      * Get ScanSetting's report delay in milli seconds
382      *
383      * @param index the ScanSetting object to useSystemClock
384      * @return the ScanSetting's report delay in milliseconds
385      * @throws Exception
386      */
387     @Rpc(description = "Get ScanSetting's report delay milliseconds")
bleGetScanSettingsReportDelayMillis( @pcParametername = "index") Integer index)388     public Long bleGetScanSettingsReportDelayMillis(
389             @RpcParameter(name = "index")
390             Integer index) throws Exception {
391         if (mScanSettingsList.get(index) != null) {
392             ScanSettings mScanSettings = mScanSettingsList.get(index);
393             return mScanSettings.getReportDelayMillis();
394         } else {
395             throw new Exception("Invalid index input:" + Integer.toString(index));
396         }
397     }
398 
399     /**
400      * Get ScanSetting's scan mode
401      *
402      * @param index the ScanSetting object to use
403      * @return the ScanSetting's scan mode
404      * @throws Exception
405      */
406     @Rpc(description = "Get ScanSetting's scan mode")
bleGetScanSettingsScanMode( @pcParametername = "index") Integer index)407     public Integer bleGetScanSettingsScanMode(
408             @RpcParameter(name = "index")
409             Integer index) throws Exception {
410         if (mScanSettingsList.get(index) != null) {
411             ScanSettings mScanSettings = mScanSettingsList.get(index);
412             return mScanSettings.getScanMode();
413         } else {
414             throw new Exception("Invalid index input:" + Integer.toString(index));
415         }
416     }
417 
418     /**
419      * Get ScanSetting's scan result type
420      *
421      * @param index the ScanSetting object to use
422      * @return the ScanSetting's scan result type
423      * @throws Exception
424      */
425     @Rpc(description = "Get ScanSetting's scan result type")
bleGetScanSettingsScanResultType( @pcParametername = "index") Integer index)426     public Integer bleGetScanSettingsScanResultType(
427             @RpcParameter(name = "index")
428             Integer index) throws Exception {
429         if (mScanSettingsList.get(index) != null) {
430             ScanSettings mScanSettings = mScanSettingsList.get(index);
431             return mScanSettings.getScanResultType();
432         } else {
433             throw new Exception("Invalid index input:" + Integer.toString(index));
434         }
435     }
436 
437     /**
438      * Get ScanFilter's Manufacturer Id
439      *
440      * @param index the ScanFilter object to use
441      * @return the ScanFilter's manufacturer id
442      * @throws Exception
443      */
444     @Rpc(description = "Get ScanFilter's Manufacturer Id")
bleGetScanFilterManufacturerId( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)445     public Integer bleGetScanFilterManufacturerId(
446             @RpcParameter(name = "index")
447             Integer index,
448             @RpcParameter(name = "filterIndex")
449             Integer filterIndex)
450             throws Exception {
451         if (mScanFilterList.get(index) != null) {
452             if (mScanFilterList.get(index).get(filterIndex) != null) {
453                 return mScanFilterList.get(index)
454                         .get(filterIndex).getManufacturerId();
455             } else {
456                 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex));
457             }
458         } else {
459             throw new Exception("Invalid index input:" + Integer.toString(index));
460         }
461     }
462 
463     /**
464      * Get ScanFilter's device address
465      *
466      * @param index the ScanFilter object to use
467      * @return the ScanFilter's device address
468      * @throws Exception
469      */
470     @Rpc(description = "Get ScanFilter's device address")
bleGetScanFilterDeviceAddress( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)471     public String bleGetScanFilterDeviceAddress(
472             @RpcParameter(name = "index")
473             Integer index,
474             @RpcParameter(name = "filterIndex")
475             Integer filterIndex)
476             throws Exception {
477         if (mScanFilterList.get(index) != null) {
478             if (mScanFilterList.get(index).get(filterIndex) != null) {
479                 return mScanFilterList.get(index).get(filterIndex).getDeviceAddress();
480             } else {
481                 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex));
482             }
483         } else {
484             throw new Exception("Invalid index input:" + Integer.toString(index));
485         }
486     }
487 
488     /**
489      * Get ScanFilter's device name
490      *
491      * @param index the ScanFilter object to use
492      * @return the ScanFilter's device name
493      * @throws Exception
494      */
495     @Rpc(description = "Get ScanFilter's device name")
bleGetScanFilterDeviceName( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)496     public String bleGetScanFilterDeviceName(
497             @RpcParameter(name = "index")
498             Integer index,
499             @RpcParameter(name = "filterIndex")
500             Integer filterIndex)
501             throws Exception {
502         if (mScanFilterList.get(index) != null) {
503             if (mScanFilterList.get(index).get(filterIndex) != null) {
504                 return mScanFilterList.get(index).get(filterIndex).getDeviceName();
505             } else {
506                 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex));
507             }
508         } else {
509             throw new Exception("Invalid index input:" + Integer.toString(index));
510         }
511     }
512 
513     /**
514      * Get ScanFilter's manufacturer data
515      *
516      * @param index the ScanFilter object to use
517      * @return the ScanFilter's manufacturer data
518      * @throws Exception
519      */
520     @Rpc(description = "Get ScanFilter's manufacturer data")
bleGetScanFilterManufacturerData( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)521     public byte[] bleGetScanFilterManufacturerData(
522             @RpcParameter(name = "index")
523             Integer index,
524             @RpcParameter(name = "filterIndex")
525             Integer filterIndex)
526             throws Exception {
527         if (mScanFilterList.get(index) != null) {
528             if (mScanFilterList.get(index).get(filterIndex) != null) {
529                 return mScanFilterList.get(index).get(filterIndex).getManufacturerData();
530             } else {
531                 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex));
532             }
533         } else {
534             throw new Exception("Invalid index input:" + Integer.toString(index));
535         }
536     }
537 
538     /**
539      * Get ScanFilter's manufacturer data mask
540      *
541      * @param index the ScanFilter object to use
542      * @return the ScanFilter's manufacturer data mask
543      * @throws Exception
544      */
545     @Rpc(description = "Get ScanFilter's manufacturer data mask")
bleGetScanFilterManufacturerDataMask( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)546     public byte[] bleGetScanFilterManufacturerDataMask(
547             @RpcParameter(name = "index")
548             Integer index,
549             @RpcParameter(name = "filterIndex")
550             Integer filterIndex)
551             throws Exception {
552         if (mScanFilterList.get(index) != null) {
553             if (mScanFilterList.get(index).get(filterIndex) != null) {
554                 return mScanFilterList.get(index).get(filterIndex).getManufacturerDataMask();
555             } else {
556                 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex));
557             }
558         } else {
559             throw new Exception("Invalid index input:" + Integer.toString(index));
560         }
561     }
562 
563     /**
564      * Get ScanFilter's service data
565      *
566      * @param index the ScanFilter object to use
567      * @return the ScanFilter's service data
568      * @throws Exception
569      */
570     @Rpc(description = "Get ScanFilter's service data")
bleGetScanFilterServiceData( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)571     public byte[] bleGetScanFilterServiceData(
572             @RpcParameter(name = "index")
573             Integer index,
574             @RpcParameter(name = "filterIndex")
575             Integer filterIndex)
576             throws Exception {
577         if (mScanFilterList.get(index) != null) {
578             if (mScanFilterList.get(index).get(filterIndex) != null) {
579                 return mScanFilterList.get(index).get(filterIndex).getServiceData();
580             } else {
581                 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex));
582             }
583         } else {
584             throw new Exception("Invalid index input:" + Integer.toString(index));
585         }
586     }
587 
588     /**
589      * Get ScanFilter's service data mask
590      *
591      * @param index the ScanFilter object to use
592      * @return the ScanFilter's service data mask
593      * @throws Exception
594      */
595     @Rpc(description = "Get ScanFilter's service data mask")
bleGetScanFilterServiceDataMask( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)596     public byte[] bleGetScanFilterServiceDataMask(
597             @RpcParameter(name = "index")
598             Integer index,
599             @RpcParameter(name = "filterIndex")
600             Integer filterIndex)
601             throws Exception {
602         if (mScanFilterList.get(index) != null) {
603             if (mScanFilterList.get(index).get(filterIndex) != null) {
604                 return mScanFilterList.get(index).get(filterIndex).getServiceDataMask();
605             } else {
606                 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex));
607             }
608         } else {
609             throw new Exception("Invalid index input:" + Integer.toString(index));
610         }
611     }
612 
613     /**
614      * Get ScanFilter's service uuid
615      *
616      * @param index the ScanFilter object to use
617      * @return the ScanFilter's service uuid
618      * @throws Exception
619      */
620     @Rpc(description = "Get ScanFilter's service uuid")
bleGetScanFilterServiceUuid( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)621     public String bleGetScanFilterServiceUuid(
622             @RpcParameter(name = "index")
623             Integer index,
624             @RpcParameter(name = "filterIndex")
625             Integer filterIndex)
626             throws Exception {
627         if (mScanFilterList.get(index) != null) {
628             if (mScanFilterList.get(index).get(filterIndex) != null) {
629                 if (mScanFilterList.get(index).get(filterIndex).getServiceUuid() != null) {
630                     return mScanFilterList.get(index).get(filterIndex).getServiceUuid().toString();
631                 } else {
632                     throw new Exception("No Service Uuid set for filter:"
633                             + Integer.toString(filterIndex));
634                 }
635             } else {
636                 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex));
637             }
638         } else {
639             throw new Exception("Invalid index input:" + Integer.toString(index));
640         }
641     }
642 
643     /**
644      * Get ScanFilter's service uuid mask
645      *
646      * @param index the ScanFilter object to use
647      * @return the ScanFilter's service uuid mask
648      * @throws Exception
649      */
650     @Rpc(description = "Get ScanFilter's service uuid mask")
bleGetScanFilterServiceUuidMask( @pcParametername = "index") Integer index, @RpcParameter(name = "filterIndex") Integer filterIndex)651     public String bleGetScanFilterServiceUuidMask(
652             @RpcParameter(name = "index")
653             Integer index,
654             @RpcParameter(name = "filterIndex")
655             Integer filterIndex)
656             throws Exception {
657         if (mScanFilterList.get(index) != null) {
658             if (mScanFilterList.get(index).get(filterIndex) != null) {
659                 if (mScanFilterList.get(index).get(filterIndex).getServiceUuidMask() != null) {
660                     return mScanFilterList.get(index).get(filterIndex).getServiceUuidMask()
661                             .toString();
662                 } else {
663                     throw new Exception("No Service Uuid Mask set for filter:"
664                             + Integer.toString(filterIndex));
665                 }
666             } else {
667                 throw new Exception("Invalid filterIndex input:" + Integer.toString(filterIndex));
668             }
669         } else {
670             throw new Exception("Invalid index input:" + Integer.toString(index));
671         }
672     }
673 
674     /**
675      * Add filter "macAddress" to existing ScanFilter
676      *
677      * @param macAddress the macAddress to filter against
678      * @throws Exception
679      */
680     @Rpc(description = "Add filter \"macAddress\" to existing ScanFilter")
bleSetScanFilterDeviceAddress( @pcParametername = "macAddress") String macAddress )681     public void bleSetScanFilterDeviceAddress(
682             @RpcParameter(name = "macAddress")
683             String macAddress
684             ) {
685             mScanFilterBuilder.setDeviceAddress(macAddress);
686     }
687 
688     /**
689      * Add filter "manufacturereDataId and/or manufacturerData" to existing ScanFilter
690      *
691      * @param manufacturerDataId the manufacturer data id to filter against
692      * @param manufacturerDataMask the manufacturere data mask to filter against
693      * @throws Exception
694      */
695     @Rpc(description = "Add filter \"manufacturereDataId and/or manufacturerData\" to existing ScanFilter")
bleSetScanFilterManufacturerData( @pcParametername = "manufacturerDataId") Integer manufacturerDataId, @RpcParameter(name = "manufacturerData") byte[] manufacturerData, @RpcParameter(name = "manufacturerDataMask") @RpcOptional byte[] manufacturerDataMask )696     public void bleSetScanFilterManufacturerData(
697             @RpcParameter(name = "manufacturerDataId")
698             Integer manufacturerDataId,
699             @RpcParameter(name = "manufacturerData")
700             byte[] manufacturerData,
701             @RpcParameter(name = "manufacturerDataMask")
702             @RpcOptional
703             byte[] manufacturerDataMask
704             ){
705         if (manufacturerDataMask != null) {
706             mScanFilterBuilder.setManufacturerData(manufacturerDataId,
707                     manufacturerData, manufacturerDataMask);
708         } else {
709             mScanFilterBuilder.setManufacturerData(manufacturerDataId,
710                     manufacturerData);
711         }
712     }
713 
714     /**
715      * Add filter "serviceData and serviceDataMask" to existing ScanFilter
716      *
717      * @param serviceData the service data to filter against
718      * @param serviceDataMask the servie data mask to filter against
719      * @throws Exception
720      */
721     @Rpc(description = "Add filter \"serviceData and serviceDataMask\" to existing ScanFilter ")
bleSetScanFilterServiceData( @pcParametername = "serviceUuid") String serviceUuid, @RpcParameter(name = "serviceData") byte[] serviceData, @RpcParameter(name = "serviceDataMask") @RpcOptional byte[] serviceDataMask )722     public void bleSetScanFilterServiceData(
723             @RpcParameter(name = "serviceUuid")
724             String serviceUuid,
725             @RpcParameter(name = "serviceData")
726             byte[] serviceData,
727             @RpcParameter(name = "serviceDataMask")
728             @RpcOptional
729             byte[] serviceDataMask
730             ) {
731         if (serviceDataMask != null) {
732             mScanFilterBuilder
733                     .setServiceData(
734                             ParcelUuid.fromString(serviceUuid),
735                             serviceData, serviceDataMask);
736         } else {
737             mScanFilterBuilder.setServiceData(ParcelUuid.fromString(serviceUuid),
738                     serviceData);
739         }
740     }
741 
742     /**
743      * Add filter "serviceUuid and/or serviceMask" to existing ScanFilter
744      *
745      * @param serviceUuid the service uuid to filter against
746      * @param serviceMask the service mask to filter against
747      * @throws Exception
748      */
749     @Rpc(description = "Add filter \"serviceUuid and/or serviceMask\" to existing ScanFilter")
bleSetScanFilterServiceUuid( @pcParametername = "serviceUuid") String serviceUuid, @RpcParameter(name = "serviceMask") @RpcOptional String serviceMask )750     public void bleSetScanFilterServiceUuid(
751             @RpcParameter(name = "serviceUuid")
752             String serviceUuid,
753             @RpcParameter(name = "serviceMask")
754             @RpcOptional
755             String serviceMask
756             ) {
757         if (serviceMask != null) {
758             mScanFilterBuilder
759                     .setServiceUuid(ParcelUuid.fromString(serviceUuid),
760                             ParcelUuid.fromString(serviceMask));
761         } else {
762             mScanFilterBuilder.setServiceUuid(ParcelUuid.fromString(serviceUuid));
763         }
764     }
765 
766     /**
767      * Add filter "device name" to existing ScanFilter
768      *
769      * @param name the device name to filter against
770      * @throws Exception
771      */
772     @Rpc(description = "Sets the scan filter's device name")
bleSetScanFilterDeviceName( @pcParametername = "name") String name )773     public void bleSetScanFilterDeviceName(
774             @RpcParameter(name = "name")
775             String name
776             ) {
777             mScanFilterBuilder.setDeviceName(name);
778     }
779 
780     @Rpc(description = "Set the scan setting's match mode")
bleSetScanSettingsMatchMode( @pcParametername = "mode") Integer mode)781     public void bleSetScanSettingsMatchMode(
782             @RpcParameter(name = "mode") Integer mode) {
783         mScanSettingsBuilder.setMatchMode(mode);
784     }
785 
786     @Rpc(description = "Get the scan setting's match mode")
bleGetScanSettingsMatchMode( @pcParametername = "scanSettingsIndex") Integer scanSettingsIndex )787     public int bleGetScanSettingsMatchMode(
788             @RpcParameter(name = "scanSettingsIndex") Integer scanSettingsIndex
789             ) {
790         return mScanSettingsList.get(scanSettingsIndex).getMatchMode();
791     }
792 
793     @Rpc(description = "Set the scan setting's number of matches")
bleSetScanSettingsNumOfMatches( @pcParametername = "matches") Integer matches)794     public void bleSetScanSettingsNumOfMatches(
795             @RpcParameter(name = "matches") Integer matches) {
796         mScanSettingsBuilder.setNumOfMatches(matches);
797     }
798 
799     @Rpc(description = "Get the scan setting's number of matches")
bleGetScanSettingsNumberOfMatches( @pcParametername = "scanSettingsIndex") Integer scanSettingsIndex)800     public int bleGetScanSettingsNumberOfMatches(
801             @RpcParameter(name = "scanSettingsIndex")
802             Integer scanSettingsIndex) {
803         return  mScanSettingsList.get(scanSettingsIndex).getNumOfMatches();
804     }
805 
806     private class myScanCallback extends ScanCallback {
807         public Integer index;
808         String mEventType;
809         private final Bundle mResults;
810 
myScanCallback(Integer idx)811         public myScanCallback(Integer idx) {
812             index = idx;
813             mEventType = "BleScan";
814             mResults = new Bundle();
815         }
816 
817         @Override
onScanFailed(int errorCode)818         public void onScanFailed(int errorCode) {
819             String errorString = "UNKNOWN_ERROR_CODE";
820             if (errorCode == ScanCallback.SCAN_FAILED_ALREADY_STARTED) {
821                 errorString = "SCAN_FAILED_ALREADY_STARTED";
822             } else if (errorCode == ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED) {
823                 errorString = "SCAN_FAILED_APPLICATION_REGISTRATION_FAILED";
824             } else if (errorCode == ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED) {
825                 errorString = "SCAN_FAILED_FEATURE_UNSUPPORTED";
826             } else if (errorCode == ScanCallback.SCAN_FAILED_INTERNAL_ERROR) {
827                 errorString = "SCAN_FAILED_INTERNAL_ERROR";
828             }
829             Log.d("bluetooth_le_scan change onScanFailed " + mEventType + " " + index + " error "
830                     + errorString);
831             mResults.putInt("ID", index);
832             mResults.putString("Type", "onScanFailed");
833             mResults.putInt("ErrorCode", errorCode);
834             mResults.putString("Error", errorString);
835             mEventFacade.postEvent(mEventType + index + "onScanFailed",
836                     mResults.clone());
837             mResults.clear();
838         }
839 
840         @Override
onScanResult(int callbackType, ScanResult result)841         public void onScanResult(int callbackType, ScanResult result) {
842             Log.d("bluetooth_le_scan change onUpdate " + mEventType + " " + index);
843             mResults.putInt("ID", index);
844             mResults.putInt("CallbackType", callbackType);
845             mResults.putString("Type", "onScanResult");
846             mResults.putParcelable("Result", result);
847             mEventFacade.postEvent(mEventType + index + "onScanResults", mResults.clone());
848             mResults.clear();
849         }
850 
851         @Override
onBatchScanResults(List<ScanResult> results)852         public void onBatchScanResults(List<ScanResult> results) {
853             Log.d("reportResult " + mEventType + " " + index);
854             mResults.putLong("Timestamp", System.currentTimeMillis() / 1000);
855             mResults.putInt("ID", index);
856             mResults.putString("Type", "onBatchScanResults");
857             mResults.putParcelableList("Results", results);
858             mEventFacade.postEvent(mEventType + index + "onBatchScanResult", mResults.clone());
859             mResults.clear();
860         }
861     }
862 
863     private class myLeScanCallback implements LeScanCallback {
864         public Integer index;
865         String mEventType;
866         private final Bundle mResults;
867 
myLeScanCallback(Integer idx)868         public myLeScanCallback(Integer idx) {
869             index = idx;
870             mEventType = "ClassicBleScan";
871             mResults = new Bundle();
872         }
873 
874         @Override
onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)875         public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
876             Log.d("bluetooth_classic_le_scan " + mEventType + " " + index);
877             mResults.putParcelable("Device", device);
878             mResults.putInt("Rssi", rssi);
879             mResults.putByteArray("ScanRecord", scanRecord);
880             mResults.putString("Type", "onLeScan");
881             mEventFacade.postEvent(mEventType + index + "onLeScan", mResults.clone());
882             mResults.clear();
883         }
884     }
885 
886     @Override
shutdown()887     public void shutdown() {
888       if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
889           for (myScanCallback mScanCallback : mScanCallbackList.values()) {
890               if (mScanCallback != null) {
891                   try {
892                     mBluetoothAdapter.getBluetoothLeScanner()
893                       .stopScan(mScanCallback);
894                   } catch (NullPointerException e) {
895                     Log.e("Failed to stop ble scan callback.", e);
896                   }
897               }
898           }
899           for (myLeScanCallback mLeScanCallback : mLeScanCallbackList.values()) {
900               if (mLeScanCallback != null) {
901                   try {
902                       mBluetoothAdapter.stopLeScan(mLeScanCallback);
903                   } catch (NullPointerException e) {
904                     Log.e("Failed to stop classic ble scan callback.", e);
905                   }
906               }
907           }
908       }
909       mScanCallbackList.clear();
910       mScanFilterList.clear();
911       mScanSettingsList.clear();
912       mLeScanCallbackList.clear();
913     }
914 }
915