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