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