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