• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.gatt;
18 
19 import android.app.AppOpsManager;
20 import android.app.PendingIntent;
21 import android.app.Service;
22 import android.bluetooth.BluetoothAdapter;
23 import android.bluetooth.BluetoothDevice;
24 import android.bluetooth.BluetoothGatt;
25 import android.bluetooth.BluetoothGattCharacteristic;
26 import android.bluetooth.BluetoothGattDescriptor;
27 import android.bluetooth.BluetoothGattService;
28 import android.bluetooth.BluetoothProfile;
29 import android.bluetooth.IBluetoothGatt;
30 import android.bluetooth.IBluetoothGattCallback;
31 import android.bluetooth.IBluetoothGattServerCallback;
32 import android.bluetooth.le.AdvertiseData;
33 import android.bluetooth.le.AdvertisingSetParameters;
34 import android.bluetooth.le.BluetoothLeScanner;
35 import android.bluetooth.le.IAdvertisingSetCallback;
36 import android.bluetooth.le.IPeriodicAdvertisingCallback;
37 import android.bluetooth.le.IScannerCallback;
38 import android.bluetooth.le.PeriodicAdvertisingParameters;
39 import android.bluetooth.le.ResultStorageDescriptor;
40 import android.bluetooth.le.ScanFilter;
41 import android.bluetooth.le.ScanRecord;
42 import android.bluetooth.le.ScanResult;
43 import android.bluetooth.le.ScanSettings;
44 import android.content.Intent;
45 import android.os.Binder;
46 import android.os.IBinder;
47 import android.os.ParcelUuid;
48 import android.os.RemoteException;
49 import android.os.SystemClock;
50 import android.os.WorkSource;
51 import android.provider.Settings;
52 import android.util.Log;
53 
54 import com.android.bluetooth.R;
55 import com.android.bluetooth.Utils;
56 import com.android.bluetooth.btservice.AdapterService;
57 import com.android.bluetooth.btservice.BluetoothProto;
58 import com.android.bluetooth.btservice.ProfileService;
59 import com.android.bluetooth.util.NumberUtils;
60 import com.android.internal.annotations.VisibleForTesting;
61 
62 import java.util.ArrayList;
63 import java.util.Arrays;
64 import java.util.Collections;
65 import java.util.HashMap;
66 import java.util.HashSet;
67 import java.util.List;
68 import java.util.Map;
69 import java.util.Set;
70 import java.util.UUID;
71 import java.util.concurrent.TimeUnit;
72 
73 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
74 /**
75  * Provides Bluetooth Gatt profile, as a service in
76  * the Bluetooth application.
77  * @hide
78  */
79 public class GattService extends ProfileService {
80     private static final boolean DBG = GattServiceConfig.DBG;
81     private static final boolean VDBG = GattServiceConfig.VDBG;
82     private static final String TAG = GattServiceConfig.TAG_PREFIX + "GattService";
83 
84     static final int SCAN_FILTER_ENABLED = 1;
85     static final int SCAN_FILTER_MODIFIED = 2;
86 
87     private static final int MAC_ADDRESS_LENGTH = 6;
88     // Batch scan related constants.
89     private static final int TRUNCATED_RESULT_SIZE = 11;
90     private static final int TIME_STAMP_LENGTH = 2;
91 
92     // onFoundLost related constants
93     private static final int ADVT_STATE_ONFOUND = 0;
94     private static final int ADVT_STATE_ONLOST = 1;
95 
96     private static final int ET_LEGACY_MASK = 0x10;
97 
98     private static final UUID[] HID_UUIDS = {
99         UUID.fromString("00002A4A-0000-1000-8000-00805F9B34FB"),
100         UUID.fromString("00002A4B-0000-1000-8000-00805F9B34FB"),
101         UUID.fromString("00002A4C-0000-1000-8000-00805F9B34FB"),
102         UUID.fromString("00002A4D-0000-1000-8000-00805F9B34FB")
103     };
104 
105     private static final UUID[] FIDO_UUIDS = {
106         UUID.fromString("0000FFFD-0000-1000-8000-00805F9B34FB") // U2F
107     };
108 
109     /**
110      * Keep the arguments passed in for the PendingIntent.
111      */
112     class PendingIntentInfo {
113         PendingIntent intent;
114         ScanSettings settings;
115         List<ScanFilter> filters;
116         String callingPackage;
117 
118         @Override
equals(Object other)119         public boolean equals(Object other) {
120             if (!(other instanceof PendingIntentInfo)) return false;
121             return intent.equals(((PendingIntentInfo) other).intent);
122         }
123     }
124 
125     /**
126      * List of our registered scanners.
127      */
128     class ScannerMap extends ContextMap<IScannerCallback, PendingIntentInfo> {}
129     ScannerMap mScannerMap = new ScannerMap();
130 
131     /**
132      * List of our registered clients.
133      */
134     class ClientMap extends ContextMap<IBluetoothGattCallback, Void> {}
135     ClientMap mClientMap = new ClientMap();
136 
137     /**
138      * List of our registered server apps.
139      */
140     class ServerMap extends ContextMap<IBluetoothGattServerCallback, Void> {}
141     ServerMap mServerMap = new ServerMap();
142 
143     /**
144      * Server handle map.
145      */
146     HandleMap mHandleMap = new HandleMap();
147     private List<UUID> mAdvertisingServiceUuids = new ArrayList<UUID>();
148 
149     private int mMaxScanFilters;
150 
151     static final int NUM_SCAN_EVENTS_KEPT = 20;
152     /**
153      * Internal list of scan events to use with the proto
154      */
155     ArrayList<BluetoothProto.ScanEvent> mScanEvents =
156         new ArrayList<BluetoothProto.ScanEvent>(NUM_SCAN_EVENTS_KEPT);
157 
158     private Map<Integer, List<BluetoothGattService>> gattClientDatabases =
159             new HashMap<Integer, List<BluetoothGattService>>();
160 
161     private AdvertiseManager mAdvertiseManager;
162     private PeriodicScanManager mPeriodicScanManager;
163     private ScanManager mScanManager;
164     private AppOpsManager mAppOps;
165 
166     /**
167      * Reliable write queue
168      */
169     private Set<String> mReliableQueue = new HashSet<String>();
170 
171     static {
classInitNative()172         classInitNative();
173     }
174 
getName()175     protected String getName() {
176         return TAG;
177     }
178 
initBinder()179     protected IProfileServiceBinder initBinder() {
180         return new BluetoothGattBinder(this);
181     }
182 
start()183     protected boolean start() {
184         if (DBG) Log.d(TAG, "start()");
185         initializeNative();
186         mAppOps = getSystemService(AppOpsManager.class);
187         mAdvertiseManager = new AdvertiseManager(this, AdapterService.getAdapterService());
188         mAdvertiseManager.start();
189 
190         mScanManager = new ScanManager(this);
191         mScanManager.start();
192 
193         mPeriodicScanManager = new PeriodicScanManager(AdapterService.getAdapterService());
194         mPeriodicScanManager.start();
195 
196         return true;
197     }
198 
stop()199     protected boolean stop() {
200         if (DBG) Log.d(TAG, "stop()");
201         mScannerMap.clear();
202         mClientMap.clear();
203         mServerMap.clear();
204         mHandleMap.clear();
205         mReliableQueue.clear();
206         if (mAdvertiseManager != null) mAdvertiseManager.cleanup();
207         if (mScanManager != null) mScanManager.cleanup();
208         if (mPeriodicScanManager != null) mPeriodicScanManager.cleanup();
209         return true;
210     }
211 
cleanup()212     protected boolean cleanup() {
213         if (DBG) Log.d(TAG, "cleanup()");
214         cleanupNative();
215         if (mAdvertiseManager != null) mAdvertiseManager.cleanup();
216         if (mScanManager != null) mScanManager.cleanup();
217         if (mPeriodicScanManager != null) mPeriodicScanManager.cleanup();
218         return true;
219     }
220 
permissionCheck(UUID uuid)221     boolean permissionCheck(UUID uuid) {
222         if (isRestrictedCharUuid(uuid) && (0 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED)))
223             return false;
224         else
225             return true;
226     }
227 
permissionCheck(int connId, int handle)228     boolean permissionCheck(int connId, int handle) {
229         List<BluetoothGattService> db = gattClientDatabases.get(connId);
230         if (db == null) return true;
231 
232         for (BluetoothGattService service : db) {
233             for (BluetoothGattCharacteristic characteristic: service.getCharacteristics()) {
234                 if (handle == characteristic.getInstanceId()) {
235                     if ((isRestrictedCharUuid(characteristic.getUuid()) ||
236                          isRestrictedSrvcUuid(service.getUuid())) &&
237                         (0 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED)))
238                         return false;
239                     else
240                         return true;
241                 }
242 
243                 for (BluetoothGattDescriptor descriptor: characteristic.getDescriptors()) {
244                     if (handle == descriptor.getInstanceId()) {
245                         if ((isRestrictedCharUuid(characteristic.getUuid()) ||
246                              isRestrictedSrvcUuid(service.getUuid())) &&
247                             (0 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED)))
248                             return false;
249                         else
250                             return true;
251                     }
252                 }
253             }
254         }
255 
256         return true;
257     }
258 
259     @Override
onStartCommand(Intent intent, int flags, int startId)260     public int onStartCommand(Intent intent, int flags, int startId) {
261         if (GattDebugUtils.handleDebugAction(this, intent)) {
262             return Service.START_NOT_STICKY;
263         }
264         return super.onStartCommand(intent, flags, startId);
265     }
266 
267     /**
268      * DeathReceipient handlers used to unregister applications that
269      * disconnect ungracefully (ie. crash or forced close).
270      */
271 
272     class ScannerDeathRecipient implements IBinder.DeathRecipient {
273         int mScannerId;
274 
ScannerDeathRecipient(int scannerId)275         public ScannerDeathRecipient(int scannerId) {
276             mScannerId = scannerId;
277         }
278 
279         @Override
binderDied()280         public void binderDied() {
281             if (DBG) Log.d(TAG, "Binder is dead - unregistering scanner (" + mScannerId + ")!");
282 
283             if (isScanClient(mScannerId)) {
284                 ScanClient client = new ScanClient(mScannerId);
285                 client.appDied = true;
286                 stopScan(client);
287             }
288         }
289 
isScanClient(int clientIf)290         private boolean isScanClient(int clientIf) {
291             for (ScanClient client : mScanManager.getRegularScanQueue()) {
292                 if (client.scannerId == clientIf) {
293                     return true;
294                 }
295             }
296             for (ScanClient client : mScanManager.getBatchScanQueue()) {
297                 if (client.scannerId == clientIf) {
298                     return true;
299                 }
300             }
301             return false;
302         }
303     }
304 
305     class ServerDeathRecipient implements IBinder.DeathRecipient {
306         int mAppIf;
307 
ServerDeathRecipient(int appIf)308         public ServerDeathRecipient(int appIf) {
309             mAppIf = appIf;
310         }
311 
binderDied()312         public void binderDied() {
313             if (DBG) Log.d(TAG, "Binder is dead - unregistering server (" + mAppIf + ")!");
314             unregisterServer(mAppIf);
315         }
316     }
317 
318     class ClientDeathRecipient implements IBinder.DeathRecipient {
319         int mAppIf;
320 
ClientDeathRecipient(int appIf)321         public ClientDeathRecipient(int appIf) {
322             mAppIf = appIf;
323         }
324 
binderDied()325         public void binderDied() {
326             if (DBG) Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!");
327             unregisterClient(mAppIf);
328         }
329     }
330 
331     /**
332      * Handlers for incoming service calls
333      */
334     private static class BluetoothGattBinder extends IBluetoothGatt.Stub implements IProfileServiceBinder {
335         private GattService mService;
336 
BluetoothGattBinder(GattService svc)337         public BluetoothGattBinder(GattService svc) {
338             mService = svc;
339         }
340 
cleanup()341         public boolean cleanup()  {
342             mService = null;
343             return true;
344         }
345 
getService()346         private GattService getService() {
347             if (mService  != null && mService.isAvailable()) return mService;
348             Log.e(TAG, "getService() - Service requested, but not available!");
349             return null;
350         }
351 
getDevicesMatchingConnectionStates(int[] states)352         public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
353             GattService service = getService();
354             if (service == null) return new ArrayList<BluetoothDevice>();
355             return service.getDevicesMatchingConnectionStates(states);
356         }
357 
registerClient(ParcelUuid uuid, IBluetoothGattCallback callback)358         public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) {
359             GattService service = getService();
360             if (service == null) return;
361             service.registerClient(uuid.getUuid(), callback);
362         }
363 
unregisterClient(int clientIf)364         public void unregisterClient(int clientIf) {
365             GattService service = getService();
366             if (service == null) return;
367             service.unregisterClient(clientIf);
368         }
369 
registerScanner(IScannerCallback callback, WorkSource workSource)370         public void registerScanner(IScannerCallback callback, WorkSource workSource) {
371             GattService service = getService();
372             if (service == null) return;
373             service.registerScanner(callback, workSource);
374         }
375 
unregisterScanner(int scannerId)376         public void unregisterScanner(int scannerId) {
377             GattService service = getService();
378             if (service == null) return;
379             service.unregisterScanner(scannerId);
380         }
381 
382         @Override
startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, List storages, String callingPackage)383         public void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters,
384                 List storages, String callingPackage) {
385             GattService service = getService();
386             if (service == null) return;
387             service.startScan(scannerId, settings, filters, storages, callingPackage);
388         }
389 
390         @Override
startScanForIntent(PendingIntent intent, ScanSettings settings, List<ScanFilter> filters, String callingPackage)391         public void startScanForIntent(PendingIntent intent, ScanSettings settings,
392                 List<ScanFilter> filters, String callingPackage) throws RemoteException {
393             GattService service = getService();
394             if (service == null) return;
395             service.registerPiAndStartScan(intent, settings, filters, callingPackage);
396         }
397 
398         @Override
stopScanForIntent(PendingIntent intent, String callingPackage)399         public void stopScanForIntent(PendingIntent intent, String callingPackage)
400                 throws RemoteException {
401             GattService service = getService();
402             if (service == null) return;
403             service.stopScan(intent, callingPackage);
404         }
405 
stopScan(int scannerId)406         public void stopScan(int scannerId) {
407             GattService service = getService();
408             if (service == null) return;
409             service.stopScan(new ScanClient(scannerId));
410         }
411 
412         @Override
flushPendingBatchResults(int scannerId)413         public void flushPendingBatchResults(int scannerId) {
414             GattService service = getService();
415             if (service == null) return;
416             service.flushPendingBatchResults(scannerId);
417         }
418 
419         @Override
clientConnect( int clientIf, String address, boolean isDirect, int transport, int phy)420         public void clientConnect(
421                 int clientIf, String address, boolean isDirect, int transport, int phy) {
422             GattService service = getService();
423             if (service == null) return;
424             service.clientConnect(clientIf, address, isDirect, transport, phy);
425         }
426 
427         @Override
clientDisconnect(int clientIf, String address)428         public void clientDisconnect(int clientIf, String address) {
429             GattService service = getService();
430             if (service == null) return;
431             service.clientDisconnect(clientIf, address);
432         }
433 
434         @Override
clientSetPreferredPhy( int clientIf, String address, int txPhy, int rxPhy, int phyOptions)435         public void clientSetPreferredPhy(
436                 int clientIf, String address, int txPhy, int rxPhy, int phyOptions) {
437             GattService service = getService();
438             if (service == null) return;
439             service.clientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions);
440         }
441 
442         @Override
clientReadPhy(int clientIf, String address)443         public void clientReadPhy(int clientIf, String address) {
444             GattService service = getService();
445             if (service == null) return;
446             service.clientReadPhy(clientIf, address);
447         }
448 
refreshDevice(int clientIf, String address)449         public void refreshDevice(int clientIf, String address) {
450             GattService service = getService();
451             if (service == null) return;
452             service.refreshDevice(clientIf, address);
453         }
454 
discoverServices(int clientIf, String address)455         public void discoverServices(int clientIf, String address) {
456             GattService service = getService();
457             if (service == null) return;
458             service.discoverServices(clientIf, address);
459         }
460 
discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid)461         public void discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid) {
462             GattService service = getService();
463             if (service == null) return;
464             service.discoverServiceByUuid(clientIf, address, uuid.getUuid());
465         }
466 
readCharacteristic(int clientIf, String address, int handle, int authReq)467         public void readCharacteristic(int clientIf, String address, int handle, int authReq) {
468             GattService service = getService();
469             if (service == null) return;
470             service.readCharacteristic(clientIf, address, handle, authReq);
471         }
472 
readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid, int startHandle, int endHandle, int authReq)473         public void readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid,
474                 int startHandle, int endHandle, int authReq) {
475             GattService service = getService();
476             if (service == null) return;
477             service.readUsingCharacteristicUuid(
478                     clientIf, address, uuid.getUuid(), startHandle, endHandle, authReq);
479         }
480 
writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq, byte[] value)481         public void writeCharacteristic(int clientIf, String address, int handle,
482                              int writeType, int authReq, byte[] value) {
483             GattService service = getService();
484             if (service == null) return;
485             service.writeCharacteristic(clientIf, address, handle, writeType, authReq, value);
486         }
487 
readDescriptor(int clientIf, String address, int handle, int authReq)488         public void readDescriptor(int clientIf, String address, int handle, int authReq) {
489             GattService service = getService();
490             if (service == null) return;
491             service.readDescriptor(clientIf, address, handle, authReq);
492         }
493 
writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value)494         public void writeDescriptor(int clientIf, String address, int handle,
495                                     int authReq, byte[] value) {
496             GattService service = getService();
497             if (service == null) return;
498             service.writeDescriptor(clientIf, address, handle, authReq, value);
499         }
500 
beginReliableWrite(int clientIf, String address)501         public void beginReliableWrite(int clientIf, String address) {
502             GattService service = getService();
503             if (service == null) return;
504             service.beginReliableWrite(clientIf, address);
505         }
506 
endReliableWrite(int clientIf, String address, boolean execute)507         public void endReliableWrite(int clientIf, String address, boolean execute) {
508             GattService service = getService();
509             if (service == null) return;
510             service.endReliableWrite(clientIf, address, execute);
511         }
512 
registerForNotification(int clientIf, String address, int handle, boolean enable)513         public void registerForNotification(int clientIf, String address, int handle, boolean enable) {
514             GattService service = getService();
515             if (service == null) return;
516             service.registerForNotification(clientIf, address, handle, enable);
517         }
518 
readRemoteRssi(int clientIf, String address)519         public void readRemoteRssi(int clientIf, String address) {
520             GattService service = getService();
521             if (service == null) return;
522             service.readRemoteRssi(clientIf, address);
523         }
524 
configureMTU(int clientIf, String address, int mtu)525         public void configureMTU(int clientIf, String address, int mtu) {
526             GattService service = getService();
527             if (service == null) return;
528             service.configureMTU(clientIf, address, mtu);
529         }
530 
connectionParameterUpdate(int clientIf, String address, int connectionPriority)531         public void connectionParameterUpdate(int clientIf, String address,
532                                               int connectionPriority) {
533             GattService service = getService();
534             if (service == null) return;
535             service.connectionParameterUpdate(clientIf, address, connectionPriority);
536         }
537 
registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback)538         public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback) {
539             GattService service = getService();
540             if (service == null) return;
541             service.registerServer(uuid.getUuid(), callback);
542         }
543 
unregisterServer(int serverIf)544         public void unregisterServer(int serverIf) {
545             GattService service = getService();
546             if (service == null) return;
547             service.unregisterServer(serverIf);
548         }
549 
serverConnect(int serverIf, String address, boolean isDirect, int transport)550         public void serverConnect(int serverIf, String address, boolean isDirect, int transport) {
551             GattService service = getService();
552             if (service == null) return;
553             service.serverConnect(serverIf, address, isDirect, transport);
554         }
555 
serverDisconnect(int serverIf, String address)556         public void serverDisconnect(int serverIf, String address) {
557             GattService service = getService();
558             if (service == null) return;
559             service.serverDisconnect(serverIf, address);
560         }
561 
serverSetPreferredPhy( int serverIf, String address, int txPhy, int rxPhy, int phyOptions)562         public void serverSetPreferredPhy(
563                 int serverIf, String address, int txPhy, int rxPhy, int phyOptions) {
564             GattService service = getService();
565             if (service == null) return;
566             service.serverSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions);
567         }
568 
serverReadPhy(int clientIf, String address)569         public void serverReadPhy(int clientIf, String address) {
570             GattService service = getService();
571             if (service == null) return;
572             service.serverReadPhy(clientIf, address);
573         }
574 
addService(int serverIf, BluetoothGattService svc)575         public void addService(int serverIf, BluetoothGattService svc) {
576             GattService service = getService();
577             if (service == null) return;
578 
579             service.addService(serverIf, svc);
580         }
581 
removeService(int serverIf, int handle)582         public void removeService(int serverIf, int handle) {
583             GattService service = getService();
584             if (service == null) return;
585             service.removeService(serverIf, handle);
586         }
587 
clearServices(int serverIf)588         public void clearServices(int serverIf) {
589             GattService service = getService();
590             if (service == null) return;
591             service.clearServices(serverIf);
592         }
593 
sendResponse(int serverIf, String address, int requestId, int status, int offset, byte[] value)594         public void sendResponse(int serverIf, String address, int requestId,
595                                  int status, int offset, byte[] value) {
596             GattService service = getService();
597             if (service == null) return;
598             service.sendResponse(serverIf, address, requestId, status, offset, value);
599         }
600 
sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value)601         public void sendNotification(int serverIf, String address, int handle,
602                                               boolean confirm, byte[] value) {
603             GattService service = getService();
604             if (service == null) return;
605             service.sendNotification(serverIf, address, handle, confirm, value);
606         }
607 
startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, int duration, int maxExtAdvEvents, IAdvertisingSetCallback callback)608         public void startAdvertisingSet(AdvertisingSetParameters parameters,
609                 AdvertiseData advertiseData, AdvertiseData scanResponse,
610                 PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData,
611                 int duration, int maxExtAdvEvents, IAdvertisingSetCallback callback) {
612             GattService service = getService();
613             if (service == null) return;
614             service.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
615                     periodicData, duration, maxExtAdvEvents, callback);
616         }
617 
stopAdvertisingSet(IAdvertisingSetCallback callback)618         public void stopAdvertisingSet(IAdvertisingSetCallback callback) {
619             GattService service = getService();
620             if (service == null) return;
621             service.stopAdvertisingSet(callback);
622         }
623 
getOwnAddress(int advertiserId)624         public void getOwnAddress(int advertiserId) {
625             GattService service = getService();
626             if (service == null) return;
627             service.getOwnAddress(advertiserId);
628         }
629 
enableAdvertisingSet( int advertiserId, boolean enable, int duration, int maxExtAdvEvents)630         public void enableAdvertisingSet(
631                 int advertiserId, boolean enable, int duration, int maxExtAdvEvents) {
632             GattService service = getService();
633             if (service == null) return;
634             service.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents);
635         }
636 
setAdvertisingData(int advertiserId, AdvertiseData data)637         public void setAdvertisingData(int advertiserId, AdvertiseData data) {
638             GattService service = getService();
639             if (service == null) return;
640             service.setAdvertisingData(advertiserId, data);
641         }
642 
setScanResponseData(int advertiserId, AdvertiseData data)643         public void setScanResponseData(int advertiserId, AdvertiseData data) {
644             GattService service = getService();
645             if (service == null) return;
646             service.setScanResponseData(advertiserId, data);
647         }
648 
setAdvertisingParameters( int advertiserId, AdvertisingSetParameters parameters)649         public void setAdvertisingParameters(
650                 int advertiserId, AdvertisingSetParameters parameters) {
651             GattService service = getService();
652             if (service == null) return;
653             service.setAdvertisingParameters(advertiserId, parameters);
654         }
655 
setPeriodicAdvertisingParameters( int advertiserId, PeriodicAdvertisingParameters parameters)656         public void setPeriodicAdvertisingParameters(
657                 int advertiserId, PeriodicAdvertisingParameters parameters) {
658             GattService service = getService();
659             if (service == null) return;
660             service.setPeriodicAdvertisingParameters(advertiserId, parameters);
661         }
662 
setPeriodicAdvertisingData(int advertiserId, AdvertiseData data)663         public void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) {
664             GattService service = getService();
665             if (service == null) return;
666             service.setPeriodicAdvertisingData(advertiserId, data);
667         }
668 
setPeriodicAdvertisingEnable(int advertiserId, boolean enable)669         public void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) {
670             GattService service = getService();
671             if (service == null) return;
672             service.setPeriodicAdvertisingEnable(advertiserId, enable);
673         }
674 
675         @Override
registerSync(ScanResult scanResult, int skip, int timeout, IPeriodicAdvertisingCallback callback)676         public void registerSync(ScanResult scanResult, int skip, int timeout,
677                 IPeriodicAdvertisingCallback callback) {
678             GattService service = getService();
679             if (service == null) return;
680             service.registerSync(scanResult, skip, timeout, callback);
681         }
682 
683         @Override
unregisterSync(IPeriodicAdvertisingCallback callback)684         public void unregisterSync(IPeriodicAdvertisingCallback callback) {
685             GattService service = getService();
686             if (service == null) return;
687             service.unregisterSync(callback);
688         }
689 
690         @Override
disconnectAll()691         public void disconnectAll() {
692             GattService service = getService();
693             if (service == null) return;
694             service.disconnectAll();
695         }
696 
697         @Override
unregAll()698         public void unregAll() {
699             GattService service = getService();
700             if (service == null) return;
701             service.unregAll();
702         }
703 
704         @Override
numHwTrackFiltersAvailable()705         public int numHwTrackFiltersAvailable() {
706             GattService service = getService();
707             if (service == null) return 0;
708             return service.numHwTrackFiltersAvailable();
709         }
710     };
711 
712     /**************************************************************************
713      * Callback functions - CLIENT
714      *************************************************************************/
715 
onScanResult(int event_type, int address_type, String address, int primary_phy, int secondary_phy, int advertising_sid, int tx_power, int rssi, int periodic_adv_int, byte[] adv_data)716     void onScanResult(int event_type, int address_type, String address, int primary_phy,
717             int secondary_phy, int advertising_sid, int tx_power, int rssi, int periodic_adv_int,
718             byte[] adv_data) {
719         if (VDBG) {
720             Log.d(TAG, "onScanResult() - event_type=0x" + Integer.toHexString(event_type)
721                             + ", address_type=" + address_type + ", address=" + address
722                             + ", primary_phy=" + primary_phy + ", secondary_phy=" + secondary_phy
723                             + ", advertising_sid=0x" + Integer.toHexString(advertising_sid)
724                             + ", tx_power=" + tx_power + ", rssi=" + rssi + ", periodic_adv_int=0x"
725                             + Integer.toHexString(periodic_adv_int));
726         }
727         List<UUID> remoteUuids = parseUuids(adv_data);
728         addScanResult();
729 
730         byte[] legacy_adv_data = Arrays.copyOfRange(adv_data, 0, 62);
731 
732         for (ScanClient client : mScanManager.getRegularScanQueue()) {
733             if (client.uuids.length > 0) {
734                 int matches = 0;
735                 for (UUID search : client.uuids) {
736                     for (UUID remote: remoteUuids) {
737                         if (remote.equals(search)) {
738                             ++matches;
739                             break; // Only count 1st match in case of duplicates
740                         }
741                     }
742                 }
743 
744                 if (matches < client.uuids.length) continue;
745             }
746 
747             ScannerMap.App app = mScannerMap.getById(client.scannerId);
748             if (app == null) {
749                 continue;
750             }
751 
752             BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
753 
754             ScanSettings settings = client.settings;
755             byte[] scan_record_data;
756             // This is for compability with applications that assume fixed size scan data.
757             if (settings.getLegacy()) {
758                 if ((event_type & ET_LEGACY_MASK) == 0) {
759                     // If this is legacy scan, but nonlegacy result - skip.
760                     continue;
761                 } else {
762                     // Some apps are used to fixed-size advertise data.
763                     scan_record_data = legacy_adv_data;
764                 }
765             } else {
766                 scan_record_data = adv_data;
767             }
768 
769             ScanResult result = new ScanResult(device, event_type, primary_phy, secondary_phy,
770                     advertising_sid, tx_power, rssi, periodic_adv_int,
771                     ScanRecord.parseFromBytes(scan_record_data),
772                     SystemClock.elapsedRealtimeNanos());
773             // Do no report if location mode is OFF or the client has no location permission
774             // PEERS_MAC_ADDRESS permission holders always get results
775             if (!hasScanResultPermission(client) || !matchesFilters(client, result)) {
776                 continue;
777             }
778 
779             if ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_ALL_MATCHES) == 0) {
780                 continue;
781             }
782 
783             try {
784                 app.appScanStats.addResult();
785                 if (app.callback != null) {
786                     app.callback.onScanResult(result);
787                 } else {
788                     // Send the PendingIntent
789                     ArrayList<ScanResult> results = new ArrayList<>();
790                     results.add(result);
791                     sendResultsByPendingIntent(app.info, results,
792                             ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
793                 }
794             } catch (RemoteException | PendingIntent.CanceledException e) {
795                 Log.e(TAG, "Exception: " + e);
796                 mScannerMap.remove(client.scannerId);
797                 mScanManager.stopScan(client);
798             }
799         }
800     }
801 
sendResultByPendingIntent(PendingIntentInfo pii, ScanResult result, int callbackType, ScanClient client)802     private void sendResultByPendingIntent(PendingIntentInfo pii, ScanResult result,
803             int callbackType, ScanClient client) {
804         ArrayList<ScanResult> results = new ArrayList<>();
805         results.add(result);
806         try {
807             sendResultsByPendingIntent(pii, results, callbackType);
808         } catch (PendingIntent.CanceledException e) {
809             stopScan(client);
810             unregisterScanner(client.scannerId);
811         }
812     }
813 
sendResultsByPendingIntent(PendingIntentInfo pii, ArrayList<ScanResult> results, int callbackType)814     private void sendResultsByPendingIntent(PendingIntentInfo pii, ArrayList<ScanResult> results,
815             int callbackType) throws PendingIntent.CanceledException {
816         Intent extrasIntent = new Intent();
817         extrasIntent.putParcelableArrayListExtra(
818                 BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT, results);
819         extrasIntent.putExtra(
820                 BluetoothLeScanner.EXTRA_CALLBACK_TYPE, callbackType);
821         pii.intent.send(this, 0, extrasIntent);
822     }
823 
sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode)824     private void sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode)
825             throws PendingIntent.CanceledException {
826         Intent extrasIntent = new Intent();
827         extrasIntent.putExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, errorCode);
828         pii.intent.send(this, 0, extrasIntent);
829     }
830 
onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb)831     void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb)
832             throws RemoteException {
833         UUID uuid = new UUID(uuidMsb, uuidLsb);
834         if (DBG) Log.d(TAG, "onScannerRegistered() - UUID=" + uuid
835                 + ", scannerId=" + scannerId + ", status=" + status);
836 
837         // First check the callback map
838         ScannerMap.App cbApp = mScannerMap.getByUuid(uuid);
839         if (cbApp != null) {
840             if (status == 0) {
841                 cbApp.id = scannerId;
842                 // If app is callback based, setup a death recipient. App will initiate the start.
843                 // Otherwise, if PendingIntent based, start the scan directly.
844                 if (cbApp.callback != null) {
845                     cbApp.linkToDeath(new ScannerDeathRecipient(scannerId));
846                 } else {
847                     continuePiStartScan(scannerId, cbApp.info);
848                 }
849             } else {
850                 mScannerMap.remove(scannerId);
851             }
852             if (cbApp.callback != null) {
853                 cbApp.callback.onScannerRegistered(status, scannerId);
854             }
855         }
856     }
857 
858     /** Determines if the given scan client has the appropriate permissions to receive callbacks. */
hasScanResultPermission(final ScanClient client)859     private boolean hasScanResultPermission(final ScanClient client) {
860         final boolean requiresLocationEnabled =
861                 getResources().getBoolean(R.bool.strict_location_check);
862         final boolean locationEnabledSetting = Settings.Secure.getInt(getContentResolver(),
863                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF)
864                 != Settings.Secure.LOCATION_MODE_OFF;
865         final boolean locationEnabled = !requiresLocationEnabled || locationEnabledSetting
866                 || client.legacyForegroundApp;
867         return (client.hasPeersMacAddressPermission
868                 || (client.hasLocationPermission && locationEnabled));
869     }
870 
871     // Check if a scan record matches a specific filters.
matchesFilters(ScanClient client, ScanResult scanResult)872     private boolean matchesFilters(ScanClient client, ScanResult scanResult) {
873         if (client.filters == null || client.filters.isEmpty()) {
874             return true;
875         }
876         for (ScanFilter filter : client.filters) {
877             if (filter.matches(scanResult)) {
878                 return true;
879             }
880         }
881         return false;
882     }
883 
onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb)884     void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb)
885             throws RemoteException {
886         UUID uuid = new UUID(uuidMsb, uuidLsb);
887         if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf);
888         ClientMap.App app = mClientMap.getByUuid(uuid);
889         if (app != null) {
890             if (status == 0) {
891                 app.id = clientIf;
892                 app.linkToDeath(new ClientDeathRecipient(clientIf));
893             } else {
894                 mClientMap.remove(uuid);
895             }
896             app.callback.onClientRegistered(status, clientIf);
897         }
898     }
899 
onConnected(int clientIf, int connId, int status, String address)900     void onConnected(int clientIf, int connId, int status, String address)
901             throws RemoteException  {
902         if (DBG) Log.d(TAG, "onConnected() - clientIf=" + clientIf
903             + ", connId=" + connId + ", address=" + address);
904 
905         if (status == 0) mClientMap.addConnection(clientIf, connId, address);
906         ClientMap.App app = mClientMap.getById(clientIf);
907         if (app != null) {
908             app.callback.onClientConnectionState(status, clientIf,
909                                 (status==BluetoothGatt.GATT_SUCCESS), address);
910         }
911     }
912 
onDisconnected(int clientIf, int connId, int status, String address)913     void onDisconnected(int clientIf, int connId, int status, String address)
914             throws RemoteException {
915         if (DBG) Log.d(TAG, "onDisconnected() - clientIf=" + clientIf
916             + ", connId=" + connId + ", address=" + address);
917 
918         mClientMap.removeConnection(clientIf, connId);
919         ClientMap.App app = mClientMap.getById(clientIf);
920         if (app != null) {
921             app.callback.onClientConnectionState(status, clientIf, false, address);
922         }
923     }
924 
onClientPhyUpdate(int connId, int txPhy, int rxPhy, int status)925     void onClientPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException {
926         if (DBG) Log.d(TAG, "onClientPhyUpdate() - connId=" + connId + ", status=" + status);
927 
928         String address = mClientMap.addressByConnId(connId);
929         if (address == null) return;
930 
931         ClientMap.App app = mClientMap.getByConnId(connId);
932         if (app == null) return;
933 
934         app.callback.onPhyUpdate(address, txPhy, rxPhy, status);
935     }
936 
onClientPhyRead(int connId, int txPhy, int rxPhy, int status)937     void onClientPhyRead(int connId, int txPhy, int rxPhy, int status) throws RemoteException {
938         if (DBG) Log.d(TAG, "onClientPhyRead() - connId=" + connId + ", status=" + status);
939 
940         String address = mClientMap.addressByConnId(connId);
941         if (address == null) return;
942 
943         ClientMap.App app = mClientMap.getByConnId(connId);
944         if (app == null) return;
945 
946         app.callback.onPhyRead(address, txPhy, rxPhy, status);
947     }
948 
onClientConnUpdate(int connId, int interval, int latency, int timeout, int status)949     void onClientConnUpdate(int connId, int interval, int latency, int timeout, int status)
950             throws RemoteException {
951         if (DBG) Log.d(TAG, "onClientConnUpdate() - connId=" + connId + ", status=" + status);
952 
953         String address = mClientMap.addressByConnId(connId);
954         if (address == null) return;
955 
956         ClientMap.App app = mClientMap.getByConnId(connId);
957         if (app == null) return;
958 
959         app.callback.onConnectionUpdated(address, interval, latency, timeout, status);
960     }
961 
onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status)962     void onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException {
963         if (DBG) Log.d(TAG, "onServerPhyUpdate() - connId=" + connId + ", status=" + status);
964 
965         String address = mServerMap.addressByConnId(connId);
966         if (address == null) return;
967 
968         ServerMap.App app = mServerMap.getByConnId(connId);
969         if (app == null) return;
970 
971         app.callback.onPhyUpdate(address, txPhy, rxPhy, status);
972     }
973 
onServerPhyRead(int connId, int txPhy, int rxPhy, int status)974     void onServerPhyRead(int connId, int txPhy, int rxPhy, int status) throws RemoteException {
975         if (DBG) Log.d(TAG, "onServerPhyRead() - connId=" + connId + ", status=" + status);
976 
977         String address = mServerMap.addressByConnId(connId);
978         if (address == null) return;
979 
980         ServerMap.App app = mServerMap.getByConnId(connId);
981         if (app == null) return;
982 
983         app.callback.onPhyRead(address, txPhy, rxPhy, status);
984     }
985 
onServerConnUpdate(int connId, int interval, int latency, int timeout, int status)986     void onServerConnUpdate(int connId, int interval, int latency, int timeout, int status)
987             throws RemoteException {
988         if (DBG) Log.d(TAG, "onServerConnUpdate() - connId=" + connId + ", status=" + status);
989 
990         String address = mServerMap.addressByConnId(connId);
991         if (address == null) return;
992 
993         ServerMap.App app = mServerMap.getByConnId(connId);
994         if (app == null) return;
995 
996         app.callback.onConnectionUpdated(address, interval, latency, timeout, status);
997     }
998 
onSearchCompleted(int connId, int status)999     void onSearchCompleted(int connId, int status) throws RemoteException {
1000         if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status);
1001         // Gatt DB is ready!
1002 
1003         // This callback was called from the jni_workqueue thread. If we make request to the stack
1004         // on the same thread, it might cause deadlock. Schedule request on a new thread instead.
1005         Thread t = new Thread(new Runnable() {
1006             public void run() {
1007                 gattClientGetGattDbNative(connId);
1008             }
1009         });
1010         t.start();
1011     }
1012 
GetSampleGattDbElement()1013     GattDbElement GetSampleGattDbElement() {
1014         return new GattDbElement();
1015     }
1016 
onGetGattDb(int connId, ArrayList<GattDbElement> db)1017     void onGetGattDb(int connId, ArrayList<GattDbElement> db) throws RemoteException {
1018         String address = mClientMap.addressByConnId(connId);
1019 
1020         if (DBG) Log.d(TAG, "onGetGattDb() - address=" + address);
1021 
1022         ClientMap.App app = mClientMap.getByConnId(connId);
1023         if (app == null || app.callback == null) {
1024             Log.e(TAG, "app or callback is null");
1025             return;
1026         }
1027 
1028         List<BluetoothGattService> db_out = new ArrayList<BluetoothGattService>();
1029 
1030         BluetoothGattService currSrvc = null;
1031         BluetoothGattCharacteristic currChar = null;
1032 
1033         for (GattDbElement el: db) {
1034             switch (el.type)
1035             {
1036                 case GattDbElement.TYPE_PRIMARY_SERVICE:
1037                 case GattDbElement.TYPE_SECONDARY_SERVICE:
1038                     if (DBG) Log.d(TAG, "got service with UUID=" + el.uuid);
1039 
1040                     currSrvc = new BluetoothGattService(el.uuid, el.id, el.type);
1041                     db_out.add(currSrvc);
1042                     break;
1043 
1044                 case GattDbElement.TYPE_CHARACTERISTIC:
1045                     if (DBG) Log.d(TAG, "got characteristic with UUID=" + el.uuid);
1046 
1047                     currChar = new BluetoothGattCharacteristic(el.uuid, el.id, el.properties, 0);
1048                     currSrvc.addCharacteristic(currChar);
1049                     break;
1050 
1051                 case GattDbElement.TYPE_DESCRIPTOR:
1052                     if (DBG) Log.d(TAG, "got descriptor with UUID=" + el.uuid);
1053 
1054                     currChar.addDescriptor(new BluetoothGattDescriptor(el.uuid, el.id, 0));
1055                     break;
1056 
1057                 case GattDbElement.TYPE_INCLUDED_SERVICE:
1058                     if (DBG) Log.d(TAG, "got included service with UUID=" + el.uuid);
1059 
1060                     currSrvc.addIncludedService(new BluetoothGattService(el.uuid, el.id, el.type));
1061                     break;
1062 
1063                 default:
1064                     Log.e(TAG, "got unknown element with type=" + el.type + " and UUID=" + el.uuid);
1065             }
1066         }
1067 
1068         // Search is complete when there was error, or nothing more to process
1069         gattClientDatabases.put(connId, db_out);
1070         app.callback.onSearchComplete(address, db_out, 0 /* status */);
1071     }
1072 
onRegisterForNotifications(int connId, int status, int registered, int handle)1073     void onRegisterForNotifications(int connId, int status, int registered, int handle) {
1074         String address = mClientMap.addressByConnId(connId);
1075 
1076         if (DBG) Log.d(TAG, "onRegisterForNotifications() - address=" + address
1077             + ", status=" + status + ", registered=" + registered
1078             + ", handle=" + handle);
1079     }
1080 
onNotify(int connId, String address, int handle, boolean isNotify, byte[] data)1081     void onNotify(int connId, String address, int handle,
1082             boolean isNotify, byte[] data) throws RemoteException {
1083 
1084         if (VDBG) Log.d(TAG, "onNotify() - address=" + address
1085             + ", handle=" + handle + ", length=" + data.length);
1086 
1087         if (!permissionCheck(connId, handle)) {
1088             Log.w(TAG, "onNotify() - permission check failed!");
1089             return;
1090         }
1091 
1092         ClientMap.App app = mClientMap.getByConnId(connId);
1093         if (app != null) {
1094             app.callback.onNotify(address, handle, data);
1095         }
1096     }
1097 
onReadCharacteristic(int connId, int status, int handle, byte[] data)1098     void onReadCharacteristic(int connId, int status, int handle, byte[] data) throws RemoteException {
1099         String address = mClientMap.addressByConnId(connId);
1100 
1101         if (VDBG) Log.d(TAG, "onReadCharacteristic() - address=" + address
1102             + ", status=" + status + ", length=" + data.length);
1103 
1104         ClientMap.App app = mClientMap.getByConnId(connId);
1105         if (app != null) {
1106             app.callback.onCharacteristicRead(address, status, handle, data);
1107         }
1108     }
1109 
onWriteCharacteristic(int connId, int status, int handle)1110     void onWriteCharacteristic(int connId, int status, int handle)
1111             throws RemoteException {
1112         String address = mClientMap.addressByConnId(connId);
1113 
1114         if (VDBG) Log.d(TAG, "onWriteCharacteristic() - address=" + address
1115             + ", status=" + status);
1116 
1117         ClientMap.App app = mClientMap.getByConnId(connId);
1118         if (app == null) return;
1119 
1120         if (!app.isCongested) {
1121             app.callback.onCharacteristicWrite(address, status, handle);
1122         } else {
1123             if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
1124                 status = BluetoothGatt.GATT_SUCCESS;
1125             }
1126             CallbackInfo callbackInfo = new CallbackInfo(address, status, handle);
1127             app.queueCallback(callbackInfo);
1128         }
1129     }
1130 
onExecuteCompleted(int connId, int status)1131     void onExecuteCompleted(int connId, int status) throws RemoteException {
1132         String address = mClientMap.addressByConnId(connId);
1133         if (VDBG) Log.d(TAG, "onExecuteCompleted() - address=" + address
1134             + ", status=" + status);
1135 
1136         ClientMap.App app = mClientMap.getByConnId(connId);
1137         if (app != null) {
1138             app.callback.onExecuteWrite(address, status);
1139         }
1140     }
1141 
onReadDescriptor(int connId, int status, int handle, byte[] data)1142     void onReadDescriptor(int connId, int status, int handle, byte[] data) throws RemoteException {
1143         String address = mClientMap.addressByConnId(connId);
1144 
1145         if (VDBG) Log.d(TAG, "onReadDescriptor() - address=" + address
1146             + ", status=" + status + ", length=" + data.length);
1147 
1148         ClientMap.App app = mClientMap.getByConnId(connId);
1149         if (app != null) {
1150             app.callback.onDescriptorRead(address, status, handle, data);
1151         }
1152     }
1153 
onWriteDescriptor(int connId, int status, int handle)1154     void onWriteDescriptor(int connId, int status, int handle) throws RemoteException {
1155         String address = mClientMap.addressByConnId(connId);
1156 
1157         if (VDBG) Log.d(TAG, "onWriteDescriptor() - address=" + address
1158             + ", status=" + status);
1159 
1160         ClientMap.App app = mClientMap.getByConnId(connId);
1161         if (app != null) {
1162             app.callback.onDescriptorWrite(address, status, handle);
1163         }
1164     }
1165 
onReadRemoteRssi(int clientIf, String address, int rssi, int status)1166     void onReadRemoteRssi(int clientIf, String address,
1167                     int rssi, int status) throws RemoteException{
1168         if (DBG) Log.d(TAG, "onReadRemoteRssi() - clientIf=" + clientIf + " address=" +
1169                      address + ", rssi=" + rssi + ", status=" + status);
1170 
1171         ClientMap.App app = mClientMap.getById(clientIf);
1172         if (app != null) {
1173             app.callback.onReadRemoteRssi(address, rssi, status);
1174         }
1175     }
1176 
onScanFilterEnableDisabled(int action, int status, int clientIf)1177     void onScanFilterEnableDisabled(int action, int status, int clientIf) {
1178         if (DBG) {
1179             Log.d(TAG, "onScanFilterEnableDisabled() - clientIf=" + clientIf + ", status=" + status
1180                     + ", action=" + action);
1181         }
1182         mScanManager.callbackDone(clientIf, status);
1183     }
1184 
onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace)1185     void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) {
1186         if (DBG) {
1187             Log.d(TAG, "onScanFilterParamsConfigured() - clientIf=" + clientIf
1188                     + ", status=" + status + ", action=" + action
1189                     + ", availableSpace=" + availableSpace);
1190         }
1191         mScanManager.callbackDone(clientIf, status);
1192     }
1193 
onScanFilterConfig(int action, int status, int clientIf, int filterType, int availableSpace)1194     void onScanFilterConfig(int action, int status, int clientIf, int filterType,
1195             int availableSpace) {
1196         if (DBG) {
1197             Log.d(TAG, "onScanFilterConfig() - clientIf=" + clientIf + ", action = " + action
1198                     + " status = " + status + ", filterType=" + filterType
1199                     + ", availableSpace=" + availableSpace);
1200         }
1201 
1202         mScanManager.callbackDone(clientIf, status);
1203     }
1204 
onBatchScanStorageConfigured(int status, int clientIf)1205     void onBatchScanStorageConfigured(int status, int clientIf) {
1206         if (DBG) {
1207             Log.d(TAG,
1208                     "onBatchScanStorageConfigured() - clientIf=" + clientIf + ", status=" + status);
1209         }
1210         mScanManager.callbackDone(clientIf, status);
1211     }
1212 
1213     // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped.
onBatchScanStartStopped(int startStopAction, int status, int clientIf)1214     void onBatchScanStartStopped(int startStopAction, int status, int clientIf) {
1215         if (DBG) {
1216             Log.d(TAG, "onBatchScanStartStopped() - clientIf=" + clientIf
1217                     + ", status=" + status + ", startStopAction=" + startStopAction);
1218         }
1219         mScanManager.callbackDone(clientIf, status);
1220     }
1221 
onBatchScanReports(int status, int scannerId, int reportType, int numRecords, byte[] recordData)1222     void onBatchScanReports(int status, int scannerId, int reportType, int numRecords,
1223             byte[] recordData) throws RemoteException {
1224         if (DBG) {
1225             Log.d(TAG, "onBatchScanReports() - scannerId=" + scannerId + ", status=" + status
1226                     + ", reportType=" + reportType + ", numRecords=" + numRecords);
1227         }
1228         mScanManager.callbackDone(scannerId, status);
1229         Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData);
1230         if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) {
1231             // We only support single client for truncated mode.
1232             ScannerMap.App app = mScannerMap.getById(scannerId);
1233             if (app == null) return;
1234             if (app.callback != null) {
1235                 app.callback.onBatchScanResults(new ArrayList<ScanResult>(results));
1236             } else {
1237                 // PendingIntent based
1238                 try {
1239                     sendResultsByPendingIntent(app.info, new ArrayList<ScanResult>(results),
1240                             ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
1241                 } catch (PendingIntent.CanceledException e) {
1242                 }
1243             }
1244         } else {
1245             for (ScanClient client : mScanManager.getFullBatchScanQueue()) {
1246                 // Deliver results for each client.
1247                 deliverBatchScan(client, results);
1248             }
1249         }
1250     }
1251 
sendBatchScanResults( ScannerMap.App app, ScanClient client, ArrayList<ScanResult> results)1252     private void sendBatchScanResults(
1253             ScannerMap.App app, ScanClient client, ArrayList<ScanResult> results) {
1254         try {
1255             if (app.callback != null) {
1256                 app.callback.onBatchScanResults(results);
1257             } else {
1258                 sendResultsByPendingIntent(app.info, results,
1259                         ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
1260             }
1261         } catch (RemoteException | PendingIntent.CanceledException e) {
1262             Log.e(TAG, "Exception: " + e);
1263             mScannerMap.remove(client.scannerId);
1264             mScanManager.stopScan(client);
1265         }
1266     }
1267 
1268     // Check and deliver scan results for different scan clients.
deliverBatchScan(ScanClient client, Set<ScanResult> allResults)1269     private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) throws
1270             RemoteException {
1271         ScannerMap.App app = mScannerMap.getById(client.scannerId);
1272         if (app == null) return;
1273         if (client.filters == null || client.filters.isEmpty()) {
1274             sendBatchScanResults(app, client, new ArrayList<ScanResult>(allResults));
1275             // TODO: Question to reviewer: Shouldn't there be a return here?
1276         }
1277         // Reconstruct the scan results.
1278         ArrayList<ScanResult> results = new ArrayList<ScanResult>();
1279         for (ScanResult scanResult : allResults) {
1280             if (matchesFilters(client, scanResult)) {
1281                 results.add(scanResult);
1282             }
1283         }
1284         sendBatchScanResults(app, client, results);
1285     }
1286 
parseBatchScanResults(int numRecords, int reportType, byte[] batchRecord)1287     private Set<ScanResult> parseBatchScanResults(int numRecords, int reportType,
1288             byte[] batchRecord) {
1289         if (numRecords == 0) {
1290             return Collections.emptySet();
1291         }
1292         if (DBG) Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos());
1293         if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) {
1294             return parseTruncatedResults(numRecords, batchRecord);
1295         } else {
1296             return parseFullResults(numRecords, batchRecord);
1297         }
1298     }
1299 
parseTruncatedResults(int numRecords, byte[] batchRecord)1300     private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) {
1301         if (DBG) Log.d(TAG, "batch record " + Arrays.toString(batchRecord));
1302         Set<ScanResult> results = new HashSet<ScanResult>(numRecords);
1303         long now = SystemClock.elapsedRealtimeNanos();
1304         for (int i = 0; i < numRecords; ++i) {
1305             byte[] record = extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE,
1306                     TRUNCATED_RESULT_SIZE);
1307             byte[] address = extractBytes(record, 0, 6);
1308             reverse(address);
1309             BluetoothDevice device = mAdapter.getRemoteDevice(address);
1310             int rssi = record[8];
1311             long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2));
1312             results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]),
1313                     rssi, timestampNanos));
1314         }
1315         return results;
1316     }
1317 
1318     @VisibleForTesting
parseTimestampNanos(byte[] data)1319     long parseTimestampNanos(byte[] data) {
1320         long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data);
1321         // Timestamp is in every 50 ms.
1322         return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50);
1323     }
1324 
parseFullResults(int numRecords, byte[] batchRecord)1325     private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) {
1326         if (DBG) Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord));
1327         Set<ScanResult> results = new HashSet<ScanResult>(numRecords);
1328         int position = 0;
1329         long now = SystemClock.elapsedRealtimeNanos();
1330         while (position < batchRecord.length) {
1331             byte[] address = extractBytes(batchRecord, position, 6);
1332             // TODO: remove temp hack.
1333             reverse(address);
1334             BluetoothDevice device = mAdapter.getRemoteDevice(address);
1335             position += 6;
1336             // Skip address type.
1337             position++;
1338             // Skip tx power level.
1339             position++;
1340             int rssi = batchRecord[position++];
1341             long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2));
1342             position += 2;
1343 
1344             // Combine advertise packet and scan response packet.
1345             int advertisePacketLen = batchRecord[position++];
1346             byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen);
1347             position += advertisePacketLen;
1348             int scanResponsePacketLen = batchRecord[position++];
1349             byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen);
1350             position += scanResponsePacketLen;
1351             byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen];
1352             System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen);
1353             System.arraycopy(scanResponseBytes, 0, scanRecord,
1354                     advertisePacketLen, scanResponsePacketLen);
1355             if (DBG) Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord));
1356             results.add(new ScanResult(device, ScanRecord.parseFromBytes(scanRecord),
1357                     rssi, timestampNanos));
1358         }
1359         return results;
1360     }
1361 
1362     // Reverse byte array.
reverse(byte[] address)1363     private void reverse(byte[] address) {
1364         int len = address.length;
1365         for (int i = 0; i < len / 2; ++i) {
1366             byte b = address[i];
1367             address[i] = address[len - 1 - i];
1368             address[len - 1 - i] = b;
1369         }
1370     }
1371 
1372     // Helper method to extract bytes from byte array.
extractBytes(byte[] scanRecord, int start, int length)1373     private static byte[] extractBytes(byte[] scanRecord, int start, int length) {
1374         byte[] bytes = new byte[length];
1375         System.arraycopy(scanRecord, start, bytes, 0, length);
1376         return bytes;
1377     }
1378 
onBatchScanThresholdCrossed(int clientIf)1379     void onBatchScanThresholdCrossed(int clientIf) {
1380         if (DBG) {
1381             Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf);
1382         }
1383         flushPendingBatchResults(clientIf);
1384     }
1385 
CreateonTrackAdvFoundLostObject(int client_if, int adv_pkt_len, byte[] adv_pkt, int scan_rsp_len, byte[] scan_rsp, int filt_index, int adv_state, int adv_info_present, String address, int addr_type, int tx_power, int rssi_value, int time_stamp)1386     AdvtFilterOnFoundOnLostInfo CreateonTrackAdvFoundLostObject(int client_if, int adv_pkt_len,
1387                     byte[] adv_pkt, int scan_rsp_len, byte[] scan_rsp, int filt_index, int adv_state,
1388                     int adv_info_present, String address, int addr_type, int tx_power, int rssi_value,
1389                     int time_stamp) {
1390 
1391         return new AdvtFilterOnFoundOnLostInfo(client_if, adv_pkt_len, adv_pkt,
1392                     scan_rsp_len, scan_rsp, filt_index, adv_state,
1393                     adv_info_present, address, addr_type, tx_power,
1394                     rssi_value, time_stamp);
1395     }
1396 
onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo)1397     void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException {
1398         if (DBG) Log.d(TAG, "onTrackAdvFoundLost() - scannerId= " + trackingInfo.getClientIf()
1399                     + " address = " + trackingInfo.getAddress()
1400                     + " adv_state = " + trackingInfo.getAdvState());
1401 
1402         ScannerMap.App app = mScannerMap.getById(trackingInfo.getClientIf());
1403         if (app == null || (app.callback == null && app.info == null)) {
1404             Log.e(TAG, "app or callback is null");
1405             return;
1406         }
1407 
1408         BluetoothDevice device = BluetoothAdapter.getDefaultAdapter()
1409                         .getRemoteDevice(trackingInfo.getAddress());
1410         int advertiserState = trackingInfo.getAdvState();
1411         ScanResult result = new ScanResult(device,
1412                         ScanRecord.parseFromBytes(trackingInfo.getResult()),
1413                         trackingInfo.getRSSIValue(), SystemClock.elapsedRealtimeNanos());
1414 
1415         for (ScanClient client : mScanManager.getRegularScanQueue()) {
1416             if (client.scannerId == trackingInfo.getClientIf()) {
1417                 ScanSettings settings = client.settings;
1418                 if ((advertiserState == ADVT_STATE_ONFOUND)
1419                         && ((settings.getCallbackType()
1420                                 & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0)) {
1421                     if (app.callback != null) {
1422                         app.callback.onFoundOrLost(true, result);
1423                     } else {
1424                         sendResultByPendingIntent(app.info, result,
1425                                 ScanSettings.CALLBACK_TYPE_FIRST_MATCH, client);
1426                     }
1427                 } else if ((advertiserState == ADVT_STATE_ONLOST)
1428                                 && ((settings.getCallbackType()
1429                                         & ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0)) {
1430                     if (app.callback != null) {
1431                         app.callback.onFoundOrLost(false, result);
1432                     } else {
1433                         sendResultByPendingIntent(app.info, result,
1434                                 ScanSettings.CALLBACK_TYPE_MATCH_LOST, client);
1435                     }
1436                 } else {
1437                     if (DBG) {
1438                         Log.d(TAG, "Not reporting onlost/onfound : " + advertiserState
1439                                         + " scannerId = " + client.scannerId + " callbackType "
1440                                         + settings.getCallbackType());
1441                     }
1442                 }
1443             }
1444         }
1445     }
1446 
onScanParamSetupCompleted(int status, int scannerId)1447     void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException {
1448         ScannerMap.App app = mScannerMap.getById(scannerId);
1449         if (app == null || app.callback == null) {
1450             Log.e(TAG, "Advertise app or callback is null");
1451             return;
1452         }
1453         if (DBG) Log.d(TAG, "onScanParamSetupCompleted : " + status);
1454     }
1455 
1456     // callback from ScanManager for dispatch of errors apps.
onScanManagerErrorCallback(int scannerId, int errorCode)1457     void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException {
1458         ScannerMap.App app = mScannerMap.getById(scannerId);
1459         if (app == null || (app.callback == null && app.info == null)) {
1460             Log.e(TAG, "App or callback is null");
1461             return;
1462         }
1463         if (app.callback != null) {
1464             app.callback.onScanManagerErrorCallback(errorCode);
1465         } else {
1466             try {
1467                 sendErrorByPendingIntent(app.info, errorCode);
1468             } catch (PendingIntent.CanceledException e) {
1469                 Log.e(TAG, "Error sending error code via PendingIntent:" + e);
1470             }
1471         }
1472     }
1473 
onConfigureMTU(int connId, int status, int mtu)1474     void onConfigureMTU(int connId, int status, int mtu) throws RemoteException {
1475         String address = mClientMap.addressByConnId(connId);
1476 
1477         if (DBG) Log.d(TAG, "onConfigureMTU() address=" + address + ", status="
1478             + status + ", mtu=" + mtu);
1479 
1480         ClientMap.App app = mClientMap.getByConnId(connId);
1481         if (app != null) {
1482             app.callback.onConfigureMTU(address, mtu, status);
1483         }
1484     }
1485 
onClientCongestion(int connId, boolean congested)1486     void onClientCongestion(int connId, boolean congested) throws RemoteException {
1487         if (VDBG) Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested);
1488 
1489         ClientMap.App app = mClientMap.getByConnId(connId);
1490 
1491         if (app != null) {
1492             app.isCongested = congested;
1493             while(!app.isCongested) {
1494                 CallbackInfo callbackInfo = app.popQueuedCallback();
1495                 if (callbackInfo == null)  return;
1496                 app.callback.onCharacteristicWrite(callbackInfo.address,
1497                         callbackInfo.status, callbackInfo.handle);
1498             }
1499         }
1500     }
1501 
1502     /**************************************************************************
1503      * GATT Service functions - Shared CLIENT/SERVER
1504      *************************************************************************/
1505 
getDevicesMatchingConnectionStates(int[] states)1506     List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
1507         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1508 
1509         final int DEVICE_TYPE_BREDR = 0x1;
1510 
1511         Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice,
1512                                                                  Integer>();
1513 
1514         // Add paired LE devices
1515 
1516         Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices();
1517         for (BluetoothDevice device : bondedDevices) {
1518             if (getDeviceType(device) != DEVICE_TYPE_BREDR) {
1519                 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED);
1520             }
1521         }
1522 
1523         // Add connected deviceStates
1524 
1525         Set<String> connectedDevices = new HashSet<String>();
1526         connectedDevices.addAll(mClientMap.getConnectedDevices());
1527         connectedDevices.addAll(mServerMap.getConnectedDevices());
1528 
1529         for (String address : connectedDevices ) {
1530             BluetoothDevice device = mAdapter.getRemoteDevice(address);
1531             if (device != null) {
1532                 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED);
1533             }
1534         }
1535 
1536         // Create matching device sub-set
1537 
1538         List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();
1539 
1540         for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) {
1541             for(int state : states) {
1542                 if (entry.getValue() == state) {
1543                     deviceList.add(entry.getKey());
1544                 }
1545             }
1546         }
1547 
1548         return deviceList;
1549     }
1550 
registerScanner(IScannerCallback callback, WorkSource workSource)1551     void registerScanner(IScannerCallback callback, WorkSource workSource) {
1552         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1553 
1554         UUID uuid = UUID.randomUUID();
1555         if (DBG) Log.d(TAG, "registerScanner() - UUID=" + uuid);
1556 
1557         if (workSource != null) {
1558             enforceImpersonatationPermission();
1559         }
1560 
1561         mScannerMap.add(uuid, workSource, callback, null, this);
1562         mScanManager.registerScanner(uuid);
1563     }
1564 
unregisterScanner(int scannerId)1565     void unregisterScanner(int scannerId) {
1566         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1567 
1568         if (DBG) Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId);
1569         mScannerMap.remove(scannerId);
1570         mScanManager.unregisterScanner(scannerId);
1571     }
1572 
startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, List<List<ResultStorageDescriptor>> storages, String callingPackage)1573     void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters,
1574             List<List<ResultStorageDescriptor>> storages, String callingPackage) {
1575         if (DBG) Log.d(TAG, "start scan with filters");
1576         enforceAdminPermission();
1577         if (needsPrivilegedPermissionForScan(settings)) {
1578             enforcePrivilegedPermission();
1579         }
1580         final ScanClient scanClient = new ScanClient(scannerId, settings, filters, storages);
1581         scanClient.hasLocationPermission = Utils.checkCallerHasLocationPermission(this, mAppOps,
1582                 callingPackage);
1583         scanClient.hasPeersMacAddressPermission = Utils.checkCallerHasPeersMacAddressPermission(
1584                 this);
1585         scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, callingPackage);
1586 
1587         AppScanStats app = null;
1588         app = mScannerMap.getAppScanStatsById(scannerId);
1589 
1590         if (app != null) {
1591             if (app.isScanningTooFrequently() &&
1592                 checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) != PERMISSION_GRANTED) {
1593                 Log.e(TAG, "App '" + app.appName + "' is scanning too frequently");
1594                 return;
1595             }
1596             scanClient.stats = app;
1597 
1598             boolean isFilteredScan = (filters != null) && !filters.isEmpty();
1599             app.recordScanStart(settings, isFilteredScan);
1600         }
1601 
1602         mScanManager.startScan(scanClient);
1603     }
1604 
registerPiAndStartScan(PendingIntent pendingIntent, ScanSettings settings, List<ScanFilter> filters, String callingPackage)1605     void registerPiAndStartScan(PendingIntent pendingIntent, ScanSettings settings,
1606             List<ScanFilter> filters, String callingPackage) {
1607         if (DBG) Log.d(TAG, "start scan with filters, for PendingIntent");
1608         enforceAdminPermission();
1609         if (needsPrivilegedPermissionForScan(settings)) {
1610             enforcePrivilegedPermission();
1611         }
1612 
1613         UUID uuid = UUID.randomUUID();
1614         if (DBG) Log.d(TAG, "startScan(PI) - UUID=" + uuid);
1615         PendingIntentInfo piInfo = new PendingIntentInfo();
1616         piInfo.intent = pendingIntent;
1617         piInfo.settings = settings;
1618         piInfo.filters = filters;
1619         piInfo.callingPackage = callingPackage;
1620         mScannerMap.add(uuid, null, null, piInfo, this);
1621         mScanManager.registerScanner(uuid);
1622     }
1623 
continuePiStartScan(int scannerId, PendingIntentInfo piInfo)1624     void continuePiStartScan(int scannerId, PendingIntentInfo piInfo) {
1625         final ScanClient scanClient =
1626                 new ScanClient(scannerId, piInfo.settings, piInfo.filters, null);
1627         scanClient.hasLocationPermission =
1628                 true; // Utils.checkCallerHasLocationPermission(this, mAppOps,
1629         // piInfo.callingPackage);
1630         scanClient.hasPeersMacAddressPermission =
1631                 true; // Utils.checkCallerHasPeersMacAddressPermission(
1632         // this);
1633         scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, piInfo.callingPackage);
1634 
1635         AppScanStats app = null;
1636         app = mScannerMap.getAppScanStatsById(scannerId);
1637 
1638         if (app != null) {
1639             if (app.isScanningTooFrequently()
1640                     && checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) != PERMISSION_GRANTED) {
1641                 Log.e(TAG, "App '" + app.appName + "' is scanning too frequently");
1642                 return;
1643             }
1644             scanClient.stats = app;
1645 
1646             boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty();
1647             app.recordScanStart(piInfo.settings, isFilteredScan);
1648         }
1649 
1650         mScanManager.startScan(scanClient);
1651     }
1652 
flushPendingBatchResults(int scannerId)1653     void flushPendingBatchResults(int scannerId) {
1654         if (DBG) Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId);
1655         mScanManager.flushBatchScanResults(new ScanClient(scannerId));
1656     }
1657 
stopScan(ScanClient client)1658     void stopScan(ScanClient client) {
1659         enforceAdminPermission();
1660         int scanQueueSize = mScanManager.getBatchScanQueue().size() +
1661                 mScanManager.getRegularScanQueue().size();
1662         if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize);
1663 
1664         AppScanStats app = null;
1665         app = mScannerMap.getAppScanStatsById(client.scannerId);
1666         if (app != null) app.recordScanStop();
1667 
1668         mScanManager.stopScan(client);
1669     }
1670 
stopScan(PendingIntent intent, String callingPackage)1671     void stopScan(PendingIntent intent, String callingPackage) {
1672         enforceAdminPermission();
1673         PendingIntentInfo pii = new PendingIntentInfo();
1674         pii.intent = intent;
1675         ScannerMap.App app = mScannerMap.getByContextInfo(pii);
1676         if (VDBG) Log.d(TAG, "stopScan(PendingIntent): app found = " + app);
1677         if (app != null) {
1678             final int scannerId = app.id;
1679             stopScan(new ScanClient(scannerId));
1680             // Also unregister the scanner
1681             unregisterScanner(scannerId);
1682         }
1683     }
1684 
disconnectAll()1685     void disconnectAll() {
1686         if (DBG) Log.d(TAG, "disconnectAll()");
1687         Map<Integer, String> connMap = mClientMap.getConnectedMap();
1688         for(Map.Entry<Integer, String> entry:connMap.entrySet()){
1689             if (DBG) Log.d(TAG, "disconnecting addr:" + entry.getValue());
1690             clientDisconnect(entry.getKey(), entry.getValue());
1691             //clientDisconnect(int clientIf, String address)
1692         }
1693     }
1694 
unregAll()1695     void unregAll() {
1696         for (Integer appId : mClientMap.getAllAppsIds()) {
1697             if (DBG) Log.d(TAG, "unreg:" + appId);
1698             unregisterClient(appId);
1699         }
1700     }
1701 
1702     /**************************************************************************
1703      * PERIODIC SCANNING
1704      *************************************************************************/
registerSync( ScanResult scanResult, int skip, int timeout, IPeriodicAdvertisingCallback callback)1705     void registerSync(
1706             ScanResult scanResult, int skip, int timeout, IPeriodicAdvertisingCallback callback) {
1707         enforceAdminPermission();
1708         mPeriodicScanManager.startSync(scanResult, skip, timeout, callback);
1709     }
1710 
unregisterSync(IPeriodicAdvertisingCallback callback)1711     void unregisterSync(IPeriodicAdvertisingCallback callback) {
1712         enforceAdminPermission();
1713         mPeriodicScanManager.stopSync(callback);
1714     }
1715 
1716     /**************************************************************************
1717      * ADVERTISING SET
1718      *************************************************************************/
startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, int duration, int maxExtAdvEvents, IAdvertisingSetCallback callback)1719     void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData,
1720             AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters,
1721             AdvertiseData periodicData, int duration, int maxExtAdvEvents,
1722             IAdvertisingSetCallback callback) {
1723         enforceAdminPermission();
1724         mAdvertiseManager.startAdvertisingSet(parameters, advertiseData, scanResponse,
1725                 periodicParameters, periodicData, duration, maxExtAdvEvents, callback);
1726     }
1727 
stopAdvertisingSet(IAdvertisingSetCallback callback)1728     void stopAdvertisingSet(IAdvertisingSetCallback callback) {
1729         enforceAdminPermission();
1730         mAdvertiseManager.stopAdvertisingSet(callback);
1731     }
1732 
getOwnAddress(int advertiserId)1733     void getOwnAddress(int advertiserId) {
1734         enforcePrivilegedPermission();
1735         mAdvertiseManager.getOwnAddress(advertiserId);
1736     }
1737 
enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents)1738     void enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents) {
1739         enforceAdminPermission();
1740         mAdvertiseManager.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents);
1741     }
1742 
setAdvertisingData(int advertiserId, AdvertiseData data)1743     void setAdvertisingData(int advertiserId, AdvertiseData data) {
1744         enforceAdminPermission();
1745         mAdvertiseManager.setAdvertisingData(advertiserId, data);
1746     }
1747 
setScanResponseData(int advertiserId, AdvertiseData data)1748     void setScanResponseData(int advertiserId, AdvertiseData data) {
1749         enforceAdminPermission();
1750         mAdvertiseManager.setScanResponseData(advertiserId, data);
1751     }
1752 
setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters)1753     void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters) {
1754         enforceAdminPermission();
1755         mAdvertiseManager.setAdvertisingParameters(advertiserId, parameters);
1756     }
1757 
setPeriodicAdvertisingParameters( int advertiserId, PeriodicAdvertisingParameters parameters)1758     void setPeriodicAdvertisingParameters(
1759             int advertiserId, PeriodicAdvertisingParameters parameters) {
1760         enforceAdminPermission();
1761         mAdvertiseManager.setPeriodicAdvertisingParameters(advertiserId, parameters);
1762     }
1763 
setPeriodicAdvertisingData(int advertiserId, AdvertiseData data)1764     void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data) {
1765         enforceAdminPermission();
1766         mAdvertiseManager.setPeriodicAdvertisingData(advertiserId, data);
1767     }
1768 
setPeriodicAdvertisingEnable(int advertiserId, boolean enable)1769     void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) {
1770         enforceAdminPermission();
1771         mAdvertiseManager.setPeriodicAdvertisingEnable(advertiserId, enable);
1772     }
1773 
1774     /**************************************************************************
1775      * GATT Service functions - CLIENT
1776      *************************************************************************/
1777 
registerClient(UUID uuid, IBluetoothGattCallback callback)1778     void registerClient(UUID uuid, IBluetoothGattCallback callback) {
1779         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1780 
1781         if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid);
1782         mClientMap.add(uuid, null, callback, null, this);
1783         gattClientRegisterAppNative(uuid.getLeastSignificantBits(),
1784                                     uuid.getMostSignificantBits());
1785     }
1786 
unregisterClient(int clientIf)1787     void unregisterClient(int clientIf) {
1788         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1789 
1790         if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf);
1791         mClientMap.remove(clientIf);
1792         gattClientUnregisterAppNative(clientIf);
1793     }
1794 
clientConnect(int clientIf, String address, boolean isDirect, int transport, int phy)1795     void clientConnect(int clientIf, String address, boolean isDirect, int transport, int phy) {
1796         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1797 
1798         if (DBG) {
1799             Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect + ", phy= "
1800                             + phy);
1801         }
1802         gattClientConnectNative(clientIf, address, isDirect, transport, phy);
1803     }
1804 
clientDisconnect(int clientIf, String address)1805     void clientDisconnect(int clientIf, String address) {
1806         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1807 
1808         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1809         if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId);
1810 
1811         gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0);
1812     }
1813 
clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions)1814     void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions) {
1815         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1816 
1817         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1818         if (connId == null) {
1819             if (DBG) Log.d(TAG, "clientSetPreferredPhy() - no connection to " + address);
1820             return;
1821         }
1822 
1823         if (DBG) Log.d(TAG, "clientSetPreferredPhy() - address=" + address + ", connId=" + connId);
1824         gattClientSetPreferredPhyNative(clientIf, connId, txPhy, rxPhy, phyOptions);
1825     }
1826 
clientReadPhy(int clientIf, String address)1827     void clientReadPhy(int clientIf, String address) {
1828         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1829 
1830         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1831         if (connId == null) {
1832             if (DBG) Log.d(TAG, "clientReadPhy() - no connection to " + address);
1833             return;
1834         }
1835 
1836         if (DBG) Log.d(TAG, "clientReadPhy() - address=" + address + ", connId=" + connId);
1837         gattClientReadPhyNative(clientIf, connId);
1838     }
1839 
numHwTrackFiltersAvailable()1840     int numHwTrackFiltersAvailable() {
1841         return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements()
1842                     - mScanManager.getCurrentUsedTrackingAdvertisement());
1843     }
1844 
getRegisteredServiceUuids()1845     synchronized List<ParcelUuid> getRegisteredServiceUuids() {
1846         Utils.enforceAdminPermission(this);
1847         List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>();
1848         for (HandleMap.Entry entry : mHandleMap.mEntries) {
1849             serviceUuids.add(new ParcelUuid(entry.uuid));
1850         }
1851         return serviceUuids;
1852     }
1853 
getConnectedDevices()1854     List<String> getConnectedDevices() {
1855         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1856 
1857         Set<String> connectedDevAddress = new HashSet<String>();
1858         connectedDevAddress.addAll(mClientMap.getConnectedDevices());
1859         connectedDevAddress.addAll(mServerMap.getConnectedDevices());
1860         List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress);
1861         return connectedDeviceList;
1862     }
1863 
refreshDevice(int clientIf, String address)1864     void refreshDevice(int clientIf, String address) {
1865         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1866 
1867         if (DBG) Log.d(TAG, "refreshDevice() - address=" + address);
1868         gattClientRefreshNative(clientIf, address);
1869     }
1870 
discoverServices(int clientIf, String address)1871     void discoverServices(int clientIf, String address) {
1872         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1873 
1874         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1875         if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId);
1876 
1877         if (connId != null)
1878             gattClientSearchServiceNative(connId, true, 0, 0);
1879         else
1880             Log.e(TAG, "discoverServices() - No connection for " + address + "...");
1881     }
1882 
discoverServiceByUuid(int clientIf, String address, UUID uuid)1883     void discoverServiceByUuid(int clientIf, String address, UUID uuid) {
1884         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1885 
1886         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1887         if (connId != null)
1888             gattClientDiscoverServiceByUuidNative(
1889                     connId, uuid.getLeastSignificantBits(), uuid.getMostSignificantBits());
1890         else
1891             Log.e(TAG, "discoverServiceByUuid() - No connection for " + address + "...");
1892     }
1893 
readCharacteristic(int clientIf, String address, int handle, int authReq)1894     void readCharacteristic(int clientIf, String address, int handle, int authReq) {
1895         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1896 
1897         if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address);
1898 
1899         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1900         if (connId == null) {
1901             Log.e(TAG, "readCharacteristic() - No connection for " + address + "...");
1902             return;
1903         }
1904 
1905         if (!permissionCheck(connId, handle)) {
1906             Log.w(TAG, "readCharacteristic() - permission check failed!");
1907             return;
1908         }
1909 
1910         gattClientReadCharacteristicNative(connId, handle, authReq);
1911     }
1912 
readUsingCharacteristicUuid( int clientIf, String address, UUID uuid, int startHandle, int endHandle, int authReq)1913     void readUsingCharacteristicUuid(
1914             int clientIf, String address, UUID uuid, int startHandle, int endHandle, int authReq) {
1915         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1916 
1917         if (VDBG) Log.d(TAG, "readUsingCharacteristicUuid() - address=" + address);
1918 
1919         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1920         if (connId == null) {
1921             Log.e(TAG, "readUsingCharacteristicUuid() - No connection for " + address + "...");
1922             return;
1923         }
1924 
1925         if (!permissionCheck(uuid)) {
1926             Log.w(TAG, "readUsingCharacteristicUuid() - permission check failed!");
1927             return;
1928         }
1929 
1930         gattClientReadUsingCharacteristicUuidNative(connId, uuid.getLeastSignificantBits(),
1931                 uuid.getMostSignificantBits(), startHandle, endHandle, authReq);
1932     }
1933 
writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq, byte[] value)1934     void writeCharacteristic(int clientIf, String address, int handle, int writeType,
1935                              int authReq, byte[] value) {
1936         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1937 
1938         if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address);
1939 
1940         if (mReliableQueue.contains(address)) writeType = 3; // Prepared write
1941 
1942         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1943         if (connId == null) {
1944             Log.e(TAG, "writeCharacteristic() - No connection for " + address + "...");
1945             return;
1946         }
1947 
1948         if (!permissionCheck(connId, handle)) {
1949             Log.w(TAG, "writeCharacteristic() - permission check failed!");
1950             return;
1951         }
1952 
1953         gattClientWriteCharacteristicNative(connId, handle, writeType, authReq, value);
1954     }
1955 
readDescriptor(int clientIf, String address, int handle, int authReq)1956     void readDescriptor(int clientIf, String address, int handle, int authReq) {
1957         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1958 
1959         if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address);
1960 
1961         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1962         if (connId == null) {
1963             Log.e(TAG, "readDescriptor() - No connection for " + address + "...");
1964             return;
1965         }
1966 
1967         if (!permissionCheck(connId, handle)) {
1968             Log.w(TAG, "readDescriptor() - permission check failed!");
1969             return;
1970         }
1971 
1972         gattClientReadDescriptorNative(connId, handle, authReq);
1973     };
1974 
writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value)1975     void writeDescriptor(int clientIf, String address, int handle,
1976                             int authReq, byte[] value) {
1977         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1978         if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address);
1979 
1980         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1981         if (connId == null) {
1982             Log.e(TAG, "writeDescriptor() - No connection for " + address + "...");
1983             return;
1984         }
1985 
1986         if (!permissionCheck(connId, handle)) {
1987             Log.w(TAG, "writeDescriptor() - permission check failed!");
1988             return;
1989         }
1990 
1991         gattClientWriteDescriptorNative(connId, handle, authReq, value);
1992     }
1993 
beginReliableWrite(int clientIf, String address)1994     void beginReliableWrite(int clientIf, String address) {
1995         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1996 
1997         if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address);
1998         mReliableQueue.add(address);
1999     }
2000 
endReliableWrite(int clientIf, String address, boolean execute)2001     void endReliableWrite(int clientIf, String address, boolean execute) {
2002         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2003 
2004         if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address
2005                                 + " execute: " + execute);
2006         mReliableQueue.remove(address);
2007 
2008         Integer connId = mClientMap.connIdByAddress(clientIf, address);
2009         if (connId != null) gattClientExecuteWriteNative(connId, execute);
2010     }
2011 
registerForNotification(int clientIf, String address, int handle, boolean enable)2012     void registerForNotification(int clientIf, String address, int handle, boolean enable) {
2013         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2014 
2015         if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable);
2016 
2017         Integer connId = mClientMap.connIdByAddress(clientIf, address);
2018         if (connId == null) {
2019             Log.e(TAG, "registerForNotification() - No connection for " + address + "...");
2020             return;
2021         }
2022 
2023         if (!permissionCheck(connId, handle)) {
2024             Log.w(TAG, "registerForNotification() - permission check failed!");
2025             return;
2026         }
2027 
2028         gattClientRegisterForNotificationsNative(clientIf, address, handle, enable);
2029     }
2030 
readRemoteRssi(int clientIf, String address)2031     void readRemoteRssi(int clientIf, String address) {
2032         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2033 
2034         if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address);
2035         gattClientReadRemoteRssiNative(clientIf, address);
2036     }
2037 
configureMTU(int clientIf, String address, int mtu)2038     void configureMTU(int clientIf, String address, int mtu) {
2039         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2040 
2041         if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu);
2042         Integer connId = mClientMap.connIdByAddress(clientIf, address);
2043         if (connId != null) {
2044             gattClientConfigureMTUNative(connId, mtu);
2045         } else {
2046             Log.e(TAG, "configureMTU() - No connection for " + address + "...");
2047         }
2048     }
2049 
connectionParameterUpdate(int clientIf, String address, int connectionPriority)2050     void connectionParameterUpdate(int clientIf, String address, int connectionPriority) {
2051         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2052 
2053         int minInterval;
2054         int maxInterval;
2055 
2056         // Slave latency
2057         int latency;
2058 
2059         // Link supervision timeout is measured in N * 10ms
2060         int timeout = 2000; // 20s
2061 
2062         switch (connectionPriority)
2063         {
2064             case BluetoothGatt.CONNECTION_PRIORITY_HIGH:
2065                 minInterval = getResources().getInteger(R.integer.gatt_high_priority_min_interval);
2066                 maxInterval = getResources().getInteger(R.integer.gatt_high_priority_max_interval);
2067                 latency = getResources().getInteger(R.integer.gatt_high_priority_latency);
2068                 break;
2069 
2070             case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER:
2071                 minInterval = getResources().getInteger(R.integer.gatt_low_power_min_interval);
2072                 maxInterval = getResources().getInteger(R.integer.gatt_low_power_max_interval);
2073                 latency = getResources().getInteger(R.integer.gatt_low_power_latency);
2074                 break;
2075 
2076             default:
2077                 // Using the values for CONNECTION_PRIORITY_BALANCED.
2078                 minInterval =
2079                         getResources().getInteger(R.integer.gatt_balanced_priority_min_interval);
2080                 maxInterval =
2081                         getResources().getInteger(R.integer.gatt_balanced_priority_max_interval);
2082                 latency = getResources().getInteger(R.integer.gatt_balanced_priority_latency);
2083                 break;
2084         }
2085 
2086         if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address
2087             + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval);
2088         gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval,
2089                                             latency, timeout);
2090     }
2091 
2092     /**************************************************************************
2093      * Callback functions - SERVER
2094      *************************************************************************/
2095 
onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb)2096     void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb)
2097             throws RemoteException {
2098 
2099         UUID uuid = new UUID(uuidMsb, uuidLsb);
2100         if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf);
2101         ServerMap.App app = mServerMap.getByUuid(uuid);
2102         if (app != null) {
2103             app.id = serverIf;
2104             app.linkToDeath(new ServerDeathRecipient(serverIf));
2105             app.callback.onServerRegistered(status, serverIf);
2106         }
2107     }
2108 
onServiceAdded(int status, int serverIf, List<GattDbElement> service)2109     void onServiceAdded(int status, int serverIf, List<GattDbElement> service)
2110                         throws RemoteException {
2111         if (DBG) Log.d(TAG, "onServiceAdded(), status=" + status);
2112 
2113         if (status != 0) {
2114             return;
2115         }
2116 
2117         GattDbElement svcEl = service.get(0);
2118         int srvcHandle = svcEl.attributeHandle;
2119 
2120         BluetoothGattService svc = null;
2121 
2122         for (GattDbElement el : service) {
2123             if (el.type == GattDbElement.TYPE_PRIMARY_SERVICE) {
2124                 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid,
2125                         BluetoothGattService.SERVICE_TYPE_PRIMARY, 0, false);
2126                 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle,
2127                         BluetoothGattService.SERVICE_TYPE_PRIMARY);
2128             } else if (el.type == GattDbElement.TYPE_SECONDARY_SERVICE) {
2129                 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid,
2130                         BluetoothGattService.SERVICE_TYPE_SECONDARY, 0, false);
2131                 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle,
2132                         BluetoothGattService.SERVICE_TYPE_SECONDARY);
2133             } else if (el.type == GattDbElement.TYPE_CHARACTERISTIC) {
2134                 mHandleMap.addCharacteristic(serverIf, el.attributeHandle, el.uuid, srvcHandle);
2135                 svc.addCharacteristic(new BluetoothGattCharacteristic(el.uuid,
2136                         el.attributeHandle, el.properties, el.permissions));
2137             } else if (el.type == GattDbElement.TYPE_DESCRIPTOR) {
2138                 mHandleMap.addDescriptor(serverIf, el.attributeHandle, el.uuid, srvcHandle);
2139                 List<BluetoothGattCharacteristic> chars = svc.getCharacteristics();
2140                 chars.get(chars.size()-1).addDescriptor(
2141                         new BluetoothGattDescriptor(el.uuid, el.attributeHandle, el.permissions));
2142             }
2143         }
2144         mHandleMap.setStarted(serverIf, srvcHandle, true);
2145 
2146         ServerMap.App app = mServerMap.getById(serverIf);
2147         if (app != null) {
2148                 app.callback.onServiceAdded(status, svc);
2149         }
2150     }
2151 
onServiceStopped(int status, int serverIf, int srvcHandle)2152     void onServiceStopped(int status, int serverIf, int srvcHandle)
2153             throws RemoteException {
2154         if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle
2155             + ", status=" + status);
2156         if (status == 0)
2157             mHandleMap.setStarted(serverIf, srvcHandle, false);
2158         stopNextService(serverIf, status);
2159     }
2160 
onServiceDeleted(int status, int serverIf, int srvcHandle)2161     void onServiceDeleted(int status, int serverIf, int srvcHandle) {
2162         if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle
2163             + ", status=" + status);
2164         mHandleMap.deleteService(serverIf, srvcHandle);
2165     }
2166 
onClientConnected(String address, boolean connected, int connId, int serverIf)2167     void onClientConnected(String address, boolean connected, int connId, int serverIf)
2168             throws RemoteException {
2169 
2170         if (DBG) Log.d(TAG, "onClientConnected() connId=" + connId
2171             + ", address=" + address + ", connected=" + connected);
2172 
2173         ServerMap.App app = mServerMap.getById(serverIf);
2174         if (app == null) return;
2175 
2176         if (connected) {
2177             mServerMap.addConnection(serverIf, connId, address);
2178         } else {
2179             mServerMap.removeConnection(serverIf, connId);
2180         }
2181 
2182         app.callback.onServerConnectionState((byte)0, serverIf, connected, address);
2183     }
2184 
onServerReadCharacteristic(String address, int connId, int transId, int handle, int offset, boolean isLong)2185     void onServerReadCharacteristic(String address, int connId, int transId,
2186                             int handle, int offset, boolean isLong)
2187                             throws RemoteException {
2188         if (VDBG) Log.d(TAG, "onServerReadCharacteristic() connId=" + connId
2189             + ", address=" + address + ", handle=" + handle
2190             + ", requestId=" + transId + ", offset=" + offset);
2191 
2192         HandleMap.Entry entry = mHandleMap.getByHandle(handle);
2193         if (entry == null) return;
2194 
2195         mHandleMap.addRequest(transId, handle);
2196 
2197         ServerMap.App app = mServerMap.getById(entry.serverIf);
2198         if (app == null) return;
2199 
2200         app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, handle);
2201     }
2202 
onServerReadDescriptor(String address, int connId, int transId, int handle, int offset, boolean isLong)2203     void onServerReadDescriptor(String address, int connId, int transId,
2204                             int handle, int offset, boolean isLong)
2205                             throws RemoteException {
2206         if (VDBG) Log.d(TAG, "onServerReadDescriptor() connId=" + connId
2207             + ", address=" + address + ", handle=" + handle
2208             + ", requestId=" + transId + ", offset=" + offset);
2209 
2210         HandleMap.Entry entry = mHandleMap.getByHandle(handle);
2211         if (entry == null) return;
2212 
2213         mHandleMap.addRequest(transId, handle);
2214 
2215         ServerMap.App app = mServerMap.getById(entry.serverIf);
2216         if (app == null) return;
2217 
2218         app.callback.onDescriptorReadRequest(address, transId, offset, isLong, handle);
2219     }
2220 
onServerWriteCharacteristic(String address, int connId, int transId, int handle, int offset, int length, boolean needRsp, boolean isPrep, byte[] data)2221     void onServerWriteCharacteristic(String address, int connId, int transId,
2222                             int handle, int offset, int length,
2223                             boolean needRsp, boolean isPrep,
2224                             byte[] data)
2225                             throws RemoteException {
2226         if (VDBG) Log.d(TAG, "onServerWriteCharacteristic() connId=" + connId
2227             + ", address=" + address + ", handle=" + handle
2228             + ", requestId=" + transId + ", isPrep=" + isPrep
2229             + ", offset=" + offset);
2230 
2231         HandleMap.Entry entry = mHandleMap.getByHandle(handle);
2232         if (entry == null) return;
2233 
2234         mHandleMap.addRequest(transId, handle);
2235 
2236         ServerMap.App app = mServerMap.getById(entry.serverIf);
2237         if (app == null) return;
2238 
2239         app.callback.onCharacteristicWriteRequest(address, transId,
2240                     offset, length, isPrep, needRsp, handle, data);
2241     }
2242 
onServerWriteDescriptor(String address, int connId, int transId, int handle, int offset, int length, boolean needRsp, boolean isPrep, byte[] data)2243     void onServerWriteDescriptor(String address, int connId, int transId,
2244                             int handle, int offset, int length,
2245                             boolean needRsp, boolean isPrep,
2246                             byte[] data)
2247                             throws RemoteException {
2248         if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId
2249             + ", address=" + address + ", handle=" + handle
2250             + ", requestId=" + transId + ", isPrep=" + isPrep
2251             + ", offset=" + offset);
2252 
2253         HandleMap.Entry entry = mHandleMap.getByHandle(handle);
2254         if (entry == null) return;
2255 
2256         mHandleMap.addRequest(transId, handle);
2257 
2258         ServerMap.App app = mServerMap.getById(entry.serverIf);
2259         if (app == null) return;
2260 
2261         app.callback.onDescriptorWriteRequest(address, transId,
2262                     offset, length, isPrep, needRsp, handle, data);
2263     }
2264 
onExecuteWrite(String address, int connId, int transId, int execWrite)2265     void onExecuteWrite(String address, int connId, int transId, int execWrite)
2266             throws RemoteException {
2267         if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId
2268             + ", address=" + address + ", transId=" + transId);
2269 
2270         ServerMap.App app = mServerMap.getByConnId(connId);
2271         if (app == null) return;
2272 
2273         app.callback.onExecuteWrite(address, transId, execWrite == 1);
2274     }
2275 
onResponseSendCompleted(int status, int attrHandle)2276     void onResponseSendCompleted(int status, int attrHandle) {
2277         if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle);
2278     }
2279 
onNotificationSent(int connId, int status)2280     void onNotificationSent(int connId, int status) throws RemoteException {
2281         if (VDBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status);
2282 
2283         String address = mServerMap.addressByConnId(connId);
2284         if (address == null) return;
2285 
2286         ServerMap.App app = mServerMap.getByConnId(connId);
2287         if (app == null) return;
2288 
2289         if (!app.isCongested) {
2290             app.callback.onNotificationSent(address, status);
2291         } else {
2292             if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
2293                 status = BluetoothGatt.GATT_SUCCESS;
2294             }
2295             app.queueCallback(new CallbackInfo(address, status));
2296         }
2297     }
2298 
onServerCongestion(int connId, boolean congested)2299     void onServerCongestion(int connId, boolean congested) throws RemoteException {
2300         if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested);
2301 
2302         ServerMap.App app = mServerMap.getByConnId(connId);
2303         if (app == null) return;
2304 
2305         app.isCongested = congested;
2306         while(!app.isCongested) {
2307             CallbackInfo callbackInfo = app.popQueuedCallback();
2308             if (callbackInfo == null) return;
2309             app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status);
2310         }
2311     }
2312 
onMtuChanged(int connId, int mtu)2313     void onMtuChanged(int connId, int mtu) throws RemoteException {
2314         if (DBG) Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu);
2315 
2316         String address = mServerMap.addressByConnId(connId);
2317         if (address == null) return;
2318 
2319         ServerMap.App app = mServerMap.getByConnId(connId);
2320         if (app == null) return;
2321 
2322         app.callback.onMtuChanged(address, mtu);
2323     }
2324 
2325     /**************************************************************************
2326      * GATT Service functions - SERVER
2327      *************************************************************************/
2328 
registerServer(UUID uuid, IBluetoothGattServerCallback callback)2329     void registerServer(UUID uuid, IBluetoothGattServerCallback callback) {
2330         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2331 
2332         if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid);
2333         mServerMap.add(uuid, null, callback, null, this);
2334         gattServerRegisterAppNative(uuid.getLeastSignificantBits(),
2335                                     uuid.getMostSignificantBits());
2336     }
2337 
unregisterServer(int serverIf)2338     void unregisterServer(int serverIf) {
2339         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2340 
2341         if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf);
2342 
2343         deleteServices(serverIf);
2344 
2345         mServerMap.remove(serverIf);
2346         gattServerUnregisterAppNative(serverIf);
2347     }
2348 
serverConnect(int serverIf, String address, boolean isDirect, int transport)2349     void serverConnect(int serverIf, String address, boolean isDirect, int transport) {
2350         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2351 
2352         if (DBG) Log.d(TAG, "serverConnect() - address=" + address);
2353         gattServerConnectNative(serverIf, address, isDirect,transport);
2354     }
2355 
serverDisconnect(int serverIf, String address)2356     void serverDisconnect(int serverIf, String address) {
2357         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2358 
2359         Integer connId = mServerMap.connIdByAddress(serverIf, address);
2360         if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId);
2361 
2362         gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0);
2363     }
2364 
serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions)2365     void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions) {
2366         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2367 
2368         Integer connId = mServerMap.connIdByAddress(serverIf, address);
2369         if (connId == null) {
2370             if (DBG) Log.d(TAG, "serverSetPreferredPhy() - no connection to " + address);
2371             return;
2372         }
2373 
2374         if (DBG) Log.d(TAG, "serverSetPreferredPhy() - address=" + address + ", connId=" + connId);
2375         gattServerSetPreferredPhyNative(serverIf, connId, txPhy, rxPhy, phyOptions);
2376     }
2377 
serverReadPhy(int serverIf, String address)2378     void serverReadPhy(int serverIf, String address) {
2379         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2380 
2381         Integer connId = mServerMap.connIdByAddress(serverIf, address);
2382         if (connId == null) {
2383             if (DBG) Log.d(TAG, "serverReadPhy() - no connection to " + address);
2384             return;
2385         }
2386 
2387         if (DBG) Log.d(TAG, "serverReadPhy() - address=" + address + ", connId=" + connId);
2388         gattServerReadPhyNative(serverIf, connId);
2389     }
2390 
addService(int serverIf, BluetoothGattService service)2391     void addService(int serverIf, BluetoothGattService service) {
2392         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2393 
2394         if (DBG) Log.d(TAG, "addService() - uuid=" + service.getUuid());
2395 
2396         List<GattDbElement> db = new ArrayList<GattDbElement>();
2397 
2398         if (service.getType() == BluetoothGattService.SERVICE_TYPE_PRIMARY)
2399             db.add(GattDbElement.createPrimaryService(service.getUuid()));
2400         else db.add(GattDbElement.createSecondaryService(service.getUuid()));
2401 
2402         for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
2403             int permission = ((characteristic.getKeySize() - 7) << 12)
2404                                     + characteristic.getPermissions();
2405             db.add(GattDbElement.createCharacteristic(characteristic.getUuid(),
2406                  characteristic.getProperties(), permission));
2407 
2408             for (BluetoothGattDescriptor descriptor: characteristic.getDescriptors()) {
2409                 permission = ((characteristic.getKeySize() - 7) << 12)
2410                                     + descriptor.getPermissions();
2411                 db.add(GattDbElement.createDescriptor(descriptor.getUuid(), permission));
2412             }
2413         }
2414 
2415         for (BluetoothGattService includedService : service.getIncludedServices()) {
2416             int inclSrvc = mHandleMap.getServiceHandle(includedService.getUuid(),
2417                     includedService.getType(), includedService.getInstanceId());
2418             db.add(GattDbElement.createIncludedService(inclSrvc));
2419         }
2420 
2421         gattServerAddServiceNative(serverIf, db);
2422     }
2423 
removeService(int serverIf, int handle)2424     void removeService(int serverIf, int handle) {
2425         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2426 
2427         if (DBG) Log.d(TAG, "removeService() - handle=" + handle);
2428 
2429         gattServerDeleteServiceNative(serverIf, handle);
2430     }
2431 
clearServices(int serverIf)2432     void clearServices(int serverIf) {
2433         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2434 
2435         if (DBG) Log.d(TAG, "clearServices()");
2436         deleteServices(serverIf);
2437     }
2438 
sendResponse(int serverIf, String address, int requestId, int status, int offset, byte[] value)2439     void sendResponse(int serverIf, String address, int requestId,
2440                       int status, int offset, byte[] value) {
2441         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2442 
2443         if (VDBG) Log.d(TAG, "sendResponse() - address=" + address);
2444 
2445         int handle = 0;
2446         HandleMap.Entry entry = mHandleMap.getByRequestId(requestId);
2447         if (entry != null) handle = entry.handle;
2448 
2449         int connId = mServerMap.connIdByAddress(serverIf, address);
2450         gattServerSendResponseNative(serverIf, connId, requestId, (byte)status,
2451                                      handle, offset, value, (byte)0);
2452         mHandleMap.deleteRequest(requestId);
2453     }
2454 
sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value)2455     void sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value) {
2456         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2457 
2458         if (VDBG) Log.d(TAG, "sendNotification() - address=" + address + " handle=" + handle);
2459 
2460         int connId = mServerMap.connIdByAddress(serverIf, address);
2461         if (connId == 0) return;
2462 
2463         if (confirm) {
2464             gattServerSendIndicationNative(serverIf, handle, connId, value);
2465         } else {
2466             gattServerSendNotificationNative(serverIf, handle, connId, value);
2467         }
2468     }
2469 
2470 
2471     /**************************************************************************
2472      * Private functions
2473      *************************************************************************/
2474 
isRestrictedCharUuid(final UUID charUuid)2475     private boolean isRestrictedCharUuid(final UUID charUuid) {
2476       return isHidUuid(charUuid);
2477     }
2478 
isRestrictedSrvcUuid(final UUID srvcUuid)2479     private boolean isRestrictedSrvcUuid(final UUID srvcUuid) {
2480       return isFidoUUID(srvcUuid);
2481     }
2482 
isHidUuid(final UUID uuid)2483     private boolean isHidUuid(final UUID uuid) {
2484         for (UUID hid_uuid : HID_UUIDS) {
2485             if (hid_uuid.equals(uuid)) return true;
2486         }
2487         return false;
2488     }
2489 
isFidoUUID(final UUID uuid)2490     private boolean isFidoUUID(final UUID uuid) {
2491         for (UUID fido_uuid : FIDO_UUIDS) {
2492             if (fido_uuid.equals(uuid)) return true;
2493         }
2494         return false;
2495     }
2496 
getDeviceType(BluetoothDevice device)2497     private int getDeviceType(BluetoothDevice device) {
2498         int type = gattClientGetDeviceTypeNative(device.getAddress());
2499         if (DBG) Log.d(TAG, "getDeviceType() - device=" + device
2500             + ", type=" + type);
2501         return type;
2502     }
2503 
enforceAdminPermission()2504     private void enforceAdminPermission() {
2505         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
2506     }
2507 
needsPrivilegedPermissionForScan(ScanSettings settings)2508     private boolean needsPrivilegedPermissionForScan(ScanSettings settings) {
2509         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
2510         // BLE scan only mode needs special permission.
2511         if (adapter.getState() != BluetoothAdapter.STATE_ON) return true;
2512 
2513         // Regular scan, no special permission.
2514         if (settings == null) return false;
2515 
2516         // Regular scan, no special permission.
2517         if (settings.getReportDelayMillis() == 0) return false;
2518 
2519         // Batch scan, truncated mode needs permission.
2520         return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED;
2521     }
2522 
2523     // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be
2524     // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission.
enforcePrivilegedPermission()2525     private void enforcePrivilegedPermission() {
2526         enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
2527             "Need BLUETOOTH_PRIVILEGED permission");
2528     }
2529 
2530     // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other
2531     // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does
2532     // not have UPDATE_DEVICE_STATS permission.
enforceImpersonatationPermission()2533     private void enforceImpersonatationPermission() {
2534         enforceCallingOrSelfPermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
2535                 "Need UPDATE_DEVICE_STATS permission");
2536     }
2537 
stopNextService(int serverIf, int status)2538     private void stopNextService(int serverIf, int status) throws RemoteException {
2539         if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf
2540             + ", status=" + status);
2541 
2542         if (status == 0) {
2543             List<HandleMap.Entry> entries = mHandleMap.getEntries();
2544             for(HandleMap.Entry entry : entries) {
2545                 if (entry.type != HandleMap.TYPE_SERVICE ||
2546                     entry.serverIf != serverIf ||
2547                     entry.started == false)
2548                         continue;
2549 
2550                 gattServerStopServiceNative(serverIf, entry.handle);
2551                 return;
2552             }
2553         }
2554     }
2555 
deleteServices(int serverIf)2556     private void deleteServices(int serverIf) {
2557         if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf);
2558 
2559         /*
2560          * Figure out which handles to delete.
2561          * The handles are copied into a new list to avoid race conditions.
2562          */
2563         List<Integer> handleList = new ArrayList<Integer>();
2564         List<HandleMap.Entry> entries = mHandleMap.getEntries();
2565         for(HandleMap.Entry entry : entries) {
2566             if (entry.type != HandleMap.TYPE_SERVICE ||
2567                 entry.serverIf != serverIf)
2568                     continue;
2569             handleList.add(entry.handle);
2570         }
2571 
2572         /* Now actually delete the services.... */
2573         for(Integer handle : handleList) {
2574             gattServerDeleteServiceNative(serverIf, handle);
2575         }
2576     }
2577 
parseUuids(byte[] adv_data)2578     private List<UUID> parseUuids(byte[] adv_data) {
2579         List<UUID> uuids = new ArrayList<UUID>();
2580 
2581         int offset = 0;
2582         while(offset < (adv_data.length-2)) {
2583             int len = Byte.toUnsignedInt(adv_data[offset++]);
2584             if (len == 0) break;
2585 
2586             int type = adv_data[offset++];
2587             switch (type) {
2588                 case 0x02: // Partial list of 16-bit UUIDs
2589                 case 0x03: // Complete list of 16-bit UUIDs
2590                     while (len > 1) {
2591                         int uuid16 = adv_data[offset++];
2592                         uuid16 += (adv_data[offset++] << 8);
2593                         len -= 2;
2594                         uuids.add(UUID.fromString(String.format(
2595                             "%08x-0000-1000-8000-00805f9b34fb", uuid16)));
2596                     }
2597                     break;
2598 
2599                 default:
2600                     offset += (len - 1);
2601                     break;
2602             }
2603         }
2604 
2605         return uuids;
2606     }
2607 
2608     @Override
dump(StringBuilder sb)2609     public void dump(StringBuilder sb) {
2610         super.dump(sb);
2611         println(sb, "mAdvertisingServiceUuids:");
2612         for (UUID uuid : mAdvertisingServiceUuids) {
2613             println(sb, "  " + uuid);
2614         }
2615 
2616         println(sb, "mMaxScanFilters: " + mMaxScanFilters);
2617 
2618         sb.append("\nGATT Scanner Map\n");
2619         mScannerMap.dump(sb);
2620 
2621         sb.append("GATT Client Map\n");
2622         mClientMap.dump(sb);
2623 
2624         sb.append("GATT Server Map\n");
2625         mServerMap.dump(sb);
2626 
2627         sb.append("GATT Handle Map\n");
2628         mHandleMap.dump(sb);
2629     }
2630 
addScanResult()2631     void addScanResult() {
2632         if (mScanEvents.isEmpty())
2633             return;
2634 
2635         BluetoothProto.ScanEvent curr = mScanEvents.get(mScanEvents.size() - 1);
2636         curr.setNumberResults(curr.getNumberResults() + 1);
2637     }
2638 
addScanEvent(BluetoothProto.ScanEvent event)2639     void addScanEvent(BluetoothProto.ScanEvent event) {
2640         synchronized(mScanEvents) {
2641             if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT)
2642                 mScanEvents.remove(0);
2643             mScanEvents.add(event);
2644         }
2645     }
2646 
2647     @Override
dumpProto(BluetoothProto.BluetoothLog proto)2648     public void dumpProto(BluetoothProto.BluetoothLog proto) {
2649         synchronized(mScanEvents) {
2650             for (BluetoothProto.ScanEvent event : mScanEvents) {
2651                 proto.addScanEvent(event);
2652             }
2653         }
2654     }
2655 
2656     /**************************************************************************
2657      * GATT Test functions
2658      *************************************************************************/
2659 
gattTestCommand(int command, UUID uuid1, String bda1, int p1, int p2, int p3, int p4, int p5)2660     void gattTestCommand(int command, UUID uuid1, String bda1,
2661                          int p1, int p2, int p3, int p4, int p5) {
2662         if (bda1 == null) bda1 = "00:00:00:00:00:00";
2663         if (uuid1 != null)
2664             gattTestNative(command, uuid1.getLeastSignificantBits(),
2665                        uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5);
2666         else
2667             gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5);
2668     }
2669 
gattTestNative(int command, long uuid1_lsb, long uuid1_msb, String bda1, int p1, int p2, int p3, int p4, int p5)2670     private native void gattTestNative(int command,
2671                                     long uuid1_lsb, long uuid1_msb, String bda1,
2672                                     int p1, int p2, int p3, int p4, int p5);
2673 
2674     /**************************************************************************
2675      * Native functions prototypes
2676      *************************************************************************/
2677 
classInitNative()2678     private native static void classInitNative();
initializeNative()2679     private native void initializeNative();
cleanupNative()2680     private native void cleanupNative();
2681 
gattClientGetDeviceTypeNative(String address)2682     private native int gattClientGetDeviceTypeNative(String address);
2683 
gattClientRegisterAppNative(long app_uuid_lsb, long app_uuid_msb)2684     private native void gattClientRegisterAppNative(long app_uuid_lsb,
2685                                                     long app_uuid_msb);
2686 
gattClientUnregisterAppNative(int clientIf)2687     private native void gattClientUnregisterAppNative(int clientIf);
2688 
gattClientConnectNative( int clientIf, String address, boolean isDirect, int transport, int initiating_phys)2689     private native void gattClientConnectNative(
2690             int clientIf, String address, boolean isDirect, int transport, int initiating_phys);
2691 
gattClientDisconnectNative(int clientIf, String address, int conn_id)2692     private native void gattClientDisconnectNative(int clientIf, String address,
2693             int conn_id);
2694 
gattClientSetPreferredPhyNative( int clientIf, int conn_id, int tx_phy, int rx_phy, int phy_options)2695     private native void gattClientSetPreferredPhyNative(
2696             int clientIf, int conn_id, int tx_phy, int rx_phy, int phy_options);
2697 
gattClientReadPhyNative(int clientIf, int conn_id)2698     private native void gattClientReadPhyNative(int clientIf, int conn_id);
2699 
gattClientRefreshNative(int clientIf, String address)2700     private native void gattClientRefreshNative(int clientIf, String address);
2701 
gattClientSearchServiceNative(int conn_id, boolean search_all, long service_uuid_lsb, long service_uuid_msb)2702     private native void gattClientSearchServiceNative(int conn_id,
2703             boolean search_all, long service_uuid_lsb, long service_uuid_msb);
2704 
gattClientDiscoverServiceByUuidNative( int conn_id, long service_uuid_lsb, long service_uuid_msb)2705     private native void gattClientDiscoverServiceByUuidNative(
2706             int conn_id, long service_uuid_lsb, long service_uuid_msb);
2707 
gattClientGetGattDbNative(int conn_id)2708     private native void gattClientGetGattDbNative(int conn_id);
2709 
gattClientReadCharacteristicNative(int conn_id, int handle, int authReq)2710     private native void gattClientReadCharacteristicNative(int conn_id, int handle, int authReq);
2711 
gattClientReadUsingCharacteristicUuidNative( int conn_id, long uuid_msb, long uuid_lsb, int s_handle, int e_handle, int authReq)2712     private native void gattClientReadUsingCharacteristicUuidNative(
2713             int conn_id, long uuid_msb, long uuid_lsb, int s_handle, int e_handle, int authReq);
2714 
gattClientReadDescriptorNative(int conn_id, int handle, int authReq)2715     private native void gattClientReadDescriptorNative(int conn_id, int handle, int authReq);
2716 
gattClientWriteCharacteristicNative(int conn_id, int handle, int write_type, int auth_req, byte[] value)2717     private native void gattClientWriteCharacteristicNative(int conn_id,
2718             int handle, int write_type, int auth_req, byte[] value);
2719 
gattClientWriteDescriptorNative(int conn_id, int handle, int auth_req, byte[] value)2720     private native void gattClientWriteDescriptorNative(int conn_id, int handle,
2721             int auth_req, byte[] value);
2722 
gattClientExecuteWriteNative(int conn_id, boolean execute)2723     private native void gattClientExecuteWriteNative(int conn_id, boolean execute);
2724 
gattClientRegisterForNotificationsNative(int clientIf, String address, int handle, boolean enable)2725     private native void gattClientRegisterForNotificationsNative(int clientIf,
2726             String address, int handle, boolean enable);
2727 
gattClientReadRemoteRssiNative(int clientIf, String address)2728     private native void gattClientReadRemoteRssiNative(int clientIf,
2729             String address);
2730 
gattClientConfigureMTUNative(int conn_id, int mtu)2731     private native void gattClientConfigureMTUNative(int conn_id, int mtu);
2732 
gattConnectionParameterUpdateNative(int client_if, String address, int minInterval, int maxInterval, int latency, int timeout)2733     private native void gattConnectionParameterUpdateNative(int client_if, String address,
2734             int minInterval, int maxInterval, int latency, int timeout);
2735 
gattServerRegisterAppNative(long app_uuid_lsb, long app_uuid_msb)2736     private native void gattServerRegisterAppNative(long app_uuid_lsb,
2737                                                     long app_uuid_msb);
2738 
gattServerUnregisterAppNative(int serverIf)2739     private native void gattServerUnregisterAppNative(int serverIf);
2740 
gattServerConnectNative(int server_if, String address, boolean is_direct, int transport)2741     private native void gattServerConnectNative(int server_if, String address,
2742                                              boolean is_direct, int transport);
2743 
gattServerDisconnectNative(int serverIf, String address, int conn_id)2744     private native void gattServerDisconnectNative(int serverIf, String address,
2745                                               int conn_id);
2746 
gattServerSetPreferredPhyNative( int clientIf, int conn_id, int tx_phy, int rx_phy, int phy_options)2747     private native void gattServerSetPreferredPhyNative(
2748             int clientIf, int conn_id, int tx_phy, int rx_phy, int phy_options);
2749 
gattServerReadPhyNative(int clientIf, int conn_id)2750     private native void gattServerReadPhyNative(int clientIf, int conn_id);
2751 
gattServerAddServiceNative(int server_if, List<GattDbElement> service)2752     private native void gattServerAddServiceNative(int server_if, List<GattDbElement> service);
2753 
gattServerStopServiceNative(int server_if, int svc_handle)2754     private native void gattServerStopServiceNative (int server_if,
2755                                                      int svc_handle);
2756 
gattServerDeleteServiceNative(int server_if, int svc_handle)2757     private native void gattServerDeleteServiceNative (int server_if,
2758                                                        int svc_handle);
2759 
gattServerSendIndicationNative(int server_if, int attr_handle, int conn_id, byte[] val)2760     private native void gattServerSendIndicationNative (int server_if,
2761             int attr_handle, int conn_id, byte[] val);
2762 
gattServerSendNotificationNative(int server_if, int attr_handle, int conn_id, byte[] val)2763     private native void gattServerSendNotificationNative (int server_if,
2764             int attr_handle, int conn_id, byte[] val);
2765 
gattServerSendResponseNative(int server_if, int conn_id, int trans_id, int status, int handle, int offset, byte[] val, int auth_req)2766     private native void gattServerSendResponseNative (int server_if,
2767             int conn_id, int trans_id, int status, int handle, int offset,
2768             byte[] val, int auth_req);
2769 }
2770