16d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang/* 26d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Copyright (C) 2014 The Android Open Source Project 36d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 46d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Licensed under the Apache License, Version 2.0 (the "License"); you may not 56d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * use this file except in compliance with the License. You may obtain a copy of 66d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * the License at 76d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 86d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * http://www.apache.org/licenses/LICENSE-2.0 96d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 106d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Unless required by applicable law or agreed to in writing, software 116d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 126d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 136d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * License for the specific language governing permissions and limitations under 146d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * the License. 156d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 166d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 176d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangpackage android.bluetooth.le; 186d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 192d49752ee050ab7f1cd848933f6c62a73707e2d9Tor Norbyeimport android.Manifest; 20461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasaniimport android.annotation.NonNull; 21461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasaniimport android.annotation.Nullable; 222d49752ee050ab7f1cd848933f6c62a73707e2d9Tor Norbyeimport android.annotation.RequiresPermission; 230d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wangimport android.annotation.SystemApi; 24a179030483a1f3f672be41797dc6e0f077ef4748Fyodor Kupolovimport android.app.ActivityThread; 25461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasaniimport android.app.PendingIntent; 266d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.bluetooth.BluetoothAdapter; 276d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.bluetooth.BluetoothGatt; 286d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.bluetooth.IBluetoothGatt; 299fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wangimport android.bluetooth.IBluetoothManager; 306d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.os.Handler; 316d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.os.Looper; 326d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.os.RemoteException; 336771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinskiimport android.os.WorkSource; 346d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.util.Log; 356d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 360d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wangimport java.util.ArrayList; 376d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport java.util.HashMap; 386d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport java.util.List; 396d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport java.util.Map; 406d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 416d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang/** 426d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * This class provides methods to perform scan related operations for Bluetooth LE devices. An 43e7b03631d2a64c3ad5a739cedfd7d40fe5421844Scott Kennedy * application can scan for a particular type of Bluetooth LE devices using {@link ScanFilter}. It 44685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * can also request different types of callbacks for delivering the result. 456d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * <p> 466d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Use {@link BluetoothAdapter#getBluetoothLeScanner()} to get an instance of 476d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * {@link BluetoothLeScanner}. 486d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * <p> 49af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * <b>Note:</b> Most of the scan methods here require 50af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. 516d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 526d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @see ScanFilter 536d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 546d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangpublic final class BluetoothLeScanner { 556d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 566d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final String TAG = "BluetoothLeScanner"; 576d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final boolean DBG = true; 58020bd7b861dfd560fad9f761f2778ebbac8be20eWei Wang private static final boolean VDBG = false; 596d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 60461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani /** 61461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * Extra containing a list of ScanResults. It can have one or more results if there was no 62461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * error. In case of error, {@link #EXTRA_ERROR_CODE} will contain the error code and this 63461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * extra will not be available. 64461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani */ 65461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani public static final String EXTRA_LIST_SCAN_RESULT 66461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani = "android.bluetooth.le.extra.LIST_SCAN_RESULT"; 67461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani 68461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani /** 69461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * Optional extra indicating the error code, if any. The error code will be one of the 70461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * SCAN_FAILED_* codes in {@link ScanCallback}. 71461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani */ 72461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE"; 73461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani 74461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani /** 75461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * Optional extra indicating the callback type, which will be one of 76ad8f0869127bbc514711e4765703392b15e3c31aAmith Yamasani * CALLBACK_TYPE_* constants in {@link ScanSettings}. 77461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * @see ScanCallback#onScanResult(int, ScanResult) 78461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani */ 79461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE"; 80461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani 819fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang private final IBluetoothManager mBluetoothManager; 826d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private final Handler mHandler; 838e5270fdf5639461d67e9a898a85520abac6053dPrerepa Viswanadham private BluetoothAdapter mBluetoothAdapter; 846d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private final Map<ScanCallback, BleScanCallbackWrapper> mLeScanClients; 856d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 866d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 87af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead. 88685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * 89685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management. 906d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @hide 916d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 929fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang public BluetoothLeScanner(IBluetoothManager bluetoothManager) { 939fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang mBluetoothManager = bluetoothManager; 948e5270fdf5639461d67e9a898a85520abac6053dPrerepa Viswanadham mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 956d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mHandler = new Handler(Looper.getMainLooper()); 966d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mLeScanClients = new HashMap<ScanCallback, BleScanCallbackWrapper>(); 976d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 986d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 996d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 100685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * Start Bluetooth LE scan with default parameters and no filters. The scan results will be 101685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * delivered through {@code callback}. 102af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * <p> 1037bd8be0019cb5896c27d0a2d39be19274c442ba5Fyodor Kupolov * An app must hold 1047bd8be0019cb5896c27d0a2d39be19274c442ba5Fyodor Kupolov * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or 1057bd8be0019cb5896c27d0a2d39be19274c442ba5Fyodor Kupolov * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission 1067bd8be0019cb5896c27d0a2d39be19274c442ba5Fyodor Kupolov * in order to get results. 107af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * 108af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * @param callback Callback used to deliver scan results. 109af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * @throws IllegalArgumentException If {@code callback} is null. 110af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang */ 1112d49752ee050ab7f1cd848933f6c62a73707e2d9Tor Norbye @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 112af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang public void startScan(final ScanCallback callback) { 113833559d9f3f0bd6ddb1cf9c1571975751830e045Wei Wang startScan(null, new ScanSettings.Builder().build(), callback); 114af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang } 115af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang 116af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang /** 1176d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Start Bluetooth LE scan. The scan results will be delivered through {@code callback}. 1186d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * <p> 1197bd8be0019cb5896c27d0a2d39be19274c442ba5Fyodor Kupolov * An app must hold 1207bd8be0019cb5896c27d0a2d39be19274c442ba5Fyodor Kupolov * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or 1217bd8be0019cb5896c27d0a2d39be19274c442ba5Fyodor Kupolov * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission 1227bd8be0019cb5896c27d0a2d39be19274c442ba5Fyodor Kupolov * in order to get results. 1236d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 1246d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @param filters {@link ScanFilter}s for finding exact BLE devices. 125af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * @param settings Settings for the scan. 126af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * @param callback Callback used to deliver scan results. 1276d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @throws IllegalArgumentException If {@code settings} or {@code callback} is null. 1286d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 1292d49752ee050ab7f1cd848933f6c62a73707e2d9Tor Norbye @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 1306d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public void startScan(List<ScanFilter> filters, ScanSettings settings, 1316d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang final ScanCallback callback) { 132461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani startScan(filters, settings, null, callback, /*callbackIntent=*/ null, null); 133461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani } 134461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani 135461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani /** 136461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * Start Bluetooth LE scan using a {@link PendingIntent}. The scan results will be delivered via 137461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * the PendingIntent. Use this method of scanning if your process is not always running and it 138461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * should be started when scan results are available. 1399622137f3f5766408c82752f50a3dd8af6cd2134Amith Yamasani * <p> 140172dd5c652af9b9bb52392799b3b0da99231beb5Amith Yamasani * An app must hold 141172dd5c652af9b9bb52392799b3b0da99231beb5Amith Yamasani * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or 142172dd5c652af9b9bb52392799b3b0da99231beb5Amith Yamasani * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission 143172dd5c652af9b9bb52392799b3b0da99231beb5Amith Yamasani * in order to get results. 144172dd5c652af9b9bb52392799b3b0da99231beb5Amith Yamasani * <p> 1459622137f3f5766408c82752f50a3dd8af6cd2134Amith Yamasani * When the PendingIntent is delivered, the Intent passed to the receiver or activity 1469622137f3f5766408c82752f50a3dd8af6cd2134Amith Yamasani * will contain one or more of the extras {@link #EXTRA_CALLBACK_TYPE}, 1479622137f3f5766408c82752f50a3dd8af6cd2134Amith Yamasani * {@link #EXTRA_ERROR_CODE} and {@link #EXTRA_LIST_SCAN_RESULT} to indicate the result of 1489622137f3f5766408c82752f50a3dd8af6cd2134Amith Yamasani * the scan. 149461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * 150461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * @param filters Optional list of ScanFilters for finding exact BLE devices. 151461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * @param settings Optional settings for the scan. 152461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * @param callbackIntent The PendingIntent to deliver the result to. 153461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * @return Returns 0 for success or an error code from {@link ScanCallback} if the scan request 154461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * could not be sent. 155461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * @see #stopScan(PendingIntent) 156461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani */ 157461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 158461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani public int startScan(@Nullable List<ScanFilter> filters, @Nullable ScanSettings settings, 159461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani @NonNull PendingIntent callbackIntent) { 160461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani return startScan(filters, 161461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani settings != null ? settings : new ScanSettings.Builder().build(), 162461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani null, null, callbackIntent, null); 1636771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski } 1646771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski 1656771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski /** 1666771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * Start Bluetooth LE scan. Same as {@link #startScan(ScanCallback)} but allows the caller to 1676771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * specify on behalf of which application(s) the work is being done. 1686771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * 1696771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * @param workSource {@link WorkSource} identifying the application(s) for which to blame for 1706771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * the scan. 1716771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * @param callback Callback used to deliver scan results. 1726771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * @hide 1736771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski */ 1746771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski @SystemApi 1756771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski @RequiresPermission(allOf = { 1766771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS }) 1776771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski public void startScanFromSource(final WorkSource workSource, final ScanCallback callback) { 1786771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski startScanFromSource(null, new ScanSettings.Builder().build(), workSource, callback); 1796771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski } 1806771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski 1816771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski /** 1826771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * Start Bluetooth LE scan. Same as {@link #startScan(List, ScanSettings, ScanCallback)} but 1836771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * allows the caller to specify on behalf of which application(s) the work is being done. 1846771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * 1856771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * @param filters {@link ScanFilter}s for finding exact BLE devices. 1866771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * @param settings Settings for the scan. 1876771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * @param workSource {@link WorkSource} identifying the application(s) for which to blame for 1886771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * the scan. 1896771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * @param callback Callback used to deliver scan results. 1906771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski * @hide 1916771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski */ 1926771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski @SystemApi 1936771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski @RequiresPermission(allOf = { 1946771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS }) 1956771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings, 1966771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski final WorkSource workSource, final ScanCallback callback) { 197461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani startScan(filters, settings, workSource, callback, null, null); 1980d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang } 1990d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang 200461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani private int startScan(List<ScanFilter> filters, ScanSettings settings, 2016771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski final WorkSource workSource, final ScanCallback callback, 202461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani final PendingIntent callbackIntent, 2036771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski List<List<ResultStorageDescriptor>> resultStorages) { 204833559d9f3f0bd6ddb1cf9c1571975751830e045Wei Wang BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); 205461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani if (callback == null && callbackIntent == null) { 2066771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski throw new IllegalArgumentException("callback is null"); 2076771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski } 2086771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski if (settings == null) { 2096771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski throw new IllegalArgumentException("settings is null"); 2106d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2116d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang synchronized (mLeScanClients) { 212461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani if (callback != null && mLeScanClients.containsKey(callback)) { 2139722971cb4a79e37165f636f9dd057707d2e620aVinay Kalia return postCallbackErrorOrReturn(callback, 2149722971cb4a79e37165f636f9dd057707d2e620aVinay Kalia ScanCallback.SCAN_FAILED_ALREADY_STARTED); 2156d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2169fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang IBluetoothGatt gatt; 2179fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang try { 2189fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang gatt = mBluetoothManager.getBluetoothGatt(); 2199fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } catch (RemoteException e) { 2209fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang gatt = null; 2219fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } 2229fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang if (gatt == null) { 223461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); 2249fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } 2258e5270fdf5639461d67e9a898a85520abac6053dPrerepa Viswanadham if (!isSettingsConfigAllowedForScan(settings)) { 226461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani return postCallbackErrorOrReturn(callback, 227461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); 2288e5270fdf5639461d67e9a898a85520abac6053dPrerepa Viswanadham } 229e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham if (!isHardwareResourcesAvailableForScan(settings)) { 230461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani return postCallbackErrorOrReturn(callback, 231461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES); 232e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham } 233e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham if (!isSettingsAndFilterComboAllowed(settings, filters)) { 234461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani return postCallbackErrorOrReturn(callback, 235e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); 236e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham } 237461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani if (callback != null) { 238461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters, 239461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani settings, workSource, callback, resultStorages); 240461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani wrapper.startRegistration(); 241461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani } else { 242461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani try { 243461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani gatt.startScanForIntent(callbackIntent, settings, filters, 244461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani ActivityThread.currentOpPackageName()); 245461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani } catch (RemoteException e) { 246461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani return ScanCallback.SCAN_FAILED_INTERNAL_ERROR; 247461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani } 248461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani } 2496d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 250461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani return ScanCallback.NO_ERROR; 2516d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2526d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 2536d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 2546d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Stops an ongoing Bluetooth LE scan. 2556d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 2566d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @param callback 2576d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 2582d49752ee050ab7f1cd848933f6c62a73707e2d9Tor Norbye @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 2596d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public void stopScan(ScanCallback callback) { 260833559d9f3f0bd6ddb1cf9c1571975751830e045Wei Wang BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); 2616d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang synchronized (mLeScanClients) { 2626d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang BleScanCallbackWrapper wrapper = mLeScanClients.remove(callback); 2636d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang if (wrapper == null) { 264b661bb79584f83ae95713e502fc14363c80c0278Wei Wang if (DBG) Log.d(TAG, "could not find callback wrapper"); 2656d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return; 2666d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2676d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang wrapper.stopLeScan(); 2686d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2696d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2706d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 2716d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 272461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * Stops an ongoing Bluetooth LE scan started using a PendingIntent. 273461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * 274461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * @param callbackIntent The PendingIntent that was used to start the scan. 275461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani * @see #startScan(List, ScanSettings, PendingIntent) 276461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani */ 277461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 278461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani public void stopScan(PendingIntent callbackIntent) { 279461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); 280461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani IBluetoothGatt gatt; 281461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani try { 282461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani gatt = mBluetoothManager.getBluetoothGatt(); 283461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani gatt.stopScanForIntent(callbackIntent, ActivityThread.currentOpPackageName()); 284461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani } catch (RemoteException e) { 285461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani } 286461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani } 287461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani 288461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani /** 2899fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang * Flush pending batch scan results stored in Bluetooth controller. This will return Bluetooth 2909fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang * LE scan results batched on bluetooth controller. Returns immediately, batch scan results data 2919fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang * will be delivered through the {@code callback}. 2926d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 2936d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @param callback Callback of the Bluetooth LE Scan, it has to be the same instance as the one 2946d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * used to start scan. 2956d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 2969fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang public void flushPendingScanResults(ScanCallback callback) { 297833559d9f3f0bd6ddb1cf9c1571975751830e045Wei Wang BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); 2989fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang if (callback == null) { 2999fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang throw new IllegalArgumentException("callback cannot be null!"); 3009fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } 3019fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang synchronized (mLeScanClients) { 3029fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang BleScanCallbackWrapper wrapper = mLeScanClients.get(callback); 3039fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang if (wrapper == null) { 3049fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang return; 3059fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } 3069fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang wrapper.flushPendingBatchResults(); 3079fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } 3086d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 3096d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 3106d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 3110d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang * Start truncated scan. 3120d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang * 3130d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang * @hide 3140d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang */ 3150d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang @SystemApi 3160d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang public void startTruncatedScan(List<TruncatedFilter> truncatedFilters, ScanSettings settings, 3170d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang final ScanCallback callback) { 3180d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang int filterSize = truncatedFilters.size(); 3190d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang List<ScanFilter> scanFilters = new ArrayList<ScanFilter>(filterSize); 3200d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang List<List<ResultStorageDescriptor>> scanStorages = 3210d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang new ArrayList<List<ResultStorageDescriptor>>(filterSize); 3220d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang for (TruncatedFilter filter : truncatedFilters) { 3230d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang scanFilters.add(filter.getFilter()); 3240d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang scanStorages.add(filter.getStorageDescriptors()); 3250d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang } 326461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani startScan(scanFilters, settings, null, callback, null, scanStorages); 3270d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang } 3280d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang 3290d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang /** 330ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang * Cleans up scan clients. Should be called when bluetooth is down. 331ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang * 332ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang * @hide 333ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang */ 334ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang public void cleanup() { 335ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang mLeScanClients.clear(); 336ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang } 337ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang 338ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang /** 3396d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Bluetooth GATT interface callbacks 3406d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 3411b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski private class BleScanCallbackWrapper extends IScannerCallback.Stub { 342b661bb79584f83ae95713e502fc14363c80c0278Wei Wang private static final int REGISTRATION_CALLBACK_TIMEOUT_MILLIS = 2000; 3436d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 3446d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private final ScanCallback mScanCallback; 3456d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private final List<ScanFilter> mFilters; 3466771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski private final WorkSource mWorkSource; 3476d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private ScanSettings mSettings; 3486d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private IBluetoothGatt mBluetoothGatt; 3490d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang private List<List<ResultStorageDescriptor>> mResultStorages; 3506d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 3516d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // mLeHandle 0: not registered 352f50749040421edfdf22326b1e0f0568e4408fa26Jakub Pawlowski // -2: registration failed because app is scanning to frequently 35302bc0086071b5faff260566b4d3713861703eee3Wei Wang // -1: scan stopped or registration failed 3546d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // > 0: registered and scan started 3551b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski private int mScannerId; 3566d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 3576d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public BleScanCallbackWrapper(IBluetoothGatt bluetoothGatt, 3586d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang List<ScanFilter> filters, ScanSettings settings, 3596771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski WorkSource workSource, ScanCallback scanCallback, 3606771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski List<List<ResultStorageDescriptor>> resultStorages) { 3616d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mBluetoothGatt = bluetoothGatt; 3626d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mFilters = filters; 3636d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mSettings = settings; 3646771d629b5ad0b9296f0febaa2300fdaf1f90515Adam Lesinski mWorkSource = workSource; 3656d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mScanCallback = scanCallback; 3661b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski mScannerId = 0; 3670d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang mResultStorages = resultStorages; 3686d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 3696d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 370461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani public void startRegistration() { 3716d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang synchronized (this) { 372b661bb79584f83ae95713e502fc14363c80c0278Wei Wang // Scan stopped. 373f50749040421edfdf22326b1e0f0568e4408fa26Jakub Pawlowski if (mScannerId == -1 || mScannerId == -2) return; 3746d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang try { 375a71643e91c46efa49a906e3d59f126c752d750b0Ajay Panicker mBluetoothGatt.registerScanner(this, mWorkSource); 376b661bb79584f83ae95713e502fc14363c80c0278Wei Wang wait(REGISTRATION_CALLBACK_TIMEOUT_MILLIS); 377b661bb79584f83ae95713e502fc14363c80c0278Wei Wang } catch (InterruptedException | RemoteException e) { 378b661bb79584f83ae95713e502fc14363c80c0278Wei Wang Log.e(TAG, "application registeration exception", e); 379b661bb79584f83ae95713e502fc14363c80c0278Wei Wang postCallbackError(mScanCallback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); 380b661bb79584f83ae95713e502fc14363c80c0278Wei Wang } 3811b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski if (mScannerId > 0) { 382b661bb79584f83ae95713e502fc14363c80c0278Wei Wang mLeScanClients.put(mScanCallback, this); 383b661bb79584f83ae95713e502fc14363c80c0278Wei Wang } else { 3841b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski // Registration timed out or got exception, reset scannerId to -1 so no 38502bc0086071b5faff260566b4d3713861703eee3Wei Wang // subsequent operations can proceed. 3861b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski if (mScannerId == 0) mScannerId = -1; 387f50749040421edfdf22326b1e0f0568e4408fa26Jakub Pawlowski 388f50749040421edfdf22326b1e0f0568e4408fa26Jakub Pawlowski // If scanning too frequently, don't report anything to the app. 389f50749040421edfdf22326b1e0f0568e4408fa26Jakub Pawlowski if (mScannerId == -2) return; 390f50749040421edfdf22326b1e0f0568e4408fa26Jakub Pawlowski 391b661bb79584f83ae95713e502fc14363c80c0278Wei Wang postCallbackError(mScanCallback, 392b661bb79584f83ae95713e502fc14363c80c0278Wei Wang ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED); 3936d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 3946d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 3956d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 3966d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 3976d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public void stopLeScan() { 3986d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang synchronized (this) { 3991b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski if (mScannerId <= 0) { 4001b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski Log.e(TAG, "Error state, mLeHandle: " + mScannerId); 4016d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang return; 4026d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 4036d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang try { 4041b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski mBluetoothGatt.stopScan(mScannerId); 4051b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski mBluetoothGatt.unregisterScanner(mScannerId); 4066d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } catch (RemoteException e) { 4079fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang Log.e(TAG, "Failed to stop scan and unregister", e); 4086d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 4091b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski mScannerId = -1; 4106d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 4116d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 4126d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 4139fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang void flushPendingBatchResults() { 4149fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang synchronized (this) { 4151b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski if (mScannerId <= 0) { 4161b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski Log.e(TAG, "Error state, mLeHandle: " + mScannerId); 4179fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang return; 4189fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } 4199fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang try { 4201b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski mBluetoothGatt.flushPendingBatchResults(mScannerId); 4219fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } catch (RemoteException e) { 4229fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang Log.e(TAG, "Failed to get pending scan results", e); 4239fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } 4249fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } 4259fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } 4269fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang 4276d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 4286d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Application interface registered - app is ready to go 4296d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 4306d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang @Override 4311b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski public void onScannerRegistered(int status, int scannerId) { 4321b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski Log.d(TAG, "onScannerRegistered() - status=" + status + 4331b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski " scannerId=" + scannerId + " mScannerId=" + mScannerId); 4346d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang synchronized (this) { 4356d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang if (status == BluetoothGatt.GATT_SUCCESS) { 4366d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang try { 4371b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski if (mScannerId == -1) { 43802bc0086071b5faff260566b4d3713861703eee3Wei Wang // Registration succeeds after timeout, unregister client. 4391b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski mBluetoothGatt.unregisterClient(scannerId); 44002bc0086071b5faff260566b4d3713861703eee3Wei Wang } else { 4411b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski mScannerId = scannerId; 4421b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski mBluetoothGatt.startScan(mScannerId, mSettings, mFilters, 443a71643e91c46efa49a906e3d59f126c752d750b0Ajay Panicker mResultStorages, 44402bc0086071b5faff260566b4d3713861703eee3Wei Wang ActivityThread.currentOpPackageName()); 44502bc0086071b5faff260566b4d3713861703eee3Wei Wang } 4466d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } catch (RemoteException e) { 4476d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang Log.e(TAG, "fail to start le scan: " + e); 4481b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski mScannerId = -1; 4496d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 450f50749040421edfdf22326b1e0f0568e4408fa26Jakub Pawlowski } else if (status == ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY) { 451f50749040421edfdf22326b1e0f0568e4408fa26Jakub Pawlowski // applicaiton was scanning too frequently 452f50749040421edfdf22326b1e0f0568e4408fa26Jakub Pawlowski mScannerId = -2; 4536d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } else { 4546d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // registration failed 4551b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski mScannerId = -1; 4566d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 4576d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang notifyAll(); 4586d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 4596d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 4606d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 4616d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 4626d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Callback reporting an LE scan result. 4636d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 4646d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @hide 4656d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 4666d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang @Override 467e0d4afb2d4caecb264852a35f6e3cfc1248e08c4Wei Wang public void onScanResult(final ScanResult scanResult) { 468020bd7b861dfd560fad9f761f2778ebbac8be20eWei Wang if (VDBG) Log.d(TAG, "onScanResult() - " + scanResult.toString()); 4696d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 4706d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang // Check null in case the scan has been stopped 4716d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang synchronized (this) { 4721b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski if (mScannerId <= 0) return; 4736d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 4749fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang Handler handler = new Handler(Looper.getMainLooper()); 4759fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang handler.post(new Runnable() { 476b661bb79584f83ae95713e502fc14363c80c0278Wei Wang @Override 4779fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang public void run() { 478e0d4afb2d4caecb264852a35f6e3cfc1248e08c4Wei Wang mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult); 4799fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } 4809fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang }); 4819fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } 4829fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang 4839fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang @Override 4849fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang public void onBatchScanResults(final List<ScanResult> results) { 4859fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang Handler handler = new Handler(Looper.getMainLooper()); 4869fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang handler.post(new Runnable() { 487b661bb79584f83ae95713e502fc14363c80c0278Wei Wang @Override 4889fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang public void run() { 4899fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang mScanCallback.onBatchScanResults(results); 4909fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang } 4919fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang }); 4926d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 4936d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 4946d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang @Override 495d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham public void onFoundOrLost(final boolean onFound, final ScanResult scanResult) { 496020bd7b861dfd560fad9f761f2778ebbac8be20eWei Wang if (VDBG) { 497d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham Log.d(TAG, "onFoundOrLost() - onFound = " + onFound + 498d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham " " + scanResult.toString()); 4998f2e74cac282afa0bcf98f5d7131268147d12efePrerepa Viswanadham } 500d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham 501d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham // Check null in case the scan has been stopped 502d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham synchronized (this) { 5031b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski if (mScannerId <= 0) 5040d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang return; 5058f2e74cac282afa0bcf98f5d7131268147d12efePrerepa Viswanadham } 506d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham Handler handler = new Handler(Looper.getMainLooper()); 507d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham handler.post(new Runnable() { 508d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham @Override 509d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham public void run() { 510d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham if (onFound) { 5110d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_FIRST_MATCH, 5120d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang scanResult); 513d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham } else { 5140d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_MATCH_LOST, 5150d0df3ce258f569c76dc7c4b5250c4e50029d6e6Wei Wang scanResult); 516d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham } 517d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham } 518d5324e4183c97ae7271b6eda4204d9f0dc003023Prerepa Viswanadham }); 5198f2e74cac282afa0bcf98f5d7131268147d12efePrerepa Viswanadham } 520db1dbb889588505cd340e954acbde7ebf7c086d6Prerepa Viswanadham 521db1dbb889588505cd340e954acbde7ebf7c086d6Prerepa Viswanadham @Override 522db1dbb889588505cd340e954acbde7ebf7c086d6Prerepa Viswanadham public void onScanManagerErrorCallback(final int errorCode) { 523db1dbb889588505cd340e954acbde7ebf7c086d6Prerepa Viswanadham if (VDBG) { 524db1dbb889588505cd340e954acbde7ebf7c086d6Prerepa Viswanadham Log.d(TAG, "onScanManagerErrorCallback() - errorCode = " + errorCode); 525db1dbb889588505cd340e954acbde7ebf7c086d6Prerepa Viswanadham } 526db1dbb889588505cd340e954acbde7ebf7c086d6Prerepa Viswanadham synchronized (this) { 5271b49e6eb04f2eef4d8056e7447d8e0789c291847Jakub Pawlowski if (mScannerId <= 0) 528db1dbb889588505cd340e954acbde7ebf7c086d6Prerepa Viswanadham return; 529db1dbb889588505cd340e954acbde7ebf7c086d6Prerepa Viswanadham } 530db1dbb889588505cd340e954acbde7ebf7c086d6Prerepa Viswanadham postCallbackError(mScanCallback, errorCode); 531db1dbb889588505cd340e954acbde7ebf7c086d6Prerepa Viswanadham } 5326d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 5336d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 534461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani private int postCallbackErrorOrReturn(final ScanCallback callback, final int errorCode) { 535461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani if (callback == null) { 536461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani return errorCode; 537461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani } else { 538461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani postCallbackError(callback, errorCode); 539461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani return ScanCallback.NO_ERROR; 540461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani } 541461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani } 542461111bc3d9b53f745a9be686504aee161f36c28Amith Yamasani 5436d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private void postCallbackError(final ScanCallback callback, final int errorCode) { 5446d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mHandler.post(new Runnable() { 545b661bb79584f83ae95713e502fc14363c80c0278Wei Wang @Override 5466d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public void run() { 5476d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang callback.onScanFailed(errorCode); 5486d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 5496d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang }); 5506d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 5518e5270fdf5639461d67e9a898a85520abac6053dPrerepa Viswanadham 5528e5270fdf5639461d67e9a898a85520abac6053dPrerepa Viswanadham private boolean isSettingsConfigAllowedForScan(ScanSettings settings) { 553685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang if (mBluetoothAdapter.isOffloadedFilteringSupported()) { 554685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang return true; 555685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang } 556af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang final int callbackType = settings.getCallbackType(); 557685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang // Only support regular scan if no offloaded filter support. 558685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang if (callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES 559685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang && settings.getReportDelayMillis() == 0) { 560685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang return true; 561af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang } 562685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang return false; 5638e5270fdf5639461d67e9a898a85520abac6053dPrerepa Viswanadham } 564e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham 565e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham private boolean isSettingsAndFilterComboAllowed(ScanSettings settings, 566e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham List <ScanFilter> filterList) { 567e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham final int callbackType = settings.getCallbackType(); 568e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham // If onlost/onfound is requested, a non-empty filter is expected 569ab5267a4033c47761aeabad34d4228e59e6a0b07tturney if ((callbackType & (ScanSettings.CALLBACK_TYPE_FIRST_MATCH 570ab5267a4033c47761aeabad34d4228e59e6a0b07tturney | ScanSettings.CALLBACK_TYPE_MATCH_LOST)) != 0) { 571e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham if (filterList == null) { 572e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham return false; 573e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham } 574e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham for (ScanFilter filter : filterList) { 575e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham if (filter.isAllFieldsEmpty()) { 576e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham return false; 577e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham } 578e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham } 579e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham } 580e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham return true; 581e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham } 582e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham 583e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham private boolean isHardwareResourcesAvailableForScan(ScanSettings settings) { 584e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham final int callbackType = settings.getCallbackType(); 585e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham if ((callbackType & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0 586e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham || (callbackType & ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0) { 587e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham // For onlost/onfound, we required hw support be available 588e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham return (mBluetoothAdapter.isOffloadedFilteringSupported() && 589e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham mBluetoothAdapter.isHardwareTrackingFiltersAvailable()); 590e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham } 591e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham return true; 592e593d0aec6430d98731d9751facd0414a1c9c6a2Prerepa Viswanadham } 5936d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang} 594