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