• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.gatt;
18 
19 import static com.android.bluetooth.Utils.checkCallerTargetSdk;
20 import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission;
21 
22 import android.annotation.RequiresPermission;
23 import android.annotation.SuppressLint;
24 import android.app.AppOpsManager;
25 import android.app.PendingIntent;
26 import android.app.Service;
27 import android.content.Context;
28 import android.bluetooth.BluetoothAdapter;
29 import android.bluetooth.BluetoothDevice;
30 import android.bluetooth.BluetoothGatt;
31 import android.bluetooth.BluetoothGattCharacteristic;
32 import android.bluetooth.BluetoothGattDescriptor;
33 import android.bluetooth.BluetoothGattService;
34 import android.bluetooth.BluetoothProfile;
35 import android.bluetooth.BluetoothProtoEnums;
36 import android.bluetooth.BluetoothStatusCodes;
37 import android.bluetooth.IBluetoothGatt;
38 import android.bluetooth.IBluetoothGattCallback;
39 import android.bluetooth.IBluetoothGattServerCallback;
40 import android.bluetooth.le.AdvertiseData;
41 import android.bluetooth.le.AdvertisingSetParameters;
42 import android.bluetooth.le.BluetoothLeScanner;
43 import android.bluetooth.le.IAdvertisingSetCallback;
44 import android.bluetooth.le.IPeriodicAdvertisingCallback;
45 import android.bluetooth.le.IScannerCallback;
46 import android.bluetooth.le.PeriodicAdvertisingParameters;
47 import android.bluetooth.le.ScanCallback;
48 import android.bluetooth.le.ScanFilter;
49 import android.bluetooth.le.ScanRecord;
50 import android.bluetooth.le.ScanResult;
51 import android.bluetooth.le.ScanSettings;
52 import android.companion.AssociationInfo;
53 import android.companion.CompanionDeviceManager;
54 import android.content.AttributionSource;
55 import android.content.Intent;
56 import android.content.pm.PackageManager.PackageInfoFlags;
57 import android.content.pm.PackageManager.NameNotFoundException;
58 import android.net.MacAddress;
59 import android.os.Binder;
60 import android.os.Build;
61 import android.os.Handler;
62 import android.os.IBinder;
63 import android.os.Message;
64 import android.os.ParcelUuid;
65 import android.os.RemoteException;
66 import android.os.SystemClock;
67 import android.os.UserHandle;
68 import android.os.WorkSource;
69 import android.provider.DeviceConfig;
70 import android.provider.Settings;
71 import android.sysprop.BluetoothProperties;
72 import android.text.format.DateUtils;
73 import android.util.Log;
74 
75 import com.android.bluetooth.BluetoothMetricsProto;
76 import com.android.bluetooth.BluetoothStatsLog;
77 import com.android.bluetooth.R;
78 import com.android.bluetooth.Utils;
79 import com.android.bluetooth.btservice.AbstractionLayer;
80 import com.android.bluetooth.btservice.AdapterService;
81 import com.android.bluetooth.btservice.BluetoothAdapterProxy;
82 import com.android.bluetooth.btservice.CompanionManager;
83 import com.android.bluetooth.btservice.ProfileService;
84 import com.android.bluetooth.util.NumberUtils;
85 import com.android.internal.annotations.VisibleForTesting;
86 import com.android.modules.utils.SynchronousResultReceiver;
87 
88 import libcore.util.HexEncoding;
89 
90 import java.util.ArrayDeque;
91 import java.util.ArrayList;
92 import java.util.Arrays;
93 import java.util.Collections;
94 import java.util.HashMap;
95 import java.util.HashSet;
96 import java.util.List;
97 import java.util.Map;
98 import java.util.Set;
99 import java.util.UUID;
100 import java.util.concurrent.TimeUnit;
101 import java.util.concurrent.atomic.AtomicBoolean;
102 import java.util.function.Predicate;
103 
104 /**
105  * Provides Bluetooth Gatt profile, as a service in
106  * the Bluetooth application.
107  * @hide
108  */
109 public class GattService extends ProfileService {
110     private static final boolean DBG = GattServiceConfig.DBG;
111     private static final boolean VDBG = GattServiceConfig.VDBG;
112     private static final String TAG = GattServiceConfig.TAG_PREFIX + "GattService";
113     private static final String UUID_SUFFIX = "-0000-1000-8000-00805f9b34fb";
114     private static final String UUID_ZERO_PAD = "00000000";
115 
116     static final int SCAN_FILTER_ENABLED = 1;
117     static final int SCAN_FILTER_MODIFIED = 2;
118 
119     private static final int MAC_ADDRESS_LENGTH = 6;
120     // Batch scan related constants.
121     private static final int TRUNCATED_RESULT_SIZE = 11;
122     private static final int TIME_STAMP_LENGTH = 2;
123 
124     private enum MatchOrigin {
125         PSEUDO_ADDRESS,
126         ORIGINAL_ADDRESS
127     }
128 
129     private static class MatchResult {
130         private final boolean mMatches;
131         private final MatchOrigin mOrigin;
MatchResult(boolean matches, MatchOrigin origin)132         private MatchResult(boolean matches, MatchOrigin origin) {
133             this.mMatches = matches;
134             this.mOrigin = origin;
135         }
136 
getMatches()137         public boolean getMatches() {
138             return mMatches;
139         }
140 
getMatchOrigin()141         public MatchOrigin getMatchOrigin() {
142             return mOrigin;
143         }
144     }
145 
146     /**
147      * The default floor value for LE batch scan report delays greater than 0
148      */
149     @VisibleForTesting
150     static final long DEFAULT_REPORT_DELAY_FLOOR = 5000;
151 
152     // onFoundLost related constants
153     private static final int ADVT_STATE_ONFOUND = 0;
154     private static final int ADVT_STATE_ONLOST = 1;
155 
156     private static final int ET_LEGACY_MASK = 0x10;
157 
158     private static final UUID HID_SERVICE_UUID =
159             UUID.fromString("00001812-0000-1000-8000-00805F9B34FB");
160 
161     private static final UUID[] HID_UUIDS = {
162             UUID.fromString("00002A4A-0000-1000-8000-00805F9B34FB"),
163             UUID.fromString("00002A4B-0000-1000-8000-00805F9B34FB"),
164             UUID.fromString("00002A4C-0000-1000-8000-00805F9B34FB"),
165             UUID.fromString("00002A4D-0000-1000-8000-00805F9B34FB")
166     };
167 
168     private static final UUID ANDROID_TV_REMOTE_SERVICE_UUID =
169             UUID.fromString("AB5E0001-5A21-4F05-BC7D-AF01F617B664");
170 
171     private static final UUID FIDO_SERVICE_UUID =
172             UUID.fromString("0000FFFD-0000-1000-8000-00805F9B34FB"); // U2F
173 
174     private static final UUID[] LE_AUDIO_SERVICE_UUIDS = {
175             UUID.fromString("00001844-0000-1000-8000-00805F9B34FB"), // VCS
176             UUID.fromString("00001845-0000-1000-8000-00805F9B34FB"), // VOCS
177             UUID.fromString("00001843-0000-1000-8000-00805F9B34FB"), // AICS
178             UUID.fromString("00001850-0000-1000-8000-00805F9B34FB"), // PACS
179             UUID.fromString("0000184E-0000-1000-8000-00805F9B34FB"), // ASCS
180             UUID.fromString("0000184F-0000-1000-8000-00805F9B34FB"), // BASS
181             UUID.fromString("00001854-0000-1000-8000-00805F9B34FB"), // HAP
182             UUID.fromString("00001846-0000-1000-8000-00805F9B34FB"), // CSIS
183     };
184 
185     /**
186      * Example raw beacons captured from a Blue Charm BC011
187      */
188     private static final String[] TEST_MODE_BEACONS = new String[] {
189             "020106",
190             "0201060303AAFE1716AAFE10EE01626C7565636861726D626561636F6E730009168020691E0EFE13551109426C7565436861726D5F313639363835000000",
191             "0201060303AAFE1716AAFE00EE626C7565636861726D31000000000001000009168020691E0EFE13551109426C7565436861726D5F313639363835000000",
192             "0201060303AAFE1116AAFE20000BF017000008874803FB93540916802069080EFE13551109426C7565436861726D5F313639363835000000000000000000",
193             "0201061AFF4C000215426C7565436861726D426561636F6E730EFE1355C509168020691E0EFE13551109426C7565436861726D5F31363936383500000000",
194     };
195 
196     /**
197      * Keep the arguments passed in for the PendingIntent.
198      */
199     class PendingIntentInfo {
200         public PendingIntent intent;
201         public ScanSettings settings;
202         public List<ScanFilter> filters;
203         public String callingPackage;
204 
205         @Override
equals(Object other)206         public boolean equals(Object other) {
207             if (!(other instanceof PendingIntentInfo)) {
208                 return false;
209             }
210             return intent.equals(((PendingIntentInfo) other).intent);
211         }
212     }
213 
214     private final PendingIntent.CancelListener mScanIntentCancelListener =
215             new PendingIntent.CancelListener(){
216                 public void onCanceled(PendingIntent intent) {
217                     Log.d(TAG, "scanning PendingIntent canceled");
218                     stopScan(intent, getAttributionSource());
219                 }
220             };
221 
222     /**
223      * List of our registered scanners.
224      */
225     class ScannerMap extends ContextMap<IScannerCallback, PendingIntentInfo> {}
226 
227     ScannerMap mScannerMap = new ScannerMap();
228 
229     /**
230      * List of our registered advertisers.
231      */
232     static class AdvertiserMap extends ContextMap<IAdvertisingSetCallback, Void> {}
233 
234     private AdvertiserMap mAdvertiserMap = new AdvertiserMap();
235 
236     /**
237      * List of our registered clients.
238      */
239     class ClientMap extends ContextMap<IBluetoothGattCallback, Void> {}
240 
241     ClientMap mClientMap = new ClientMap();
242 
243     /**
244      * List of our registered server apps.
245      */
246     class ServerMap extends ContextMap<IBluetoothGattServerCallback, Void> {}
247 
248     ServerMap mServerMap = new ServerMap();
249 
250     /**
251      * Server handle map.
252      */
253     HandleMap mHandleMap = new HandleMap();
254     private List<UUID> mAdvertisingServiceUuids = new ArrayList<UUID>();
255 
256     private int mMaxScanFilters;
257 
258     private static final int NUM_SCAN_EVENTS_KEPT = 20;
259 
260     /**
261      * Internal list of scan events to use with the proto
262      */
263     private final ArrayDeque<BluetoothMetricsProto.ScanEvent> mScanEvents =
264             new ArrayDeque<>(NUM_SCAN_EVENTS_KEPT);
265 
266     /**
267      * Set of restricted (which require a BLUETOOTH_PRIVILEGED permission) handles per connectionId.
268      */
269     private final Map<Integer, Set<Integer>> mRestrictedHandles = new HashMap<>();
270 
271     /**
272      * HashMap used to synchronize writeCharacteristic calls mapping remote device address to
273      * available permit (connectId or -1).
274      */
275     private final HashMap<String, Integer> mPermits = new HashMap<>();
276 
277     private AdapterService mAdapterService;
278     private BluetoothAdapterProxy mBluetoothAdapterProxy;
279     @VisibleForTesting
280     AdvertiseManager mAdvertiseManager;
281     @VisibleForTesting
282     PeriodicScanManager mPeriodicScanManager;
283     @VisibleForTesting
284     ScanManager mScanManager;
285     private AppOpsManager mAppOps;
286     private CompanionDeviceManager mCompanionManager;
287     private String mExposureNotificationPackage;
288     private Handler mTestModeHandler;
289     private final Object mTestModeLock = new Object();
290 
isEnabled()291     public static boolean isEnabled() {
292         return BluetoothProperties.isProfileGattEnabled().orElse(true);
293     }
294 
295     /**
296      */
297     private final Predicate<ScanResult> mLocationDenylistPredicate = (scanResult) -> {
298         final MacAddress parsedAddress = MacAddress
299                 .fromString(scanResult.getDevice().getAddress());
300         if (mAdapterService.getLocationDenylistMac().test(parsedAddress.toByteArray())) {
301             Log.v(TAG, "Skipping device matching denylist: " + parsedAddress);
302             return true;
303         }
304         final ScanRecord scanRecord = scanResult.getScanRecord();
305         if (scanRecord.matchesAnyField(mAdapterService.getLocationDenylistAdvertisingData())) {
306             Log.v(TAG, "Skipping data matching denylist: " + scanRecord);
307             return true;
308         }
309         return false;
310     };
311 
312     private static GattService sGattService;
313 
314     /**
315      * Reliable write queue
316      */
317     @VisibleForTesting
318     Set<String> mReliableQueue = new HashSet<String>();
319 
320     static {
classInitNative()321         classInitNative();
322     }
323 
324     @Override
initBinder()325     protected IProfileServiceBinder initBinder() {
326         return new BluetoothGattBinder(this);
327     }
328 
329     @Override
start()330     protected boolean start() {
331         if (DBG) {
332             Log.d(TAG, "start()");
333         }
334         mExposureNotificationPackage = getString(R.string.exposure_notification_package);
335         Settings.Global.putInt(
336                 getContentResolver(), "bluetooth_sanitized_exposure_notification_supported", 1);
337 
338         initializeNative();
339         mAdapterService = AdapterService.getAdapterService();
340         mBluetoothAdapterProxy = BluetoothAdapterProxy.getInstance();
341         mCompanionManager = getSystemService(CompanionDeviceManager.class);
342         mAppOps = getSystemService(AppOpsManager.class);
343         mAdvertiseManager = new AdvertiseManager(this, mAdapterService, mAdvertiserMap);
344         mAdvertiseManager.start();
345 
346         mScanManager = new ScanManager(this, mAdapterService, mBluetoothAdapterProxy);
347         mScanManager.start();
348 
349         mPeriodicScanManager = new PeriodicScanManager(mAdapterService);
350         mPeriodicScanManager.start();
351 
352         setGattService(this);
353         return true;
354     }
355 
356     @Override
stop()357     protected boolean stop() {
358         if (DBG) {
359             Log.d(TAG, "stop()");
360         }
361         setGattService(null);
362         mScannerMap.clear();
363         mAdvertiserMap.clear();
364         mClientMap.clear();
365         mServerMap.clear();
366         mHandleMap.clear();
367         mReliableQueue.clear();
368         if (mAdvertiseManager != null) {
369             mAdvertiseManager.cleanup();
370         }
371         if (mScanManager != null) {
372             mScanManager.cleanup();
373         }
374         if (mPeriodicScanManager != null) {
375             mPeriodicScanManager.cleanup();
376         }
377         return true;
378     }
379 
380     @Override
cleanup()381     protected void cleanup() {
382         if (DBG) {
383             Log.d(TAG, "cleanup()");
384         }
385         cleanupNative();
386         if (mAdvertiseManager != null) {
387             mAdvertiseManager.cleanup();
388         }
389         if (mScanManager != null) {
390             mScanManager.cleanup();
391         }
392         if (mPeriodicScanManager != null) {
393             mPeriodicScanManager.cleanup();
394         }
395     }
396 
397     // While test mode is enabled, pretend as if the underlying stack
398     // discovered a specific set of well-known beacons every second
399     @Override
setTestModeEnabled(boolean enableTestMode)400     protected void setTestModeEnabled(boolean enableTestMode) {
401         synchronized (mTestModeLock) {
402             if (mTestModeHandler == null) {
403                 mTestModeHandler = new Handler(getMainLooper()) {
404                     public void handleMessage(Message msg) {
405                         synchronized (mTestModeLock) {
406                             if (!GattService.this.isTestModeEnabled()) {
407                                 return;
408                             }
409                             for (String test : TEST_MODE_BEACONS) {
410                                 onScanResultInternal(0x1b, 0x1, "DD:34:02:05:5C:4D", 1, 0, 0xff,
411                                         127, -54, 0x0, HexEncoding.decode(test),
412                                         "DD:34:02:05:5C:4E");
413                             }
414                             sendEmptyMessageDelayed(0, DateUtils.SECOND_IN_MILLIS);
415                         }
416                     }
417                 };
418             }
419             if (enableTestMode && !isTestModeEnabled()) {
420                 super.setTestModeEnabled(true);
421                 mTestModeHandler.removeMessages(0);
422                 mTestModeHandler.sendEmptyMessageDelayed(0, DateUtils.SECOND_IN_MILLIS);
423             } else if (!enableTestMode && isTestModeEnabled()) {
424                 super.setTestModeEnabled(false);
425                 mTestModeHandler.removeMessages(0);
426                 mTestModeHandler.sendEmptyMessage(0);
427             }
428         }
429     }
430 
431     /**
432      * Get the current instance of {@link GattService}
433      *
434      * @return current instance of {@link GattService}
435      */
436     @VisibleForTesting
getGattService()437     public static synchronized GattService getGattService() {
438         if (sGattService == null) {
439             Log.w(TAG, "getGattService(): service is null");
440             return null;
441         }
442         if (!sGattService.isAvailable()) {
443             Log.w(TAG, "getGattService(): service is not available");
444             return null;
445         }
446         return sGattService;
447     }
448 
449     @VisibleForTesting
getScanManager()450     ScanManager getScanManager() {
451         if (mScanManager == null) {
452             Log.w(TAG, "getScanManager(): scan manager is null");
453             return null;
454         }
455         return mScanManager;
456     }
457 
setGattService(GattService instance)458     private static synchronized void setGattService(GattService instance) {
459         if (DBG) {
460             Log.d(TAG, "setGattService(): set to: " + instance);
461         }
462         sGattService = instance;
463     }
464 
465     // Suppressed because we are conditionally enforcing
466     @SuppressLint("AndroidFrameworkRequiresPermission")
permissionCheck(UUID characteristicUuid)467     private void permissionCheck(UUID characteristicUuid) {
468         if (!isHidCharUuid(characteristicUuid)) {
469             return;
470         }
471         enforceBluetoothPrivilegedPermission(this);
472     }
473 
474     // Suppressed because we are conditionally enforcing
475     @SuppressLint("AndroidFrameworkRequiresPermission")
permissionCheck(int connId, int handle)476     private void permissionCheck(int connId, int handle) {
477         if (!isHandleRestricted(connId, handle)) {
478             return;
479         }
480         enforceBluetoothPrivilegedPermission(this);
481     }
482 
483     // Suppressed because we are conditionally enforcing
484     @SuppressLint("AndroidFrameworkRequiresPermission")
permissionCheck(ClientMap.App app, int connId, int handle)485     private void permissionCheck(ClientMap.App app, int connId, int handle) {
486         if (!isHandleRestricted(connId, handle) || app.hasBluetoothPrivilegedPermission) {
487             return;
488         }
489         enforceBluetoothPrivilegedPermission(this);
490         app.hasBluetoothPrivilegedPermission = true;
491     }
492 
isHandleRestricted(int connId, int handle)493     private boolean isHandleRestricted(int connId, int handle) {
494         Set<Integer> restrictedHandles = mRestrictedHandles.get(connId);
495         return restrictedHandles != null && restrictedHandles.contains(handle);
496     }
497 
498     @Override
onStartCommand(Intent intent, int flags, int startId)499     public int onStartCommand(Intent intent, int flags, int startId) {
500         if (GattDebugUtils.handleDebugAction(this, intent)) {
501             return Service.START_NOT_STICKY;
502         }
503         return super.onStartCommand(intent, flags, startId);
504     }
505 
506     /**
507      * DeathReceipient handlers used to unregister applications that
508      * disconnect ungracefully (ie. crash or forced close).
509      */
510 
511     class ScannerDeathRecipient implements IBinder.DeathRecipient {
512         int mScannerId;
513 
ScannerDeathRecipient(int scannerId)514         ScannerDeathRecipient(int scannerId) {
515             mScannerId = scannerId;
516         }
517 
518         @Override
binderDied()519         public void binderDied() {
520             if (DBG) {
521                 Log.d(TAG, "Binder is dead - unregistering scanner (" + mScannerId + ")!");
522             }
523 
524             ScanClient client = getScanClient(mScannerId);
525             if (client != null) {
526                 client.appDied = true;
527                 stopScan(client.scannerId, getAttributionSource());
528             }
529         }
530 
getScanClient(int clientIf)531         private ScanClient getScanClient(int clientIf) {
532             for (ScanClient client : mScanManager.getRegularScanQueue()) {
533                 if (client.scannerId == clientIf) {
534                     return client;
535                 }
536             }
537             for (ScanClient client : mScanManager.getBatchScanQueue()) {
538                 if (client.scannerId == clientIf) {
539                     return client;
540                 }
541             }
542             return null;
543         }
544     }
545 
546     class ServerDeathRecipient implements IBinder.DeathRecipient {
547         int mAppIf;
548 
ServerDeathRecipient(int appIf)549         ServerDeathRecipient(int appIf) {
550             mAppIf = appIf;
551         }
552 
553         @Override
binderDied()554         public void binderDied() {
555             if (DBG) {
556                 Log.d(TAG, "Binder is dead - unregistering server (" + mAppIf + ")!");
557             }
558             unregisterServer(mAppIf, getAttributionSource());
559         }
560     }
561 
562     class ClientDeathRecipient implements IBinder.DeathRecipient {
563         int mAppIf;
564 
ClientDeathRecipient(int appIf)565         ClientDeathRecipient(int appIf) {
566             mAppIf = appIf;
567         }
568 
569         @Override
binderDied()570         public void binderDied() {
571             if (DBG) {
572                 Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!");
573             }
574             unregisterClient(mAppIf, getAttributionSource());
575         }
576     }
577 
578     /**
579      * Handlers for incoming service calls
580      */
581     @VisibleForTesting
582     static class BluetoothGattBinder extends IBluetoothGatt.Stub
583             implements IProfileServiceBinder {
584         private GattService mService;
585 
BluetoothGattBinder(GattService svc)586         BluetoothGattBinder(GattService svc) {
587             mService = svc;
588         }
589 
590         @Override
cleanup()591         public void cleanup() {
592             mService = null;
593         }
594 
getService()595         private GattService getService() {
596             if (mService != null && mService.isAvailable()) {
597                 return mService;
598             }
599             Log.e(TAG, "getService() - Service requested, but not available!");
600             return null;
601         }
602 
603         @Override
getDevicesMatchingConnectionStates(int[] states, AttributionSource attributionSource, SynchronousResultReceiver receiver)604         public void getDevicesMatchingConnectionStates(int[] states,
605                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
606             try {
607                 receiver.send(getDevicesMatchingConnectionStates(states, attributionSource));
608             } catch (RuntimeException e) {
609                 receiver.propagateException(e);
610             }
611         }
getDevicesMatchingConnectionStates(int[] states, AttributionSource attributionSource)612         private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states,
613                 AttributionSource attributionSource) {
614             GattService service = getService();
615             if (service == null) {
616                 return new ArrayList<BluetoothDevice>();
617             }
618             return service.getDevicesMatchingConnectionStates(states, attributionSource);
619         }
620 
621         @Override
registerClient(ParcelUuid uuid, IBluetoothGattCallback callback, boolean eattSupport, AttributionSource attributionSource, SynchronousResultReceiver receiver)622         public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback,
623                 boolean eattSupport, AttributionSource attributionSource,
624                 SynchronousResultReceiver receiver) {
625             try {
626                 registerClient(uuid, callback, eattSupport, attributionSource);
627                 receiver.send(null);
628             } catch (RuntimeException e) {
629                 receiver.propagateException(e);
630             }
631         }
registerClient(ParcelUuid uuid, IBluetoothGattCallback callback, boolean eatt_support, AttributionSource attributionSource)632         private void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback,
633                 boolean eatt_support, AttributionSource attributionSource) {
634             GattService service = getService();
635             if (service == null) {
636                 return;
637             }
638             service.registerClient(uuid.getUuid(), callback, eatt_support, attributionSource);
639         }
640 
641         @Override
unregisterClient(int clientIf, AttributionSource attributionSource, SynchronousResultReceiver receiver)642         public void unregisterClient(int clientIf, AttributionSource attributionSource,
643                 SynchronousResultReceiver receiver) {
644             try {
645                 unregisterClient(clientIf, attributionSource);
646                 receiver.send(null);
647             } catch (RuntimeException e) {
648                 receiver.propagateException(e);
649             }
650         }
unregisterClient(int clientIf, AttributionSource attributionSource)651         private void unregisterClient(int clientIf, AttributionSource attributionSource) {
652             GattService service = getService();
653             if (service == null) {
654                 return;
655             }
656             service.unregisterClient(clientIf, attributionSource);
657         }
658 
659         @Override
registerScanner(IScannerCallback callback, WorkSource workSource, AttributionSource attributionSource, SynchronousResultReceiver receiver)660         public void registerScanner(IScannerCallback callback, WorkSource workSource,
661                 AttributionSource attributionSource, SynchronousResultReceiver receiver)
662                 throws RemoteException {
663             try {
664                 registerScanner(callback, workSource, attributionSource);
665                 receiver.send(null);
666             } catch (RuntimeException e) {
667                 receiver.propagateException(e);
668             }
669         }
registerScanner(IScannerCallback callback, WorkSource workSource, AttributionSource attributionSource)670         private void registerScanner(IScannerCallback callback, WorkSource workSource,
671                 AttributionSource attributionSource) throws RemoteException {
672             GattService service = getService();
673             if (service == null) {
674                 return;
675             }
676             service.registerScanner(callback, workSource, attributionSource);
677         }
678 
679         @Override
unregisterScanner(int scannerId, AttributionSource attributionSource, SynchronousResultReceiver receiver)680         public void unregisterScanner(int scannerId, AttributionSource attributionSource,
681                 SynchronousResultReceiver receiver) {
682             try {
683                 unregisterScanner(scannerId, attributionSource);
684                 receiver.send(null);
685             } catch (RuntimeException e) {
686                 receiver.propagateException(e);
687             }
688         }
unregisterScanner(int scannerId, AttributionSource attributionSource)689         private void unregisterScanner(int scannerId, AttributionSource attributionSource) {
690             GattService service = getService();
691             if (service == null) {
692                 return;
693             }
694             service.unregisterScanner(scannerId, attributionSource);
695         }
696 
697         @Override
startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, AttributionSource attributionSource, SynchronousResultReceiver receiver)698         public void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters,
699                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
700             try {
701                 startScan(scannerId, settings, filters,
702                         attributionSource);
703                 receiver.send(null);
704             } catch (RuntimeException e) {
705                 receiver.propagateException(e);
706             }
707         }
startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, AttributionSource attributionSource)708         private void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters,
709                 AttributionSource attributionSource) {
710             GattService service = getService();
711             if (service == null) {
712                 return;
713             }
714             service.startScan(scannerId, settings, filters, attributionSource);
715         }
716 
717         @Override
startScanForIntent(PendingIntent intent, ScanSettings settings, List<ScanFilter> filters, AttributionSource attributionSource, SynchronousResultReceiver receiver)718         public void startScanForIntent(PendingIntent intent, ScanSettings settings,
719                 List<ScanFilter> filters, AttributionSource attributionSource,
720                 SynchronousResultReceiver receiver)
721                 throws RemoteException {
722             try {
723                 startScanForIntent(intent, settings,
724                         filters, attributionSource);
725                 receiver.send(null);
726             } catch (RuntimeException e) {
727                 receiver.propagateException(e);
728             }
729         }
startScanForIntent(PendingIntent intent, ScanSettings settings, List<ScanFilter> filters, AttributionSource attributionSource)730         private void startScanForIntent(PendingIntent intent, ScanSettings settings,
731                 List<ScanFilter> filters, AttributionSource attributionSource)
732                 throws RemoteException {
733             GattService service = getService();
734             if (service == null) {
735                 return;
736             }
737             service.registerPiAndStartScan(intent, settings, filters, attributionSource);
738         }
739 
740         @Override
stopScanForIntent(PendingIntent intent, AttributionSource attributionSource, SynchronousResultReceiver receiver)741         public void stopScanForIntent(PendingIntent intent, AttributionSource attributionSource,
742                 SynchronousResultReceiver receiver) throws RemoteException {
743             try {
744                 stopScanForIntent(intent, attributionSource);
745                 receiver.send(null);
746             } catch (RuntimeException e) {
747                 receiver.propagateException(e);
748             }
749         }
stopScanForIntent(PendingIntent intent, AttributionSource attributionSource)750         private void stopScanForIntent(PendingIntent intent, AttributionSource attributionSource)
751                 throws RemoteException {
752             GattService service = getService();
753             if (service == null) {
754                 return;
755             }
756             service.stopScan(intent, attributionSource);
757         }
758 
759         @Override
stopScan(int scannerId, AttributionSource attributionSource, SynchronousResultReceiver receiver)760         public void stopScan(int scannerId, AttributionSource attributionSource,
761                 SynchronousResultReceiver receiver) {
762             try {
763                 stopScan(scannerId, attributionSource);
764                 receiver.send(null);
765             } catch (RuntimeException e) {
766                 receiver.propagateException(e);
767             }
768         }
stopScan(int scannerId, AttributionSource attributionSource)769         private void stopScan(int scannerId, AttributionSource attributionSource) {
770             GattService service = getService();
771             if (service == null) {
772                 return;
773             }
774             service.stopScan(scannerId, attributionSource);
775         }
776 
777         @Override
flushPendingBatchResults(int scannerId, AttributionSource attributionSource, SynchronousResultReceiver receiver)778         public void flushPendingBatchResults(int scannerId, AttributionSource attributionSource,
779                 SynchronousResultReceiver receiver) {
780             try {
781                 flushPendingBatchResults(scannerId, attributionSource);
782                 receiver.send(null);
783             } catch (RuntimeException e) {
784                 receiver.propagateException(e);
785             }
786         }
flushPendingBatchResults(int scannerId, AttributionSource attributionSource)787         private void flushPendingBatchResults(int scannerId, AttributionSource attributionSource) {
788             GattService service = getService();
789             if (service == null) {
790                 return;
791             }
792             service.flushPendingBatchResults(scannerId, attributionSource);
793         }
794 
795         @Override
clientConnect(int clientIf, String address, boolean isDirect, int transport, boolean opportunistic, int phy, AttributionSource attributionSource, SynchronousResultReceiver receiver)796         public void clientConnect(int clientIf, String address, boolean isDirect, int transport,
797                 boolean opportunistic, int phy, AttributionSource attributionSource,
798                 SynchronousResultReceiver receiver) {
799             try {
800                 clientConnect(clientIf, address, isDirect, transport, opportunistic, phy,
801                         attributionSource);
802                 receiver.send(null);
803             } catch (RuntimeException e) {
804                 receiver.propagateException(e);
805             }
806         }
clientConnect(int clientIf, String address, boolean isDirect, int transport, boolean opportunistic, int phy, AttributionSource attributionSource)807         private void clientConnect(int clientIf, String address, boolean isDirect, int transport,
808                 boolean opportunistic, int phy, AttributionSource attributionSource) {
809             GattService service = getService();
810             if (service == null) {
811                 return;
812             }
813             service.clientConnect(clientIf, address, isDirect, transport, opportunistic, phy,
814                     attributionSource);
815         }
816 
817         @Override
clientDisconnect(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)818         public void clientDisconnect(int clientIf, String address,
819                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
820             try {
821                 clientDisconnect(clientIf, address, attributionSource);
822                 receiver.send(null);
823             } catch (RuntimeException e) {
824                 receiver.propagateException(e);
825             }
826         }
clientDisconnect(int clientIf, String address, AttributionSource attributionSource)827         private void clientDisconnect(int clientIf, String address,
828                 AttributionSource attributionSource) {
829             GattService service = getService();
830             if (service == null) {
831                 return;
832             }
833             service.clientDisconnect(clientIf, address, attributionSource);
834         }
835 
836         @Override
clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions, AttributionSource attributionSource, SynchronousResultReceiver receiver)837         public void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy,
838                 int phyOptions, AttributionSource attributionSource,
839                 SynchronousResultReceiver receiver) {
840             try {
841                 clientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions,
842                         attributionSource);
843                 receiver.send(null);
844             } catch (RuntimeException e) {
845                 receiver.propagateException(e);
846             }
847         }
clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions, AttributionSource attributionSource)848         private void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy,
849                 int phyOptions, AttributionSource attributionSource) {
850             GattService service = getService();
851             if (service == null) {
852                 return;
853             }
854             service.clientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions,
855                     attributionSource);
856         }
857 
858         @Override
clientReadPhy(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)859         public void clientReadPhy(int clientIf, String address,
860                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
861             try {
862                 clientReadPhy(clientIf, address, attributionSource);
863                 receiver.send(null);
864             } catch (RuntimeException e) {
865                 receiver.propagateException(e);
866             }
867         }
clientReadPhy(int clientIf, String address, AttributionSource attributionSource)868         private void clientReadPhy(int clientIf, String address,
869                 AttributionSource attributionSource) {
870             GattService service = getService();
871             if (service == null) {
872                 return;
873             }
874             service.clientReadPhy(clientIf, address, attributionSource);
875         }
876 
877         @Override
refreshDevice(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)878         public void refreshDevice(int clientIf, String address,
879                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
880             try {
881                 refreshDevice(clientIf, address, attributionSource);
882                 receiver.send(null);
883             } catch (RuntimeException e) {
884                 receiver.propagateException(e);
885             }
886         }
refreshDevice(int clientIf, String address, AttributionSource attributionSource)887         private void refreshDevice(int clientIf, String address,
888                 AttributionSource attributionSource) {
889             GattService service = getService();
890             if (service == null) {
891                 return;
892             }
893             service.refreshDevice(clientIf, address, attributionSource);
894         }
895 
896         @Override
discoverServices(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)897         public void discoverServices(int clientIf, String address,
898                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
899             try {
900                 discoverServices(clientIf, address, attributionSource);
901                 receiver.send(null);
902             } catch (RuntimeException e) {
903                 receiver.propagateException(e);
904             }
905         }
discoverServices(int clientIf, String address, AttributionSource attributionSource)906         private void discoverServices(int clientIf, String address,
907                 AttributionSource attributionSource) {
908             GattService service = getService();
909             if (service == null) {
910                 return;
911             }
912             service.discoverServices(clientIf, address, attributionSource);
913         }
914 
915         @Override
discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid, AttributionSource attributionSource, SynchronousResultReceiver receiver)916         public void discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid,
917                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
918             try {
919                 discoverServiceByUuid(clientIf, address, uuid, attributionSource);
920                 receiver.send(null);
921             } catch (RuntimeException e) {
922                 receiver.propagateException(e);
923             }
924         }
discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid, AttributionSource attributionSource)925         private void discoverServiceByUuid(int clientIf, String address, ParcelUuid uuid,
926                 AttributionSource attributionSource) {
927             GattService service = getService();
928             if (service == null) {
929                 return;
930             }
931             service.discoverServiceByUuid(clientIf, address, uuid.getUuid(), attributionSource);
932         }
933 
934         @Override
readCharacteristic(int clientIf, String address, int handle, int authReq, AttributionSource attributionSource, SynchronousResultReceiver receiver)935         public void readCharacteristic(int clientIf, String address, int handle, int authReq,
936                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
937             try {
938                 readCharacteristic(clientIf, address, handle, authReq, attributionSource);
939                 receiver.send(null);
940             } catch (RuntimeException e) {
941                 receiver.propagateException(e);
942             }
943         }
readCharacteristic(int clientIf, String address, int handle, int authReq, AttributionSource attributionSource)944         private void readCharacteristic(int clientIf, String address, int handle, int authReq,
945                 AttributionSource attributionSource) {
946             GattService service = getService();
947             if (service == null) {
948                 return;
949             }
950             service.readCharacteristic(clientIf, address, handle, authReq, attributionSource);
951         }
952 
953         @Override
readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid, int startHandle, int endHandle, int authReq, AttributionSource attributionSource, SynchronousResultReceiver receiver)954         public void readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid,
955                 int startHandle, int endHandle, int authReq, AttributionSource attributionSource,
956                 SynchronousResultReceiver receiver) {
957             try {
958                 readUsingCharacteristicUuid(clientIf, address, uuid, startHandle, endHandle,
959                         authReq, attributionSource);
960                 receiver.send(null);
961             } catch (RuntimeException e) {
962                 receiver.propagateException(e);
963             }
964         }
readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid, int startHandle, int endHandle, int authReq, AttributionSource attributionSource)965         private void readUsingCharacteristicUuid(int clientIf, String address, ParcelUuid uuid,
966                 int startHandle, int endHandle, int authReq, AttributionSource attributionSource) {
967             GattService service = getService();
968             if (service == null) {
969                 return;
970             }
971             service.readUsingCharacteristicUuid(clientIf, address, uuid.getUuid(), startHandle,
972                     endHandle, authReq, attributionSource);
973         }
974 
975         @Override
writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq, byte[] value, AttributionSource attributionSource, SynchronousResultReceiver receiver)976         public void writeCharacteristic(int clientIf, String address, int handle, int writeType,
977                 int authReq, byte[] value, AttributionSource attributionSource,
978                 SynchronousResultReceiver receiver) {
979             try {
980                 receiver.send(writeCharacteristic(clientIf, address, handle, writeType, authReq,
981                             value, attributionSource));
982             } catch (RuntimeException e) {
983                 receiver.propagateException(e);
984             }
985         }
writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq, byte[] value, AttributionSource attributionSource)986         private int writeCharacteristic(int clientIf, String address, int handle, int writeType,
987                 int authReq, byte[] value, AttributionSource attributionSource) {
988             GattService service = getService();
989             if (service == null) {
990                 return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
991             }
992             return service.writeCharacteristic(clientIf, address, handle, writeType, authReq, value,
993                     attributionSource);
994         }
995 
996         @Override
readDescriptor(int clientIf, String address, int handle, int authReq, AttributionSource attributionSource, SynchronousResultReceiver receiver)997         public void readDescriptor(int clientIf, String address, int handle, int authReq,
998                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
999             try {
1000                 readDescriptor(clientIf, address, handle, authReq, attributionSource);
1001                 receiver.send(null);
1002             } catch (RuntimeException e) {
1003                 receiver.propagateException(e);
1004             }
1005         }
readDescriptor(int clientIf, String address, int handle, int authReq, AttributionSource attributionSource)1006         private void readDescriptor(int clientIf, String address, int handle, int authReq,
1007                 AttributionSource attributionSource) {
1008             GattService service = getService();
1009             if (service == null) {
1010                 return;
1011             }
1012             service.readDescriptor(clientIf, address, handle, authReq, attributionSource);
1013         }
1014 
1015         @Override
writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value, AttributionSource attributionSource, SynchronousResultReceiver receiver)1016         public void writeDescriptor(int clientIf, String address, int handle, int authReq,
1017                 byte[] value, AttributionSource attributionSource,
1018                 SynchronousResultReceiver receiver) {
1019             try {
1020                 receiver.send(writeDescriptor(clientIf, address, handle, authReq, value,
1021                             attributionSource));
1022             } catch (RuntimeException e) {
1023                 receiver.propagateException(e);
1024             }
1025         }
writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value, AttributionSource attributionSource)1026         private int writeDescriptor(int clientIf, String address, int handle, int authReq,
1027                 byte[] value, AttributionSource attributionSource) {
1028             GattService service = getService();
1029             if (service == null) {
1030                 return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
1031             }
1032             return service.writeDescriptor(clientIf, address, handle, authReq, value,
1033                     attributionSource);
1034         }
1035 
1036         @Override
beginReliableWrite(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)1037         public void beginReliableWrite(int clientIf, String address,
1038                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1039             try {
1040                 beginReliableWrite(clientIf, address, attributionSource);
1041                 receiver.send(null);
1042             } catch (RuntimeException e) {
1043                 receiver.propagateException(e);
1044             }
1045         }
beginReliableWrite(int clientIf, String address, AttributionSource attributionSource)1046         private void beginReliableWrite(int clientIf, String address,
1047                 AttributionSource attributionSource) {
1048             GattService service = getService();
1049             if (service == null) {
1050                 return;
1051             }
1052             service.beginReliableWrite(clientIf, address, attributionSource);
1053         }
1054 
1055         @Override
endReliableWrite(int clientIf, String address, boolean execute, AttributionSource attributionSource, SynchronousResultReceiver receiver)1056         public void endReliableWrite(int clientIf, String address, boolean execute,
1057                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1058             try {
1059                 endReliableWrite(clientIf, address, execute, attributionSource);
1060                 receiver.send(null);
1061             } catch (RuntimeException e) {
1062                 receiver.propagateException(e);
1063             }
1064         }
endReliableWrite(int clientIf, String address, boolean execute, AttributionSource attributionSource)1065         private void endReliableWrite(int clientIf, String address, boolean execute,
1066                 AttributionSource attributionSource) {
1067             GattService service = getService();
1068             if (service == null) {
1069                 return;
1070             }
1071             service.endReliableWrite(clientIf, address, execute, attributionSource);
1072         }
1073 
1074         @Override
registerForNotification(int clientIf, String address, int handle, boolean enable, AttributionSource attributionSource, SynchronousResultReceiver receiver)1075         public void registerForNotification(int clientIf, String address, int handle,
1076                 boolean enable, AttributionSource attributionSource,
1077                 SynchronousResultReceiver receiver) {
1078             try {
1079                 registerForNotification(clientIf, address, handle, enable, attributionSource);
1080                 receiver.send(null);
1081             } catch (RuntimeException e) {
1082                 receiver.propagateException(e);
1083             }
1084         }
registerForNotification(int clientIf, String address, int handle, boolean enable, AttributionSource attributionSource)1085         private void registerForNotification(int clientIf, String address, int handle,
1086                 boolean enable, AttributionSource attributionSource) {
1087             GattService service = getService();
1088             if (service == null) {
1089                 return;
1090             }
1091             service.registerForNotification(clientIf, address, handle, enable, attributionSource);
1092         }
1093 
1094         @Override
readRemoteRssi(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)1095         public void readRemoteRssi(int clientIf, String address,
1096                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1097             try {
1098                 readRemoteRssi(clientIf, address, attributionSource);
1099                 receiver.send(null);
1100             } catch (RuntimeException e) {
1101                 receiver.propagateException(e);
1102             }
1103         }
readRemoteRssi(int clientIf, String address, AttributionSource attributionSource)1104         private void readRemoteRssi(int clientIf, String address,
1105                 AttributionSource attributionSource) {
1106             GattService service = getService();
1107             if (service == null) {
1108                 return;
1109             }
1110             service.readRemoteRssi(clientIf, address, attributionSource);
1111         }
1112 
1113         @Override
configureMTU(int clientIf, String address, int mtu, AttributionSource attributionSource, SynchronousResultReceiver receiver)1114         public void configureMTU(int clientIf, String address, int mtu,
1115                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1116             try {
1117                 configureMTU(clientIf, address, mtu, attributionSource);
1118                 receiver.send(null);
1119             } catch (RuntimeException e) {
1120                 receiver.propagateException(e);
1121             }
1122         }
configureMTU(int clientIf, String address, int mtu, AttributionSource attributionSource)1123         private void configureMTU(int clientIf, String address, int mtu,
1124                 AttributionSource attributionSource) {
1125             GattService service = getService();
1126             if (service == null) {
1127                 return;
1128             }
1129             service.configureMTU(clientIf, address, mtu, attributionSource);
1130         }
1131 
1132         @Override
connectionParameterUpdate(int clientIf, String address, int connectionPriority, AttributionSource attributionSource, SynchronousResultReceiver receiver)1133         public void connectionParameterUpdate(int clientIf, String address,
1134                 int connectionPriority, AttributionSource attributionSource,
1135                 SynchronousResultReceiver receiver) {
1136             try {
1137                 connectionParameterUpdate(clientIf, address, connectionPriority, attributionSource);
1138                 receiver.send(null);
1139             } catch (RuntimeException e) {
1140                 receiver.propagateException(e);
1141             }
1142         }
connectionParameterUpdate(int clientIf, String address, int connectionPriority, AttributionSource attributionSource)1143         private void connectionParameterUpdate(int clientIf, String address,
1144                 int connectionPriority, AttributionSource attributionSource) {
1145             GattService service = getService();
1146             if (service == null) {
1147                 return;
1148             }
1149             service.connectionParameterUpdate(
1150                     clientIf, address, connectionPriority, attributionSource);
1151         }
1152 
1153         @Override
leConnectionUpdate(int clientIf, String address, int minConnectionInterval, int maxConnectionInterval, int peripheralLatency, int supervisionTimeout, int minConnectionEventLen, int maxConnectionEventLen, AttributionSource attributionSource, SynchronousResultReceiver receiver)1154         public void leConnectionUpdate(int clientIf, String address,
1155                 int minConnectionInterval, int maxConnectionInterval,
1156                 int peripheralLatency, int supervisionTimeout,
1157                 int minConnectionEventLen, int maxConnectionEventLen,
1158                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1159             try {
1160                 leConnectionUpdate(clientIf, address, minConnectionInterval, maxConnectionInterval,
1161                         peripheralLatency, supervisionTimeout, minConnectionEventLen,
1162                         maxConnectionEventLen, attributionSource);
1163                 receiver.send(null);
1164             } catch (RuntimeException e) {
1165                 receiver.propagateException(e);
1166             }
1167         }
leConnectionUpdate(int clientIf, String address, int minConnectionInterval, int maxConnectionInterval, int peripheralLatency, int supervisionTimeout, int minConnectionEventLen, int maxConnectionEventLen, AttributionSource attributionSource)1168         private void leConnectionUpdate(int clientIf, String address,
1169                 int minConnectionInterval, int maxConnectionInterval,
1170                 int peripheralLatency, int supervisionTimeout,
1171                 int minConnectionEventLen, int maxConnectionEventLen,
1172                 AttributionSource attributionSource) {
1173             GattService service = getService();
1174             if (service == null) {
1175                 return;
1176             }
1177             service.leConnectionUpdate(clientIf, address, minConnectionInterval,
1178                                        maxConnectionInterval, peripheralLatency,
1179                                        supervisionTimeout, minConnectionEventLen,
1180                                        maxConnectionEventLen, attributionSource);
1181         }
1182 
1183         @Override
registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback, boolean eattSupport, AttributionSource attributionSource, SynchronousResultReceiver receiver)1184         public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback,
1185                 boolean eattSupport, AttributionSource attributionSource,
1186                 SynchronousResultReceiver receiver) {
1187             try {
1188                 registerServer(uuid, callback, eattSupport, attributionSource);
1189                 receiver.send(null);
1190             } catch (RuntimeException e) {
1191                 receiver.propagateException(e);
1192             }
1193         }
registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback, boolean eatt_support, AttributionSource attributionSource)1194         private void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback,
1195                 boolean eatt_support, AttributionSource attributionSource) {
1196             GattService service = getService();
1197             if (service == null) {
1198                 return;
1199             }
1200             service.registerServer(uuid.getUuid(), callback, eatt_support, attributionSource);
1201         }
1202 
1203         @Override
unregisterServer(int serverIf, AttributionSource attributionSource, SynchronousResultReceiver receiver)1204         public void unregisterServer(int serverIf, AttributionSource attributionSource,
1205                 SynchronousResultReceiver receiver) {
1206             try {
1207                 unregisterServer(serverIf, attributionSource);
1208                 receiver.send(null);
1209             } catch (RuntimeException e) {
1210                 receiver.propagateException(e);
1211             }
1212         }
unregisterServer(int serverIf, AttributionSource attributionSource)1213         private void unregisterServer(int serverIf, AttributionSource attributionSource) {
1214             GattService service = getService();
1215             if (service == null) {
1216                 return;
1217             }
1218             service.unregisterServer(serverIf, attributionSource);
1219         }
1220 
1221         @Override
serverConnect(int serverIf, String address, boolean isDirect, int transport, AttributionSource attributionSource, SynchronousResultReceiver receiver)1222         public void serverConnect(int serverIf, String address, boolean isDirect, int transport,
1223                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1224             try {
1225                 serverConnect(serverIf, address, isDirect, transport, attributionSource);
1226                 receiver.send(null);
1227             } catch (RuntimeException e) {
1228                 receiver.propagateException(e);
1229             }
1230         }
serverConnect(int serverIf, String address, boolean isDirect, int transport, AttributionSource attributionSource)1231         private void serverConnect(int serverIf, String address, boolean isDirect, int transport,
1232                 AttributionSource attributionSource) {
1233             GattService service = getService();
1234             if (service == null) {
1235                 return;
1236             }
1237             service.serverConnect(serverIf, address, isDirect, transport, attributionSource);
1238         }
1239 
1240         @Override
serverDisconnect(int serverIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)1241         public void serverDisconnect(int serverIf, String address,
1242                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1243             try {
1244                 serverDisconnect(serverIf, address, attributionSource);
1245                 receiver.send(null);
1246             } catch (RuntimeException e) {
1247                 receiver.propagateException(e);
1248             }
1249         }
serverDisconnect(int serverIf, String address, AttributionSource attributionSource)1250         private void serverDisconnect(int serverIf, String address,
1251                 AttributionSource attributionSource) {
1252             GattService service = getService();
1253             if (service == null) {
1254                 return;
1255             }
1256             service.serverDisconnect(serverIf, address, attributionSource);
1257         }
1258 
1259         @Override
serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions, AttributionSource attributionSource, SynchronousResultReceiver receiver)1260         public void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy,
1261                 int phyOptions, AttributionSource attributionSource,
1262                 SynchronousResultReceiver receiver) {
1263             try {
1264                 serverSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions,
1265                         attributionSource);
1266                 receiver.send(null);
1267             } catch (RuntimeException e) {
1268                 receiver.propagateException(e);
1269             }
1270         }
serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions, AttributionSource attributionSource)1271         private void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy,
1272                 int phyOptions, AttributionSource attributionSource) {
1273             GattService service = getService();
1274             if (service == null) {
1275                 return;
1276             }
1277             service.serverSetPreferredPhy(
1278                     serverIf, address, txPhy, rxPhy, phyOptions, attributionSource);
1279         }
1280 
1281         @Override
serverReadPhy(int clientIf, String address, AttributionSource attributionSource, SynchronousResultReceiver receiver)1282         public void serverReadPhy(int clientIf, String address, AttributionSource attributionSource,
1283                 SynchronousResultReceiver receiver) {
1284             try {
1285                 serverReadPhy(clientIf, address, attributionSource);
1286                 receiver.send(null);
1287             } catch (RuntimeException e) {
1288                 receiver.propagateException(e);
1289             }
1290         }
serverReadPhy(int clientIf, String address, AttributionSource attributionSource)1291         private void serverReadPhy(int clientIf, String address,
1292                 AttributionSource attributionSource) {
1293             GattService service = getService();
1294             if (service == null) {
1295                 return;
1296             }
1297             service.serverReadPhy(clientIf, address, attributionSource);
1298         }
1299 
1300         @Override
addService(int serverIf, BluetoothGattService svc, AttributionSource attributionSource, SynchronousResultReceiver receiver)1301         public void addService(int serverIf, BluetoothGattService svc,
1302                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1303             try {
1304                 addService(serverIf, svc, attributionSource);
1305                 receiver.send(null);
1306             } catch (RuntimeException e) {
1307                 receiver.propagateException(e);
1308             }
1309         }
addService(int serverIf, BluetoothGattService svc, AttributionSource attributionSource)1310         private void addService(int serverIf, BluetoothGattService svc,
1311                 AttributionSource attributionSource) {
1312             GattService service = getService();
1313             if (service == null) {
1314                 return;
1315             }
1316 
1317             service.addService(serverIf, svc, attributionSource);
1318         }
1319 
1320         @Override
removeService(int serverIf, int handle, AttributionSource attributionSource, SynchronousResultReceiver receiver)1321         public void removeService(int serverIf, int handle, AttributionSource attributionSource,
1322                 SynchronousResultReceiver receiver) {
1323             try {
1324                 removeService(serverIf, handle, attributionSource);
1325                 receiver.send(null);
1326             } catch (RuntimeException e) {
1327                 receiver.propagateException(e);
1328             }
1329         }
removeService(int serverIf, int handle, AttributionSource attributionSource)1330         private void removeService(int serverIf, int handle, AttributionSource attributionSource) {
1331             GattService service = getService();
1332             if (service == null) {
1333                 return;
1334             }
1335             service.removeService(serverIf, handle, attributionSource);
1336         }
1337 
1338         @Override
clearServices(int serverIf, AttributionSource attributionSource, SynchronousResultReceiver receiver)1339         public void clearServices(int serverIf, AttributionSource attributionSource,
1340                 SynchronousResultReceiver receiver) {
1341             try {
1342                 clearServices(serverIf, attributionSource);
1343                 receiver.send(null);
1344             } catch (RuntimeException e) {
1345                 receiver.propagateException(e);
1346             }
1347         }
clearServices(int serverIf, AttributionSource attributionSource)1348         private void clearServices(int serverIf, AttributionSource attributionSource) {
1349             GattService service = getService();
1350             if (service == null) {
1351                 return;
1352             }
1353             service.clearServices(serverIf, attributionSource);
1354         }
1355 
1356         @Override
sendResponse(int serverIf, String address, int requestId, int status, int offset, byte[] value, AttributionSource attributionSource, SynchronousResultReceiver receiver)1357         public void sendResponse(int serverIf, String address, int requestId, int status,
1358                 int offset, byte[] value, AttributionSource attributionSource,
1359                 SynchronousResultReceiver receiver) {
1360             try {
1361                 sendResponse(serverIf, address, requestId, status, offset, value,
1362                         attributionSource);
1363                 receiver.send(null);
1364             } catch (RuntimeException e) {
1365                 receiver.propagateException(e);
1366             }
1367         }
sendResponse(int serverIf, String address, int requestId, int status, int offset, byte[] value, AttributionSource attributionSource)1368         private void sendResponse(int serverIf, String address, int requestId, int status,
1369                 int offset, byte[] value, AttributionSource attributionSource) {
1370             GattService service = getService();
1371             if (service == null) {
1372                 return;
1373             }
1374             service.sendResponse(
1375                     serverIf, address, requestId, status, offset, value, attributionSource);
1376         }
1377 
1378         @Override
sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value, AttributionSource attributionSource, SynchronousResultReceiver receiver)1379         public void sendNotification(int serverIf, String address, int handle, boolean confirm,
1380                 byte[] value, AttributionSource attributionSource,
1381                 SynchronousResultReceiver receiver) {
1382             try {
1383                 receiver.send(sendNotification(serverIf, address, handle, confirm, value,
1384                             attributionSource));
1385             } catch (RuntimeException e) {
1386                 receiver.propagateException(e);
1387             }
1388         }
sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value, AttributionSource attributionSource)1389         private int sendNotification(int serverIf, String address, int handle, boolean confirm,
1390                 byte[] value, AttributionSource attributionSource) {
1391             GattService service = getService();
1392             if (service == null) {
1393                 return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
1394             }
1395             return service.sendNotification(serverIf, address, handle, confirm, value,
1396                 attributionSource);
1397         }
1398 
1399         @Override
startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, int duration, int maxExtAdvEvents, IAdvertisingSetCallback callback, AttributionSource attributionSource, SynchronousResultReceiver receiver)1400         public void startAdvertisingSet(AdvertisingSetParameters parameters,
1401                 AdvertiseData advertiseData, AdvertiseData scanResponse,
1402                 PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData,
1403                 int duration, int maxExtAdvEvents, IAdvertisingSetCallback callback,
1404                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1405             try {
1406                 startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
1407                         periodicData, duration, maxExtAdvEvents, callback, attributionSource);
1408                 receiver.send(null);
1409             } catch (RuntimeException e) {
1410                 receiver.propagateException(e);
1411             }
1412         }
startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, int duration, int maxExtAdvEvents, IAdvertisingSetCallback callback, AttributionSource attributionSource)1413         private void startAdvertisingSet(AdvertisingSetParameters parameters,
1414                 AdvertiseData advertiseData, AdvertiseData scanResponse,
1415                 PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData,
1416                 int duration, int maxExtAdvEvents, IAdvertisingSetCallback callback,
1417                 AttributionSource attributionSource) {
1418             GattService service = getService();
1419             if (service == null) {
1420                 return;
1421             }
1422             service.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
1423                     periodicData, duration, maxExtAdvEvents, callback, attributionSource);
1424         }
1425 
1426         @Override
stopAdvertisingSet(IAdvertisingSetCallback callback, AttributionSource attributionSource, SynchronousResultReceiver receiver)1427         public void stopAdvertisingSet(IAdvertisingSetCallback callback,
1428                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1429             try {
1430                 stopAdvertisingSet(callback, attributionSource);
1431                 receiver.send(null);
1432             } catch (RuntimeException e) {
1433                 receiver.propagateException(e);
1434             }
1435         }
stopAdvertisingSet(IAdvertisingSetCallback callback, AttributionSource attributionSource)1436         private void stopAdvertisingSet(IAdvertisingSetCallback callback,
1437                 AttributionSource attributionSource) {
1438             GattService service = getService();
1439             if (service == null) {
1440                 return;
1441             }
1442             service.stopAdvertisingSet(callback, attributionSource);
1443         }
1444 
1445         @Override
getOwnAddress(int advertiserId, AttributionSource attributionSource, SynchronousResultReceiver receiver)1446         public void getOwnAddress(int advertiserId, AttributionSource attributionSource,
1447                 SynchronousResultReceiver receiver) {
1448             try {
1449                 getOwnAddress(advertiserId, attributionSource);
1450                 receiver.send(null);
1451             } catch (RuntimeException e) {
1452                 receiver.propagateException(e);
1453             }
1454         }
getOwnAddress(int advertiserId, AttributionSource attributionSource)1455         private void getOwnAddress(int advertiserId, AttributionSource attributionSource) {
1456             GattService service = getService();
1457             if (service == null) {
1458                 return;
1459             }
1460             service.getOwnAddress(advertiserId, attributionSource);
1461         }
1462 
1463         @Override
enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents, AttributionSource attributionSource, SynchronousResultReceiver receiver)1464         public void enableAdvertisingSet(int advertiserId, boolean enable, int duration,
1465                 int maxExtAdvEvents, AttributionSource attributionSource,
1466                 SynchronousResultReceiver receiver) {
1467             try {
1468                 enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents,
1469                         attributionSource);
1470                 receiver.send(null);
1471             } catch (RuntimeException e) {
1472                 receiver.propagateException(e);
1473             }
1474         }
enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents, AttributionSource attributionSource)1475         private void enableAdvertisingSet(int advertiserId, boolean enable, int duration,
1476                 int maxExtAdvEvents, AttributionSource attributionSource) {
1477             GattService service = getService();
1478             if (service == null) {
1479                 return;
1480             }
1481             service.enableAdvertisingSet(
1482                     advertiserId, enable, duration, maxExtAdvEvents, attributionSource);
1483         }
1484 
1485         @Override
setAdvertisingData(int advertiserId, AdvertiseData data, AttributionSource attributionSource, SynchronousResultReceiver receiver)1486         public void setAdvertisingData(int advertiserId, AdvertiseData data,
1487                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1488             try {
1489                 setAdvertisingData(advertiserId, data, attributionSource);
1490                 receiver.send(null);
1491             } catch (RuntimeException e) {
1492                 receiver.propagateException(e);
1493             }
1494         }
setAdvertisingData(int advertiserId, AdvertiseData data, AttributionSource attributionSource)1495         private void setAdvertisingData(int advertiserId, AdvertiseData data,
1496                 AttributionSource attributionSource) {
1497             GattService service = getService();
1498             if (service == null) {
1499                 return;
1500             }
1501             service.setAdvertisingData(advertiserId, data, attributionSource);
1502         }
1503 
1504         @Override
setScanResponseData(int advertiserId, AdvertiseData data, AttributionSource attributionSource, SynchronousResultReceiver receiver)1505         public void setScanResponseData(int advertiserId, AdvertiseData data,
1506                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1507             try {
1508                 setScanResponseData(advertiserId, data, attributionSource);
1509                 receiver.send(null);
1510             } catch (RuntimeException e) {
1511                 receiver.propagateException(e);
1512             }
1513         }
setScanResponseData(int advertiserId, AdvertiseData data, AttributionSource attributionSource)1514         private void setScanResponseData(int advertiserId, AdvertiseData data,
1515                 AttributionSource attributionSource) {
1516             GattService service = getService();
1517             if (service == null) {
1518                 return;
1519             }
1520             service.setScanResponseData(advertiserId, data, attributionSource);
1521         }
1522 
1523         @Override
setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters, AttributionSource attributionSource, SynchronousResultReceiver receiver)1524         public void setAdvertisingParameters(int advertiserId,
1525                 AdvertisingSetParameters parameters, AttributionSource attributionSource,
1526                 SynchronousResultReceiver receiver) {
1527             try {
1528                 setAdvertisingParameters(advertiserId, parameters, attributionSource);
1529                 receiver.send(null);
1530             } catch (RuntimeException e) {
1531                 receiver.propagateException(e);
1532             }
1533         }
setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters, AttributionSource attributionSource)1534         private void setAdvertisingParameters(int advertiserId,
1535                 AdvertisingSetParameters parameters, AttributionSource attributionSource) {
1536             GattService service = getService();
1537             if (service == null) {
1538                 return;
1539             }
1540             service.setAdvertisingParameters(advertiserId, parameters, attributionSource);
1541         }
1542 
1543         @Override
setPeriodicAdvertisingParameters(int advertiserId, PeriodicAdvertisingParameters parameters, AttributionSource attributionSource, SynchronousResultReceiver receiver)1544         public void setPeriodicAdvertisingParameters(int advertiserId,
1545                 PeriodicAdvertisingParameters parameters, AttributionSource attributionSource,
1546                 SynchronousResultReceiver receiver) {
1547             try {
1548                 setPeriodicAdvertisingParameters(advertiserId, parameters, attributionSource);
1549                 receiver.send(null);
1550             } catch (RuntimeException e) {
1551                 receiver.propagateException(e);
1552             }
1553         }
setPeriodicAdvertisingParameters(int advertiserId, PeriodicAdvertisingParameters parameters, AttributionSource attributionSource)1554         private void setPeriodicAdvertisingParameters(int advertiserId,
1555                 PeriodicAdvertisingParameters parameters, AttributionSource attributionSource) {
1556             GattService service = getService();
1557             if (service == null) {
1558                 return;
1559             }
1560             service.setPeriodicAdvertisingParameters(advertiserId, parameters, attributionSource);
1561         }
1562 
1563         @Override
setPeriodicAdvertisingData(int advertiserId, AdvertiseData data, AttributionSource attributionSource, SynchronousResultReceiver receiver)1564         public void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data,
1565                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1566             try {
1567                 setPeriodicAdvertisingData(advertiserId, data, attributionSource);
1568                 receiver.send(null);
1569             } catch (RuntimeException e) {
1570                 receiver.propagateException(e);
1571             }
1572         }
setPeriodicAdvertisingData(int advertiserId, AdvertiseData data, AttributionSource attributionSource)1573         private void setPeriodicAdvertisingData(int advertiserId, AdvertiseData data,
1574                 AttributionSource attributionSource) {
1575             GattService service = getService();
1576             if (service == null) {
1577                 return;
1578             }
1579             service.setPeriodicAdvertisingData(advertiserId, data, attributionSource);
1580         }
1581 
1582         @Override
setPeriodicAdvertisingEnable(int advertiserId, boolean enable, AttributionSource attributionSource, SynchronousResultReceiver receiver)1583         public void setPeriodicAdvertisingEnable(int advertiserId, boolean enable,
1584                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1585             try {
1586                 setPeriodicAdvertisingEnable(advertiserId, enable, attributionSource);
1587                 receiver.send(null);
1588             } catch (RuntimeException e) {
1589                 receiver.propagateException(e);
1590             }
1591         }
setPeriodicAdvertisingEnable(int advertiserId, boolean enable, AttributionSource attributionSource)1592         private void setPeriodicAdvertisingEnable(int advertiserId, boolean enable,
1593                 AttributionSource attributionSource) {
1594             GattService service = getService();
1595             if (service == null) {
1596                 return;
1597             }
1598             service.setPeriodicAdvertisingEnable(advertiserId, enable, attributionSource);
1599         }
1600 
1601         @Override
registerSync(ScanResult scanResult, int skip, int timeout, IPeriodicAdvertisingCallback callback, AttributionSource attributionSource, SynchronousResultReceiver receiver)1602         public void registerSync(ScanResult scanResult, int skip, int timeout,
1603                 IPeriodicAdvertisingCallback callback, AttributionSource attributionSource,
1604                 SynchronousResultReceiver receiver) {
1605             try {
1606                 registerSync(scanResult, skip, timeout, callback, attributionSource);
1607                 receiver.send(null);
1608             } catch (RuntimeException e) {
1609                 receiver.propagateException(e);
1610             }
1611         }
registerSync(ScanResult scanResult, int skip, int timeout, IPeriodicAdvertisingCallback callback, AttributionSource attributionSource)1612         private void registerSync(ScanResult scanResult, int skip, int timeout,
1613                 IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) {
1614             GattService service = getService();
1615             if (service == null) {
1616                 return;
1617             }
1618             service.registerSync(scanResult, skip, timeout, callback, attributionSource);
1619         }
1620 
1621         @Override
transferSync(BluetoothDevice bda, int serviceData , int syncHandle, AttributionSource attributionSource, SynchronousResultReceiver receiver)1622         public void transferSync(BluetoothDevice bda, int serviceData , int syncHandle,
1623                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1624             try {
1625                 transferSync(bda, serviceData , syncHandle, attributionSource);
1626                 receiver.send(null);
1627             } catch (RuntimeException e) {
1628                 receiver.propagateException(e);
1629             }
1630         }
transferSync(BluetoothDevice bda, int serviceData , int syncHandle, AttributionSource attributionSource)1631         public void transferSync(BluetoothDevice bda, int serviceData , int syncHandle,
1632                 AttributionSource attributionSource) {
1633             GattService service = getService();
1634             if (service == null) {
1635                 return;
1636             }
1637             service.transferSync(bda, serviceData , syncHandle, attributionSource);
1638         }
1639 
1640         @Override
transferSetInfo(BluetoothDevice bda, int serviceData , int advHandle, IPeriodicAdvertisingCallback callback, AttributionSource attributionSource, SynchronousResultReceiver receiver)1641         public void transferSetInfo(BluetoothDevice bda, int serviceData , int advHandle,
1642                 IPeriodicAdvertisingCallback callback, AttributionSource attributionSource,
1643                 SynchronousResultReceiver receiver) {
1644             try {
1645                 transferSetInfo(bda, serviceData , advHandle, callback, attributionSource);
1646                 receiver.send(null);
1647             } catch (RuntimeException e) {
1648                 receiver.propagateException(e);
1649             }
1650         }
transferSetInfo(BluetoothDevice bda, int serviceData , int advHandle, IPeriodicAdvertisingCallback callback, AttributionSource attributionSource)1651         public void transferSetInfo(BluetoothDevice bda, int serviceData , int advHandle,
1652                 IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) {
1653             GattService service = getService();
1654             if (service == null) {
1655                 return;
1656             }
1657             service.transferSetInfo(bda, serviceData , advHandle, callback, attributionSource);
1658         }
1659 
1660         @Override
unregisterSync(IPeriodicAdvertisingCallback callback, AttributionSource attributionSource, SynchronousResultReceiver receiver)1661         public void unregisterSync(IPeriodicAdvertisingCallback callback,
1662                 AttributionSource attributionSource, SynchronousResultReceiver receiver) {
1663             try {
1664                 unregisterSync(callback, attributionSource);
1665                 receiver.send(null);
1666             } catch (RuntimeException e) {
1667                 receiver.propagateException(e);
1668             }
1669         }
unregisterSync(IPeriodicAdvertisingCallback callback, AttributionSource attributionSource)1670         public void unregisterSync(IPeriodicAdvertisingCallback callback,
1671                 AttributionSource attributionSource) {
1672             GattService service = getService();
1673             if (service == null) {
1674                 return;
1675             }
1676             service.unregisterSync(callback, attributionSource);
1677         }
1678 
1679         @Override
disconnectAll(AttributionSource attributionSource, SynchronousResultReceiver receiver)1680         public void disconnectAll(AttributionSource attributionSource,
1681                 SynchronousResultReceiver receiver) {
1682             try {
1683                 disconnectAll(attributionSource);
1684                 receiver.send(null);
1685             } catch (RuntimeException e) {
1686                 receiver.propagateException(e);
1687             }
1688         }
disconnectAll(AttributionSource attributionSource)1689         private void disconnectAll(AttributionSource attributionSource) {
1690             GattService service = getService();
1691             if (service == null) {
1692                 return;
1693             }
1694             service.disconnectAll(attributionSource);
1695         }
1696 
1697         @Override
unregAll(AttributionSource source, SynchronousResultReceiver receiver)1698         public void unregAll(AttributionSource source, SynchronousResultReceiver receiver) {
1699             try {
1700                 unregAll(source);
1701                 receiver.send(null);
1702             } catch (RuntimeException e) {
1703                 receiver.propagateException(e);
1704             }
1705         }
unregAll(AttributionSource attributionSource)1706         private void unregAll(AttributionSource attributionSource) {
1707             GattService service = getService();
1708             if (service == null) {
1709                 return;
1710             }
1711             service.unregAll(attributionSource);
1712         }
1713 
1714         @Override
numHwTrackFiltersAvailable(AttributionSource attributionSource, SynchronousResultReceiver receiver)1715         public void numHwTrackFiltersAvailable(AttributionSource attributionSource,
1716                 SynchronousResultReceiver receiver) {
1717             try {
1718                 receiver.send(numHwTrackFiltersAvailable(attributionSource));
1719             } catch (RuntimeException e) {
1720                 receiver.propagateException(e);
1721             }
1722         }
numHwTrackFiltersAvailable(AttributionSource attributionSource)1723         private int numHwTrackFiltersAvailable(AttributionSource attributionSource) {
1724             GattService service = getService();
1725             if (service == null) {
1726                 return 0;
1727             }
1728             return service.numHwTrackFiltersAvailable(attributionSource);
1729         }
1730     }
1731 
1732     ;
1733 
1734     /**************************************************************************
1735      * Callback functions - CLIENT
1736      *************************************************************************/
1737 
1738     // EN format defined here:
1739     // https://blog.google/documents/70/Exposure_Notification_-_Bluetooth_Specification_v1.2.2.pdf
1740     private static final byte[] EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE = new byte[] {
1741         // size 2, flag field, flags byte (value is not important)
1742         (byte) 0x02, (byte) 0x01
1743     };
1744     private static final int EXPOSURE_NOTIFICATION_FLAGS_LENGTH = 0x2 + 1;
1745     private static final byte[] EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE = new byte[] {
1746         // size 3, complete 16 bit UUID, EN UUID
1747         (byte) 0x03, (byte) 0x03, (byte) 0x6F, (byte) 0xFD,
1748         // size 23, data for 16 bit UUID, EN UUID
1749         (byte) 0x17, (byte) 0x16, (byte) 0x6F, (byte) 0xFD,
1750         // ...payload
1751     };
1752     private static final int EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH = 0x03 + 0x17 + 2;
1753 
arrayStartsWith(byte[] array, byte[] prefix)1754     private static boolean arrayStartsWith(byte[] array, byte[] prefix) {
1755         if (array.length < prefix.length) {
1756             return false;
1757         }
1758         for (int i = 0; i < prefix.length; i++) {
1759             if (prefix[i] != array[i]) {
1760                 return false;
1761             }
1762         }
1763         return true;
1764     }
1765 
getSanitizedExposureNotification(ScanResult result)1766     ScanResult getSanitizedExposureNotification(ScanResult result) {
1767         ScanRecord record = result.getScanRecord();
1768         // Remove the flags part of the payload, if present
1769         if (record.getBytes().length > EXPOSURE_NOTIFICATION_FLAGS_LENGTH
1770                 && arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE)) {
1771             record = ScanRecord.parseFromBytes(
1772                     Arrays.copyOfRange(
1773                             record.getBytes(),
1774                             EXPOSURE_NOTIFICATION_FLAGS_LENGTH,
1775                             record.getBytes().length));
1776         }
1777 
1778         if (record.getBytes().length != EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH) {
1779             return null;
1780         }
1781         if (!arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE)) {
1782             return null;
1783         }
1784 
1785         return new ScanResult(null, 0, 0, 0, 0, 0, result.getRssi(), 0, record, 0);
1786     }
1787 
onScanResult(int eventType, int addressType, String address, int primaryPhy, int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt, byte[] advData, String originalAddress)1788     void onScanResult(int eventType, int addressType, String address, int primaryPhy,
1789             int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt,
1790             byte[] advData, String originalAddress) {
1791         // When in testing mode, ignore all real-world events
1792         if (isTestModeEnabled()) return;
1793 
1794         onScanResultInternal(eventType, addressType, address, primaryPhy, secondaryPhy,
1795                 advertisingSid, txPower, rssi, periodicAdvInt, advData, originalAddress);
1796     }
1797 
onScanResultInternal(int eventType, int addressType, String address, int primaryPhy, int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt, byte[] advData, String originalAddress)1798     void onScanResultInternal(int eventType, int addressType, String address, int primaryPhy,
1799             int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt,
1800             byte[] advData, String originalAddress) {
1801         if (VDBG) {
1802             Log.d(TAG, "onScanResult() - eventType=0x" + Integer.toHexString(eventType)
1803                     + ", addressType=" + addressType + ", address=" + address + ", primaryPhy="
1804                     + primaryPhy + ", secondaryPhy=" + secondaryPhy + ", advertisingSid=0x"
1805                     + Integer.toHexString(advertisingSid) + ", txPower=" + txPower + ", rssi="
1806                     + rssi + ", periodicAdvInt=0x" + Integer.toHexString(periodicAdvInt)
1807                     + ", originalAddress=" + originalAddress);
1808         }
1809 
1810         String identityAddress = mAdapterService.getIdentityAddress(address);
1811         if (!address.equals(identityAddress)) {
1812             if (VDBG) {
1813                 Log.d(TAG, "found identityAddress of " + address + ", replace originalAddress as "
1814                         + identityAddress);
1815             }
1816             originalAddress = identityAddress;
1817         }
1818 
1819 
1820         byte[] legacyAdvData = Arrays.copyOfRange(advData, 0, 62);
1821 
1822         for (ScanClient client : mScanManager.getRegularScanQueue()) {
1823             ScannerMap.App app = mScannerMap.getById(client.scannerId);
1824             if (app == null) {
1825                 if (VDBG) {
1826                     Log.d(TAG, "App is null; skip.");
1827                 }
1828                 continue;
1829             }
1830 
1831             BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
1832 
1833             ScanSettings settings = client.settings;
1834             byte[] scanRecordData;
1835             // This is for compability with applications that assume fixed size scan data.
1836             if (settings.getLegacy()) {
1837                 if ((eventType & ET_LEGACY_MASK) == 0) {
1838                     // If this is legacy scan, but nonlegacy result - skip.
1839                     if (VDBG) {
1840                         Log.d(TAG, "Legacy scan, non legacy result; skip.");
1841                     }
1842                     continue;
1843                 } else {
1844                     // Some apps are used to fixed-size advertise data.
1845                     scanRecordData = legacyAdvData;
1846                 }
1847             } else {
1848                 scanRecordData = advData;
1849             }
1850 
1851             ScanRecord scanRecord = ScanRecord.parseFromBytes(scanRecordData);
1852             ScanResult result =
1853                     new ScanResult(device, eventType, primaryPhy, secondaryPhy, advertisingSid,
1854                             txPower, rssi, periodicAdvInt, scanRecord,
1855                             SystemClock.elapsedRealtimeNanos());
1856 
1857             if (client.hasDisavowedLocation) {
1858                 if (mLocationDenylistPredicate.test(result)) {
1859                     Log.i(TAG, "Skipping client for location deny list");
1860                     continue;
1861                 }
1862             }
1863 
1864             boolean hasPermission = hasScanResultPermission(client);
1865             if (!hasPermission) {
1866                 for (String associatedDevice : client.associatedDevices) {
1867                     if (associatedDevice.equalsIgnoreCase(address)) {
1868                         hasPermission = true;
1869                         break;
1870                     }
1871                 }
1872             }
1873             if (!hasPermission && client.eligibleForSanitizedExposureNotification) {
1874                 ScanResult sanitized = getSanitizedExposureNotification(result);
1875                 if (sanitized != null) {
1876                     hasPermission = true;
1877                     result = sanitized;
1878                 }
1879             }
1880             MatchResult matchResult = matchesFilters(client, result, originalAddress);
1881             if (!hasPermission || !matchResult.getMatches()) {
1882                 if (VDBG) {
1883                     Log.d(TAG, "Skipping client: permission="
1884                             + hasPermission + " matches=" + matchResult.getMatches());
1885                 }
1886                 continue;
1887             }
1888 
1889             if ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_ALL_MATCHES) == 0) {
1890                 if (VDBG) {
1891                     Log.d(TAG, "Skipping client: CALLBACK_TYPE_ALL_MATCHES");
1892                 }
1893                 continue;
1894             }
1895 
1896             try {
1897                 app.appScanStats.addResult(client.scannerId);
1898                 if (app.callback != null) {
1899                     app.callback.onScanResult(result);
1900                 } else {
1901                     // Send the PendingIntent
1902                     ArrayList<ScanResult> results = new ArrayList<>();
1903                     results.add(result);
1904                     sendResultsByPendingIntent(app.info, results,
1905                             ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
1906                 }
1907             } catch (RemoteException | PendingIntent.CanceledException e) {
1908                 Log.e(TAG, "Exception: " + e);
1909                 mScannerMap.remove(client.scannerId);
1910                 mScanManager.stopScan(client.scannerId);
1911             }
1912         }
1913     }
1914 
sendResultByPendingIntent(PendingIntentInfo pii, ScanResult result, int callbackType, ScanClient client)1915     private void sendResultByPendingIntent(PendingIntentInfo pii, ScanResult result,
1916             int callbackType, ScanClient client) {
1917         ArrayList<ScanResult> results = new ArrayList<>();
1918         results.add(result);
1919         try {
1920             sendResultsByPendingIntent(pii, results, callbackType);
1921         } catch (PendingIntent.CanceledException e) {
1922             final long token = Binder.clearCallingIdentity();
1923             try {
1924                 stopScan(client.scannerId, getAttributionSource());
1925                 unregisterScanner(client.scannerId, getAttributionSource());
1926             } finally {
1927                 Binder.restoreCallingIdentity(token);
1928             }
1929         }
1930     }
1931 
sendResultsByPendingIntent(PendingIntentInfo pii, ArrayList<ScanResult> results, int callbackType)1932     private void sendResultsByPendingIntent(PendingIntentInfo pii, ArrayList<ScanResult> results,
1933             int callbackType) throws PendingIntent.CanceledException {
1934         Intent extrasIntent = new Intent();
1935         extrasIntent.putParcelableArrayListExtra(BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT,
1936                 results);
1937         extrasIntent.putExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, callbackType);
1938         pii.intent.send(this, 0, extrasIntent);
1939     }
1940 
sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode)1941     private void sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode)
1942             throws PendingIntent.CanceledException {
1943         Intent extrasIntent = new Intent();
1944         extrasIntent.putExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, errorCode);
1945         pii.intent.send(this, 0, extrasIntent);
1946     }
1947 
onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb)1948     void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb)
1949             throws RemoteException {
1950         UUID uuid = new UUID(uuidMsb, uuidLsb);
1951         if (DBG) {
1952             Log.d(TAG, "onScannerRegistered() - UUID=" + uuid + ", scannerId=" + scannerId
1953                     + ", status=" + status);
1954         }
1955 
1956         // First check the callback map
1957         ScannerMap.App cbApp = mScannerMap.getByUuid(uuid);
1958         if (cbApp != null) {
1959             if (status == 0) {
1960                 cbApp.id = scannerId;
1961                 // If app is callback based, setup a death recipient. App will initiate the start.
1962                 // Otherwise, if PendingIntent based, start the scan directly.
1963                 if (cbApp.callback != null) {
1964                     cbApp.linkToDeath(new ScannerDeathRecipient(scannerId));
1965                 } else {
1966                     continuePiStartScan(scannerId, cbApp);
1967                 }
1968             } else {
1969                 mScannerMap.remove(scannerId);
1970             }
1971             if (cbApp.callback != null) {
1972                 cbApp.callback.onScannerRegistered(status, scannerId);
1973             }
1974         }
1975     }
1976 
1977     /** Determines if the given scan client has the appropriate permissions to receive callbacks. */
hasScanResultPermission(final ScanClient client)1978     private boolean hasScanResultPermission(final ScanClient client) {
1979         if (client.hasNetworkSettingsPermission
1980                 || client.hasNetworkSetupWizardPermission
1981                 || client.hasScanWithoutLocationPermission) {
1982             return true;
1983         }
1984         if (client.hasDisavowedLocation) {
1985             return true;
1986         }
1987         return client.hasLocationPermission && !Utils.blockedByLocationOff(this, client.userHandle);
1988     }
1989 
1990     // Check if a scan record matches a specific filters.
matchesFilters(ScanClient client, ScanResult scanResult)1991     private MatchResult matchesFilters(ScanClient client, ScanResult scanResult) {
1992         return matchesFilters(client, scanResult, null);
1993     }
1994 
1995     // Check if a scan record matches a specific filters or original address
matchesFilters(ScanClient client, ScanResult scanResult, String originalAddress)1996     private MatchResult matchesFilters(ScanClient client, ScanResult scanResult,
1997             String originalAddress) {
1998         if (client.filters == null || client.filters.isEmpty()) {
1999             // TODO: Do we really wanna return true here?
2000             return new MatchResult(true, MatchOrigin.PSEUDO_ADDRESS);
2001         }
2002         for (ScanFilter filter : client.filters) {
2003             // Need to check the filter matches, and the original address without changing the API
2004             if (filter.matches(scanResult)) {
2005                 return new MatchResult(true, MatchOrigin.PSEUDO_ADDRESS);
2006             }
2007             if (originalAddress != null
2008                     && originalAddress.equalsIgnoreCase(filter.getDeviceAddress())) {
2009                 return new MatchResult(true, MatchOrigin.ORIGINAL_ADDRESS);
2010             }
2011         }
2012         return new MatchResult(false, MatchOrigin.PSEUDO_ADDRESS);
2013     }
2014 
onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb)2015     void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb)
2016             throws RemoteException {
2017         UUID uuid = new UUID(uuidMsb, uuidLsb);
2018         if (DBG) {
2019             Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf);
2020         }
2021         ClientMap.App app = mClientMap.getByUuid(uuid);
2022         if (app != null) {
2023             if (status == 0) {
2024                 app.id = clientIf;
2025                 app.linkToDeath(new ClientDeathRecipient(clientIf));
2026             } else {
2027                 mClientMap.remove(uuid);
2028             }
2029             app.callback.onClientRegistered(status, clientIf);
2030         }
2031     }
2032 
onConnected(int clientIf, int connId, int status, String address)2033     void onConnected(int clientIf, int connId, int status, String address) throws RemoteException {
2034         if (DBG) {
2035             Log.d(TAG, "onConnected() - clientIf=" + clientIf + ", connId=" + connId + ", address="
2036                     + address);
2037         }
2038         int connectionState = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;
2039         if (status == 0) {
2040             mClientMap.addConnection(clientIf, connId, address);
2041 
2042             // Allow one writeCharacteristic operation at a time for each connected remote device.
2043             synchronized (mPermits) {
2044                 Log.d(TAG, "onConnected() - adding permit for address="
2045                     + address);
2046                 mPermits.putIfAbsent(address, -1);
2047             }
2048             connectionState = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;
2049 
2050         }
2051         ClientMap.App app = mClientMap.getById(clientIf);
2052         if (app != null) {
2053             app.callback.onClientConnectionState(status, clientIf,
2054                     (status == BluetoothGatt.GATT_SUCCESS), address);
2055         }
2056         statsLogGattConnectionStateChange(
2057                 BluetoothProfile.GATT, address, clientIf, connectionState, status);
2058     }
2059 
onDisconnected(int clientIf, int connId, int status, String address)2060     void onDisconnected(int clientIf, int connId, int status, String address)
2061             throws RemoteException {
2062         if (DBG) {
2063             Log.d(TAG,
2064                     "onDisconnected() - clientIf=" + clientIf + ", connId=" + connId + ", address="
2065                             + address);
2066         }
2067 
2068         mClientMap.removeConnection(clientIf, connId);
2069         ClientMap.App app = mClientMap.getById(clientIf);
2070 
2071         // Remove AtomicBoolean representing permit if no other connections rely on this remote device.
2072         if (!mClientMap.getConnectedDevices().contains(address)) {
2073             synchronized (mPermits) {
2074                 Log.d(TAG, "onDisconnected() - removing permit for address="
2075                     + address);
2076                 mPermits.remove(address);
2077             }
2078         } else {
2079             synchronized (mPermits) {
2080                 if (mPermits.get(address) == connId) {
2081                     Log.d(TAG, "onDisconnected() - set permit -1 for address=" + address);
2082                     mPermits.put(address, -1);
2083                 }
2084             }
2085         }
2086 
2087         if (app != null) {
2088             app.callback.onClientConnectionState(status, clientIf, false, address);
2089         }
2090         statsLogGattConnectionStateChange(
2091                 BluetoothProfile.GATT, address, clientIf,
2092                 BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED, status);
2093     }
2094 
onClientPhyUpdate(int connId, int txPhy, int rxPhy, int status)2095     void onClientPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException {
2096         if (DBG) {
2097             Log.d(TAG, "onClientPhyUpdate() - connId=" + connId + ", status=" + status);
2098         }
2099 
2100         String address = mClientMap.addressByConnId(connId);
2101         if (address == null) {
2102             return;
2103         }
2104 
2105         ClientMap.App app = mClientMap.getByConnId(connId);
2106         if (app == null) {
2107             return;
2108         }
2109 
2110         app.callback.onPhyUpdate(address, txPhy, rxPhy, status);
2111     }
2112 
onClientPhyRead(int clientIf, String address, int txPhy, int rxPhy, int status)2113     void onClientPhyRead(int clientIf, String address, int txPhy, int rxPhy, int status)
2114             throws RemoteException {
2115         if (DBG) {
2116             Log.d(TAG,
2117                     "onClientPhyRead() - address=" + address + ", status=" + status + ", clientIf="
2118                             + clientIf);
2119         }
2120 
2121         Integer connId = mClientMap.connIdByAddress(clientIf, address);
2122         if (connId == null) {
2123             Log.d(TAG, "onClientPhyRead() - no connection to " + address);
2124             return;
2125         }
2126 
2127         ClientMap.App app = mClientMap.getByConnId(connId);
2128         if (app == null) {
2129             return;
2130         }
2131 
2132         app.callback.onPhyRead(address, txPhy, rxPhy, status);
2133     }
2134 
onClientConnUpdate(int connId, int interval, int latency, int timeout, int status)2135     void onClientConnUpdate(int connId, int interval, int latency, int timeout, int status)
2136             throws RemoteException {
2137         if (DBG) {
2138             Log.d(TAG, "onClientConnUpdate() - connId=" + connId + ", status=" + status);
2139         }
2140 
2141         String address = mClientMap.addressByConnId(connId);
2142         if (address == null) {
2143             return;
2144         }
2145 
2146         ClientMap.App app = mClientMap.getByConnId(connId);
2147         if (app == null) {
2148             return;
2149         }
2150 
2151         app.callback.onConnectionUpdated(address, interval, latency, timeout, status);
2152     }
2153 
onServiceChanged(int connId)2154     void onServiceChanged(int connId) throws RemoteException {
2155         if (DBG) {
2156             Log.d(TAG, "onServiceChanged - connId=" + connId);
2157         }
2158 
2159         String address = mClientMap.addressByConnId(connId);
2160         if (address == null) {
2161             return;
2162         }
2163 
2164         ClientMap.App app = mClientMap.getByConnId(connId);
2165         if (app == null) {
2166             return;
2167         }
2168 
2169         app.callback.onServiceChanged(address);
2170     }
2171 
onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status)2172     void onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException {
2173         if (DBG) {
2174             Log.d(TAG, "onServerPhyUpdate() - connId=" + connId + ", status=" + status);
2175         }
2176 
2177         String address = mServerMap.addressByConnId(connId);
2178         if (address == null) {
2179             return;
2180         }
2181 
2182         ServerMap.App app = mServerMap.getByConnId(connId);
2183         if (app == null) {
2184             return;
2185         }
2186 
2187         app.callback.onPhyUpdate(address, txPhy, rxPhy, status);
2188     }
2189 
onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status)2190     void onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status)
2191             throws RemoteException {
2192         if (DBG) {
2193             Log.d(TAG, "onServerPhyRead() - address=" + address + ", status=" + status);
2194         }
2195 
2196         Integer connId = mServerMap.connIdByAddress(serverIf, address);
2197         if (connId == null) {
2198             Log.d(TAG, "onServerPhyRead() - no connection to " + address);
2199             return;
2200         }
2201 
2202         ServerMap.App app = mServerMap.getByConnId(connId);
2203         if (app == null) {
2204             return;
2205         }
2206 
2207         app.callback.onPhyRead(address, txPhy, rxPhy, status);
2208     }
2209 
onServerConnUpdate(int connId, int interval, int latency, int timeout, int status)2210     void onServerConnUpdate(int connId, int interval, int latency, int timeout, int status)
2211             throws RemoteException {
2212         if (DBG) {
2213             Log.d(TAG, "onServerConnUpdate() - connId=" + connId + ", status=" + status);
2214         }
2215 
2216         String address = mServerMap.addressByConnId(connId);
2217         if (address == null) {
2218             return;
2219         }
2220 
2221         ServerMap.App app = mServerMap.getByConnId(connId);
2222         if (app == null) {
2223             return;
2224         }
2225 
2226         app.callback.onConnectionUpdated(address, interval, latency, timeout, status);
2227     }
2228 
onSearchCompleted(int connId, int status)2229     void onSearchCompleted(int connId, int status) throws RemoteException {
2230         if (DBG) {
2231             Log.d(TAG, "onSearchCompleted() - connId=" + connId + ", status=" + status);
2232         }
2233         // Gatt DB is ready!
2234 
2235         // This callback was called from the jni_workqueue thread. If we make request to the stack
2236         // on the same thread, it might cause deadlock. Schedule request on a new thread instead.
2237         Thread t = new Thread(new Runnable() {
2238             @Override
2239             public void run() {
2240                 gattClientGetGattDbNative(connId);
2241             }
2242         });
2243         t.start();
2244     }
2245 
getSampleGattDbElement()2246     GattDbElement getSampleGattDbElement() {
2247         return new GattDbElement();
2248     }
2249 
onGetGattDb(int connId, ArrayList<GattDbElement> db)2250     void onGetGattDb(int connId, ArrayList<GattDbElement> db) throws RemoteException {
2251         String address = mClientMap.addressByConnId(connId);
2252 
2253         if (DBG) {
2254             Log.d(TAG, "onGetGattDb() - address=" + address);
2255         }
2256 
2257         ClientMap.App app = mClientMap.getByConnId(connId);
2258         if (app == null || app.callback == null) {
2259             Log.e(TAG, "app or callback is null");
2260             return;
2261         }
2262 
2263         List<BluetoothGattService> dbOut = new ArrayList<BluetoothGattService>();
2264         Set<Integer> restrictedIds = new HashSet<>();
2265 
2266         BluetoothGattService currSrvc = null;
2267         BluetoothGattCharacteristic currChar = null;
2268         boolean isRestrictedSrvc = false;
2269         boolean isHidSrvc = false;
2270         boolean isRestrictedChar = false;
2271 
2272         for (GattDbElement el : db) {
2273             switch (el.type) {
2274                 case GattDbElement.TYPE_PRIMARY_SERVICE:
2275                 case GattDbElement.TYPE_SECONDARY_SERVICE:
2276                     if (DBG) {
2277                         Log.d(TAG, "got service with UUID=" + el.uuid + " id: " + el.id);
2278                     }
2279 
2280                     currSrvc = new BluetoothGattService(el.uuid, el.id, el.type);
2281                     dbOut.add(currSrvc);
2282                     isRestrictedSrvc = isRestrictedSrvcUuid(el.uuid);
2283                     isHidSrvc = isHidSrvcUuid(el.uuid);
2284                     if (isRestrictedSrvc) {
2285                         restrictedIds.add(el.id);
2286                     }
2287                     break;
2288 
2289                 case GattDbElement.TYPE_CHARACTERISTIC:
2290                     if (DBG) {
2291                         Log.d(TAG, "got characteristic with UUID=" + el.uuid + " id: " + el.id);
2292                     }
2293 
2294                     currChar = new BluetoothGattCharacteristic(el.uuid, el.id, el.properties, 0);
2295                     currSrvc.addCharacteristic(currChar);
2296                     isRestrictedChar = isRestrictedSrvc || (isHidSrvc && isHidCharUuid(el.uuid));
2297                     if (isRestrictedChar) {
2298                         restrictedIds.add(el.id);
2299                     }
2300                     break;
2301 
2302                 case GattDbElement.TYPE_DESCRIPTOR:
2303                     if (DBG) {
2304                         Log.d(TAG, "got descriptor with UUID=" + el.uuid + " id: " + el.id);
2305                     }
2306 
2307                     currChar.addDescriptor(new BluetoothGattDescriptor(el.uuid, el.id, 0));
2308                     if (isRestrictedChar) {
2309                         restrictedIds.add(el.id);
2310                     }
2311                     break;
2312 
2313                 case GattDbElement.TYPE_INCLUDED_SERVICE:
2314                     if (DBG) {
2315                         Log.d(TAG, "got included service with UUID=" + el.uuid + " id: " + el.id
2316                                 + " startHandle: " + el.startHandle);
2317                     }
2318 
2319                     currSrvc.addIncludedService(
2320                             new BluetoothGattService(el.uuid, el.startHandle, el.type));
2321                     break;
2322 
2323                 default:
2324                     Log.e(TAG, "got unknown element with type=" + el.type + " and UUID=" + el.uuid
2325                             + " id: " + el.id);
2326             }
2327         }
2328 
2329         if (!restrictedIds.isEmpty()) {
2330             mRestrictedHandles.put(connId, restrictedIds);
2331         }
2332         // Search is complete when there was error, or nothing more to process
2333         app.callback.onSearchComplete(address, dbOut, 0 /* status */);
2334     }
2335 
onRegisterForNotifications(int connId, int status, int registered, int handle)2336     void onRegisterForNotifications(int connId, int status, int registered, int handle) {
2337         String address = mClientMap.addressByConnId(connId);
2338 
2339         if (DBG) {
2340             Log.d(TAG, "onRegisterForNotifications() - address=" + address + ", status=" + status
2341                     + ", registered=" + registered + ", handle=" + handle);
2342         }
2343     }
2344 
onNotify(int connId, String address, int handle, boolean isNotify, byte[] data)2345     void onNotify(int connId, String address, int handle, boolean isNotify, byte[] data)
2346             throws RemoteException {
2347 
2348         if (VDBG) {
2349             Log.d(TAG, "onNotify() - address=" + address + ", handle=" + handle + ", length="
2350                     + data.length);
2351         }
2352 
2353         ClientMap.App app = mClientMap.getByConnId(connId);
2354         if (app != null) {
2355             try {
2356                 permissionCheck(connId, handle);
2357             } catch (SecurityException ex) {
2358                 // Only throws on apps with target SDK T+ as this old API did not throw prior to T
2359                 if (checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.TIRAMISU)) {
2360                     throw ex;
2361                 }
2362                 Log.w(TAG, "onNotify() - permission check failed!");
2363                 return;
2364             }
2365             app.callback.onNotify(address, handle, data);
2366         }
2367     }
2368 
onReadCharacteristic(int connId, int status, int handle, byte[] data)2369     void onReadCharacteristic(int connId, int status, int handle, byte[] data)
2370             throws RemoteException {
2371         String address = mClientMap.addressByConnId(connId);
2372 
2373         if (VDBG) {
2374             Log.d(TAG, "onReadCharacteristic() - address=" + address + ", status=" + status
2375                     + ", length=" + data.length);
2376         }
2377 
2378         ClientMap.App app = mClientMap.getByConnId(connId);
2379         if (app != null) {
2380             app.callback.onCharacteristicRead(address, status, handle, data);
2381         }
2382     }
2383 
onWriteCharacteristic(int connId, int status, int handle, byte[] data)2384     void onWriteCharacteristic(int connId, int status, int handle, byte[] data)
2385             throws RemoteException {
2386         String address = mClientMap.addressByConnId(connId);
2387         synchronized (mPermits) {
2388             Log.d(TAG, "onWriteCharacteristic() - increasing permit for address="
2389                     + address);
2390             mPermits.put(address, -1);
2391         }
2392 
2393         if (VDBG) {
2394             Log.d(TAG, "onWriteCharacteristic() - address=" + address + ", status=" + status
2395                     + ", length=" + data.length);
2396         }
2397 
2398         ClientMap.App app = mClientMap.getByConnId(connId);
2399         if (app == null) {
2400             return;
2401         }
2402 
2403         if (!app.isCongested) {
2404             app.callback.onCharacteristicWrite(address, status, handle, data);
2405         } else {
2406             if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
2407                 status = BluetoothGatt.GATT_SUCCESS;
2408             }
2409             CallbackInfo callbackInfo = new CallbackInfo.Builder(address, status)
2410                     .setHandle(handle)
2411                     .setValue(data)
2412                     .build();
2413             app.queueCallback(callbackInfo);
2414         }
2415     }
2416 
onExecuteCompleted(int connId, int status)2417     void onExecuteCompleted(int connId, int status) throws RemoteException {
2418         String address = mClientMap.addressByConnId(connId);
2419         if (VDBG) {
2420             Log.d(TAG, "onExecuteCompleted() - address=" + address + ", status=" + status);
2421         }
2422 
2423         ClientMap.App app = mClientMap.getByConnId(connId);
2424         if (app != null) {
2425             app.callback.onExecuteWrite(address, status);
2426         }
2427     }
2428 
onReadDescriptor(int connId, int status, int handle, byte[] data)2429     void onReadDescriptor(int connId, int status, int handle, byte[] data) throws RemoteException {
2430         String address = mClientMap.addressByConnId(connId);
2431 
2432         if (VDBG) {
2433             Log.d(TAG,
2434                     "onReadDescriptor() - address=" + address + ", status=" + status + ", length="
2435                             + data.length);
2436         }
2437 
2438         ClientMap.App app = mClientMap.getByConnId(connId);
2439         if (app != null) {
2440             app.callback.onDescriptorRead(address, status, handle, data);
2441         }
2442     }
2443 
onWriteDescriptor(int connId, int status, int handle, byte[] data)2444     void onWriteDescriptor(int connId, int status, int handle, byte[] data)
2445             throws RemoteException {
2446         String address = mClientMap.addressByConnId(connId);
2447 
2448         if (VDBG) {
2449             Log.d(TAG, "onWriteDescriptor() - address=" + address + ", status=" + status
2450                     + ", length=" + data.length);
2451         }
2452 
2453         ClientMap.App app = mClientMap.getByConnId(connId);
2454         if (app != null) {
2455             app.callback.onDescriptorWrite(address, status, handle, data);
2456         }
2457     }
2458 
onReadRemoteRssi(int clientIf, String address, int rssi, int status)2459     void onReadRemoteRssi(int clientIf, String address, int rssi, int status)
2460             throws RemoteException {
2461         if (DBG) {
2462             Log.d(TAG,
2463                     "onReadRemoteRssi() - clientIf=" + clientIf + " address=" + address + ", rssi="
2464                             + rssi + ", status=" + status);
2465         }
2466 
2467         ClientMap.App app = mClientMap.getById(clientIf);
2468         if (app != null) {
2469             app.callback.onReadRemoteRssi(address, rssi, status);
2470         }
2471     }
2472 
onScanFilterEnableDisabled(int action, int status, int clientIf)2473     void onScanFilterEnableDisabled(int action, int status, int clientIf) {
2474         if (DBG) {
2475             Log.d(TAG, "onScanFilterEnableDisabled() - clientIf=" + clientIf + ", status=" + status
2476                     + ", action=" + action);
2477         }
2478         mScanManager.callbackDone(clientIf, status);
2479     }
2480 
onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace)2481     void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) {
2482         if (DBG) {
2483             Log.d(TAG,
2484                     "onScanFilterParamsConfigured() - clientIf=" + clientIf + ", status=" + status
2485                             + ", action=" + action + ", availableSpace=" + availableSpace);
2486         }
2487         mScanManager.callbackDone(clientIf, status);
2488     }
2489 
onScanFilterConfig(int action, int status, int clientIf, int filterType, int availableSpace)2490     void onScanFilterConfig(int action, int status, int clientIf, int filterType,
2491             int availableSpace) {
2492         if (DBG) {
2493             Log.d(TAG, "onScanFilterConfig() - clientIf=" + clientIf + ", action = " + action
2494                     + " status = " + status + ", filterType=" + filterType + ", availableSpace="
2495                     + availableSpace);
2496         }
2497 
2498         mScanManager.callbackDone(clientIf, status);
2499     }
2500 
onBatchScanStorageConfigured(int status, int clientIf)2501     void onBatchScanStorageConfigured(int status, int clientIf) {
2502         if (DBG) {
2503             Log.d(TAG,
2504                     "onBatchScanStorageConfigured() - clientIf=" + clientIf + ", status=" + status);
2505         }
2506         mScanManager.callbackDone(clientIf, status);
2507     }
2508 
2509     // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped.
onBatchScanStartStopped(int startStopAction, int status, int clientIf)2510     void onBatchScanStartStopped(int startStopAction, int status, int clientIf) {
2511         if (DBG) {
2512             Log.d(TAG, "onBatchScanStartStopped() - clientIf=" + clientIf + ", status=" + status
2513                     + ", startStopAction=" + startStopAction);
2514         }
2515         mScanManager.callbackDone(clientIf, status);
2516     }
2517 
findBatchScanClientById(int scannerId)2518     ScanClient findBatchScanClientById(int scannerId) {
2519         for (ScanClient client : mScanManager.getBatchScanQueue()) {
2520             if (client.scannerId == scannerId) {
2521                 return client;
2522             }
2523         }
2524         return null;
2525     }
2526 
onBatchScanReports(int status, int scannerId, int reportType, int numRecords, byte[] recordData)2527     void onBatchScanReports(int status, int scannerId, int reportType, int numRecords,
2528             byte[] recordData) throws RemoteException {
2529         // When in testing mode, ignore all real-world events
2530         if (isTestModeEnabled()) return;
2531 
2532         onBatchScanReportsInternal(status, scannerId, reportType, numRecords, recordData);
2533     }
2534 
onBatchScanReportsInternal(int status, int scannerId, int reportType, int numRecords, byte[] recordData)2535     void onBatchScanReportsInternal(int status, int scannerId, int reportType, int numRecords,
2536             byte[] recordData) throws RemoteException {
2537         if (DBG) {
2538             Log.d(TAG, "onBatchScanReports() - scannerId=" + scannerId + ", status=" + status
2539                     + ", reportType=" + reportType + ", numRecords=" + numRecords);
2540         }
2541         mScanManager.callbackDone(scannerId, status);
2542         Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData);
2543         if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) {
2544             // We only support single client for truncated mode.
2545             ScannerMap.App app = mScannerMap.getById(scannerId);
2546             if (app == null) {
2547                 return;
2548             }
2549 
2550             ScanClient client = findBatchScanClientById(scannerId);
2551             if (client == null) {
2552                 return;
2553             }
2554 
2555             ArrayList<ScanResult> permittedResults;
2556             if (hasScanResultPermission(client)) {
2557                 permittedResults = new ArrayList<ScanResult>(results);
2558             } else {
2559                 permittedResults = new ArrayList<ScanResult>();
2560                 for (ScanResult scanResult : results) {
2561                     for (String associatedDevice : client.associatedDevices) {
2562                         if (associatedDevice.equalsIgnoreCase(scanResult.getDevice()
2563                                     .getAddress())) {
2564                             permittedResults.add(scanResult);
2565                         }
2566                     }
2567                 }
2568                 if (permittedResults.isEmpty()) {
2569                     return;
2570                 }
2571             }
2572 
2573             if (client.hasDisavowedLocation) {
2574                 permittedResults.removeIf(mLocationDenylistPredicate);
2575             }
2576 
2577             if (app.callback != null) {
2578                 app.callback.onBatchScanResults(permittedResults);
2579             } else {
2580                 // PendingIntent based
2581                 try {
2582                     sendResultsByPendingIntent(app.info, permittedResults,
2583                             ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
2584                 } catch (PendingIntent.CanceledException e) {
2585                 }
2586             }
2587         } else {
2588             for (ScanClient client : mScanManager.getFullBatchScanQueue()) {
2589                 // Deliver results for each client.
2590                 deliverBatchScan(client, results);
2591             }
2592         }
2593     }
2594 
sendBatchScanResults(ScannerMap.App app, ScanClient client, ArrayList<ScanResult> results)2595     private void sendBatchScanResults(ScannerMap.App app, ScanClient client,
2596             ArrayList<ScanResult> results) {
2597         try {
2598             if (app.callback != null) {
2599                 app.callback.onBatchScanResults(results);
2600             } else {
2601                 sendResultsByPendingIntent(app.info, results,
2602                         ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
2603             }
2604         } catch (RemoteException | PendingIntent.CanceledException e) {
2605             Log.e(TAG, "Exception: " + e);
2606             mScannerMap.remove(client.scannerId);
2607             mScanManager.stopScan(client.scannerId);
2608         }
2609     }
2610 
2611     // Check and deliver scan results for different scan clients.
deliverBatchScan(ScanClient client, Set<ScanResult> allResults)2612     private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults)
2613             throws RemoteException {
2614         ScannerMap.App app = mScannerMap.getById(client.scannerId);
2615         if (app == null) {
2616             return;
2617         }
2618 
2619         ArrayList<ScanResult> permittedResults;
2620         if (hasScanResultPermission(client)) {
2621             permittedResults = new ArrayList<ScanResult>(allResults);
2622         } else {
2623             permittedResults = new ArrayList<ScanResult>();
2624             for (ScanResult scanResult : allResults) {
2625                 for (String associatedDevice : client.associatedDevices) {
2626                     if (associatedDevice.equalsIgnoreCase(scanResult.getDevice().getAddress())) {
2627                         permittedResults.add(scanResult);
2628                     }
2629                 }
2630             }
2631             if (permittedResults.isEmpty()) {
2632                 return;
2633             }
2634         }
2635 
2636         if (client.filters == null || client.filters.isEmpty()) {
2637             sendBatchScanResults(app, client, permittedResults);
2638             // TODO: Question to reviewer: Shouldn't there be a return here?
2639         }
2640         // Reconstruct the scan results.
2641         ArrayList<ScanResult> results = new ArrayList<ScanResult>();
2642         for (ScanResult scanResult : permittedResults) {
2643             if (matchesFilters(client, scanResult).getMatches()) {
2644                 results.add(scanResult);
2645             }
2646         }
2647         sendBatchScanResults(app, client, results);
2648     }
2649 
parseBatchScanResults(int numRecords, int reportType, byte[] batchRecord)2650     private Set<ScanResult> parseBatchScanResults(int numRecords, int reportType,
2651             byte[] batchRecord) {
2652         if (numRecords == 0) {
2653             return Collections.emptySet();
2654         }
2655         if (DBG) {
2656             Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos());
2657         }
2658         if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) {
2659             return parseTruncatedResults(numRecords, batchRecord);
2660         } else {
2661             return parseFullResults(numRecords, batchRecord);
2662         }
2663     }
2664 
parseTruncatedResults(int numRecords, byte[] batchRecord)2665     private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) {
2666         if (DBG) {
2667             Log.d(TAG, "batch record " + Arrays.toString(batchRecord));
2668         }
2669         Set<ScanResult> results = new HashSet<ScanResult>(numRecords);
2670         long now = SystemClock.elapsedRealtimeNanos();
2671         for (int i = 0; i < numRecords; ++i) {
2672             byte[] record =
2673                     extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, TRUNCATED_RESULT_SIZE);
2674             byte[] address = extractBytes(record, 0, 6);
2675             reverse(address);
2676             BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
2677             int rssi = record[8];
2678             long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2));
2679             results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), rssi,
2680                     timestampNanos));
2681         }
2682         return results;
2683     }
2684 
2685     @VisibleForTesting
parseTimestampNanos(byte[] data)2686     long parseTimestampNanos(byte[] data) {
2687         long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data);
2688         // Timestamp is in every 50 ms.
2689         return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50);
2690     }
2691 
parseFullResults(int numRecords, byte[] batchRecord)2692     private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) {
2693         if (DBG) {
2694             Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord));
2695         }
2696         Set<ScanResult> results = new HashSet<ScanResult>(numRecords);
2697         int position = 0;
2698         long now = SystemClock.elapsedRealtimeNanos();
2699         while (position < batchRecord.length) {
2700             byte[] address = extractBytes(batchRecord, position, 6);
2701             // TODO: remove temp hack.
2702             reverse(address);
2703             BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
2704             position += 6;
2705             // Skip address type.
2706             position++;
2707             // Skip tx power level.
2708             position++;
2709             int rssi = batchRecord[position++];
2710             long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2));
2711             position += 2;
2712 
2713             // Combine advertise packet and scan response packet.
2714             int advertisePacketLen = batchRecord[position++];
2715             byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen);
2716             position += advertisePacketLen;
2717             int scanResponsePacketLen = batchRecord[position++];
2718             byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen);
2719             position += scanResponsePacketLen;
2720             byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen];
2721             System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen);
2722             System.arraycopy(scanResponseBytes, 0, scanRecord, advertisePacketLen,
2723                     scanResponsePacketLen);
2724             if (DBG) {
2725                 Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord));
2726             }
2727             results.add(new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), rssi,
2728                     timestampNanos));
2729         }
2730         return results;
2731     }
2732 
2733     // Reverse byte array.
reverse(byte[] address)2734     private void reverse(byte[] address) {
2735         int len = address.length;
2736         for (int i = 0; i < len / 2; ++i) {
2737             byte b = address[i];
2738             address[i] = address[len - 1 - i];
2739             address[len - 1 - i] = b;
2740         }
2741     }
2742 
2743     // Helper method to extract bytes from byte array.
extractBytes(byte[] scanRecord, int start, int length)2744     private static byte[] extractBytes(byte[] scanRecord, int start, int length) {
2745         byte[] bytes = new byte[length];
2746         System.arraycopy(scanRecord, start, bytes, 0, length);
2747         return bytes;
2748     }
2749 
2750     @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
onBatchScanThresholdCrossed(int clientIf)2751     void onBatchScanThresholdCrossed(int clientIf) {
2752         if (DBG) {
2753             Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf);
2754         }
2755         flushPendingBatchResults(clientIf, getAttributionSource());
2756     }
2757 
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)2758     AdvtFilterOnFoundOnLostInfo createOnTrackAdvFoundLostObject(int clientIf, int advPktLen,
2759             byte[] advPkt, int scanRspLen, byte[] scanRsp, int filtIndex, int advState,
2760             int advInfoPresent, String address, int addrType, int txPower, int rssiValue,
2761             int timeStamp) {
2762 
2763         return new AdvtFilterOnFoundOnLostInfo(clientIf, advPktLen, advPkt, scanRspLen, scanRsp,
2764                 filtIndex, advState, advInfoPresent, address, addrType, txPower, rssiValue,
2765                 timeStamp);
2766     }
2767 
onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo)2768     void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException {
2769         if (DBG) {
2770             Log.d(TAG, "onTrackAdvFoundLost() - scannerId= " + trackingInfo.getClientIf()
2771                     + " address = " + trackingInfo.getAddress() + " adv_state = "
2772                     + trackingInfo.getAdvState());
2773         }
2774 
2775         ScannerMap.App app = mScannerMap.getById(trackingInfo.getClientIf());
2776         if (app == null || (app.callback == null && app.info == null)) {
2777             Log.e(TAG, "app or callback is null");
2778             return;
2779         }
2780 
2781         BluetoothDevice device = BluetoothAdapter.getDefaultAdapter()
2782                 .getRemoteDevice(trackingInfo.getAddress());
2783         int advertiserState = trackingInfo.getAdvState();
2784         ScanResult result =
2785                 new ScanResult(device, ScanRecord.parseFromBytes(trackingInfo.getResult()),
2786                         trackingInfo.getRSSIValue(), SystemClock.elapsedRealtimeNanos());
2787 
2788         for (ScanClient client : mScanManager.getRegularScanQueue()) {
2789             if (client.scannerId == trackingInfo.getClientIf()) {
2790                 ScanSettings settings = client.settings;
2791                 if ((advertiserState == ADVT_STATE_ONFOUND) && (
2792                         (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_FIRST_MATCH)
2793                                 != 0)) {
2794                     if (app.callback != null) {
2795                         app.callback.onFoundOrLost(true, result);
2796                     } else {
2797                         sendResultByPendingIntent(app.info, result,
2798                                 ScanSettings.CALLBACK_TYPE_FIRST_MATCH, client);
2799                     }
2800                 } else if ((advertiserState == ADVT_STATE_ONLOST) && (
2801                         (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_MATCH_LOST)
2802                                 != 0)) {
2803                     if (app.callback != null) {
2804                         app.callback.onFoundOrLost(false, result);
2805                     } else {
2806                         sendResultByPendingIntent(app.info, result,
2807                                 ScanSettings.CALLBACK_TYPE_MATCH_LOST, client);
2808                     }
2809                 } else {
2810                     if (DBG) {
2811                         Log.d(TAG, "Not reporting onlost/onfound : " + advertiserState
2812                                 + " scannerId = " + client.scannerId + " callbackType "
2813                                 + settings.getCallbackType());
2814                     }
2815                 }
2816             }
2817         }
2818     }
2819 
onScanParamSetupCompleted(int status, int scannerId)2820     void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException {
2821         ScannerMap.App app = mScannerMap.getById(scannerId);
2822         if (app == null || app.callback == null) {
2823             Log.e(TAG, "Advertise app or callback is null");
2824             return;
2825         }
2826         if (DBG) {
2827             Log.d(TAG, "onScanParamSetupCompleted : " + status);
2828         }
2829     }
2830 
2831     // callback from ScanManager for dispatch of errors apps.
onScanManagerErrorCallback(int scannerId, int errorCode)2832     void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException {
2833         ScannerMap.App app = mScannerMap.getById(scannerId);
2834         if (app == null || (app.callback == null && app.info == null)) {
2835             Log.e(TAG, "App or callback is null");
2836             return;
2837         }
2838         if (app.callback != null) {
2839             app.callback.onScanManagerErrorCallback(errorCode);
2840         } else {
2841             try {
2842                 sendErrorByPendingIntent(app.info, errorCode);
2843             } catch (PendingIntent.CanceledException e) {
2844                 Log.e(TAG, "Error sending error code via PendingIntent:" + e);
2845             }
2846         }
2847     }
2848 
onConfigureMTU(int connId, int status, int mtu)2849     void onConfigureMTU(int connId, int status, int mtu) throws RemoteException {
2850         String address = mClientMap.addressByConnId(connId);
2851 
2852         if (DBG) {
2853             Log.d(TAG,
2854                     "onConfigureMTU() address=" + address + ", status=" + status + ", mtu=" + mtu);
2855         }
2856 
2857         ClientMap.App app = mClientMap.getByConnId(connId);
2858         if (app != null) {
2859             app.callback.onConfigureMTU(address, mtu, status);
2860         }
2861     }
2862 
onClientCongestion(int connId, boolean congested)2863     void onClientCongestion(int connId, boolean congested) throws RemoteException {
2864         if (VDBG) {
2865             Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested);
2866         }
2867 
2868         ClientMap.App app = mClientMap.getByConnId(connId);
2869 
2870         if (app != null) {
2871             app.isCongested = congested;
2872             while (!app.isCongested) {
2873                 CallbackInfo callbackInfo = app.popQueuedCallback();
2874                 if (callbackInfo == null) {
2875                     return;
2876                 }
2877                 app.callback.onCharacteristicWrite(callbackInfo.address, callbackInfo.status,
2878                         callbackInfo.handle, callbackInfo.value);
2879             }
2880         }
2881     }
2882 
2883     /**************************************************************************
2884      * GATT Service functions - Shared CLIENT/SERVER
2885      *************************************************************************/
2886 
2887     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
getDevicesMatchingConnectionStates( int[] states, AttributionSource attributionSource)2888     List<BluetoothDevice> getDevicesMatchingConnectionStates(
2889             int[] states, AttributionSource attributionSource) {
2890         if (!Utils.checkConnectPermissionForDataDelivery(
2891                 this, attributionSource,
2892                 "GattService getDevicesMatchingConnectionStates")) {
2893             return new ArrayList<>(0);
2894         }
2895 
2896         Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice, Integer>();
2897 
2898         // Add paired LE devices
2899 
2900         BluetoothDevice[] bondedDevices = mAdapterService.getBondedDevices();
2901         for (BluetoothDevice device : bondedDevices) {
2902             if (getDeviceType(device) != AbstractionLayer.BT_DEVICE_TYPE_BREDR) {
2903                 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED);
2904             }
2905         }
2906 
2907         // Add connected deviceStates
2908 
2909         Set<String> connectedDevices = new HashSet<String>();
2910         connectedDevices.addAll(mClientMap.getConnectedDevices());
2911         connectedDevices.addAll(mServerMap.getConnectedDevices());
2912 
2913         for (String address : connectedDevices) {
2914             BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
2915             if (device != null) {
2916                 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED);
2917             }
2918         }
2919 
2920         // Create matching device sub-set
2921 
2922         List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();
2923 
2924         for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) {
2925             for (int state : states) {
2926                 if (entry.getValue() == state) {
2927                     deviceList.add(entry.getKey());
2928                 }
2929             }
2930         }
2931 
2932         return deviceList;
2933     }
2934 
2935     @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
registerScanner(IScannerCallback callback, WorkSource workSource, AttributionSource attributionSource)2936     void registerScanner(IScannerCallback callback, WorkSource workSource,
2937             AttributionSource attributionSource) throws RemoteException {
2938         if (!Utils.checkScanPermissionForDataDelivery(
2939                 this, attributionSource, "GattService registerScanner")) {
2940             return;
2941         }
2942 
2943         UUID uuid = UUID.randomUUID();
2944         if (DBG) {
2945             Log.d(TAG, "registerScanner() - UUID=" + uuid);
2946         }
2947 
2948         enforceImpersonatationPermissionIfNeeded(workSource);
2949 
2950         AppScanStats app = mScannerMap.getAppScanStatsByUid(Binder.getCallingUid());
2951         if (app != null && app.isScanningTooFrequently()
2952                 && !Utils.checkCallerHasPrivilegedPermission(this)) {
2953             Log.e(TAG, "App '" + app.appName + "' is scanning too frequently");
2954             callback.onScannerRegistered(ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY, -1);
2955             return;
2956         }
2957 
2958         mScannerMap.add(uuid, workSource, callback, null, this);
2959         mScanManager.registerScanner(uuid);
2960     }
2961 
2962     @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
unregisterScanner(int scannerId, AttributionSource attributionSource)2963     void unregisterScanner(int scannerId, AttributionSource attributionSource) {
2964         if (!Utils.checkScanPermissionForDataDelivery(
2965                 this, attributionSource, "GattService unregisterScanner")) {
2966             return;
2967         }
2968 
2969         if (DBG) {
2970             Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId);
2971         }
2972         mScannerMap.remove(scannerId);
2973         mScanManager.unregisterScanner(scannerId);
2974     }
2975 
getAssociatedDevices(String callingPackage)2976     private List<String> getAssociatedDevices(String callingPackage) {
2977         if (mCompanionManager == null) {
2978             return Collections.emptyList();
2979         }
2980 
2981         List<String> macAddresses = new ArrayList();
2982 
2983         final long identity = Binder.clearCallingIdentity();
2984         try {
2985             for (AssociationInfo info : mCompanionManager.getAllAssociations()) {
2986                 if (info.getPackageName().equals(callingPackage) && !info.isSelfManaged()
2987                     && info.getDeviceMacAddress() != null) {
2988                     macAddresses.add(info.getDeviceMacAddress().toString());
2989                 }
2990             }
2991         } catch (SecurityException se) {
2992             // Not an app with associated devices
2993         } catch (Exception e) {
2994             Log.e(TAG, "Cannot check device associations for " + callingPackage, e);
2995         } finally {
2996             Binder.restoreCallingIdentity(identity);
2997         }
2998         return macAddresses;
2999     }
3000 
3001     @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, AttributionSource attributionSource)3002     void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters,
3003             AttributionSource attributionSource) {
3004         if (DBG) {
3005             Log.d(TAG, "start scan with filters");
3006         }
3007 
3008         if (!Utils.checkScanPermissionForDataDelivery(
3009                 this, attributionSource, "Starting GATT scan.")) {
3010             return;
3011         }
3012 
3013         enforcePrivilegedPermissionIfNeeded(settings);
3014         String callingPackage = attributionSource.getPackageName();
3015         settings = enforceReportDelayFloor(settings);
3016         enforcePrivilegedPermissionIfNeeded(filters);
3017         final ScanClient scanClient = new ScanClient(scannerId, settings, filters);
3018         scanClient.userHandle = Binder.getCallingUserHandle();
3019         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
3020         scanClient.eligibleForSanitizedExposureNotification =
3021                 callingPackage.equals(mExposureNotificationPackage);
3022 
3023         scanClient.hasDisavowedLocation =
3024                 Utils.hasDisavowedLocationForScan(this, attributionSource, isTestModeEnabled());
3025 
3026         scanClient.isQApp = checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q);
3027         if (!scanClient.hasDisavowedLocation) {
3028             if (scanClient.isQApp) {
3029                 scanClient.hasLocationPermission = Utils.checkCallerHasFineLocation(
3030                         this, attributionSource, scanClient.userHandle);
3031             } else {
3032                 scanClient.hasLocationPermission = Utils.checkCallerHasCoarseOrFineLocation(
3033                         this, attributionSource, scanClient.userHandle);
3034             }
3035         }
3036         scanClient.hasNetworkSettingsPermission =
3037                 Utils.checkCallerHasNetworkSettingsPermission(this);
3038         scanClient.hasNetworkSetupWizardPermission =
3039                 Utils.checkCallerHasNetworkSetupWizardPermission(this);
3040         scanClient.hasScanWithoutLocationPermission =
3041                 Utils.checkCallerHasScanWithoutLocationPermission(this);
3042         scanClient.associatedDevices = getAssociatedDevices(callingPackage);
3043 
3044         AppScanStats app = mScannerMap.getAppScanStatsById(scannerId);
3045         ScannerMap.App cbApp = mScannerMap.getById(scannerId);
3046         if (app != null) {
3047             scanClient.stats = app;
3048             boolean isFilteredScan = (filters != null) && !filters.isEmpty();
3049             boolean isCallbackScan = false;
3050             if (cbApp != null) {
3051                 isCallbackScan = cbApp.callback != null;
3052             }
3053             app.recordScanStart(settings, filters, isFilteredScan, isCallbackScan, scannerId);
3054         }
3055 
3056         mScanManager.startScan(scanClient);
3057         mAdapterService.notifyActivityAttributionInfo(getAttributionSource(),
3058                 AdapterService.ACTIVITY_ATTRIBUTION_NO_ACTIVE_DEVICE_ADDRESS);
3059     }
3060 
3061     @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
registerPiAndStartScan(PendingIntent pendingIntent, ScanSettings settings, List<ScanFilter> filters, AttributionSource attributionSource)3062     void registerPiAndStartScan(PendingIntent pendingIntent, ScanSettings settings,
3063             List<ScanFilter> filters, AttributionSource attributionSource) {
3064         if (DBG) {
3065             Log.d(TAG, "start scan with filters, for PendingIntent");
3066         }
3067 
3068         if (!Utils.checkScanPermissionForDataDelivery(
3069                 this, attributionSource, "Starting GATT scan.")) {
3070             return;
3071         }
3072         enforcePrivilegedPermissionIfNeeded(settings);
3073         settings = enforceReportDelayFloor(settings);
3074         enforcePrivilegedPermissionIfNeeded(filters);
3075         UUID uuid = UUID.randomUUID();
3076         if (DBG) {
3077             Log.d(TAG, "startScan(PI) - UUID=" + uuid);
3078         }
3079         String callingPackage = attributionSource.getPackageName();
3080         PendingIntentInfo piInfo = new PendingIntentInfo();
3081         piInfo.intent = pendingIntent;
3082         piInfo.settings = settings;
3083         piInfo.filters = filters;
3084         piInfo.callingPackage = callingPackage;
3085 
3086         // Don't start scan if the Pi scan already in mScannerMap.
3087         if (mScannerMap.getByContextInfo(piInfo) != null) {
3088             Log.d(TAG, "Don't startScan(PI) since the same Pi scan already in mScannerMap.");
3089             return;
3090         }
3091 
3092         ScannerMap.App app = mScannerMap.add(uuid, null, null, piInfo, this);
3093 
3094         app.mUserHandle = UserHandle.getUserHandleForUid(Binder.getCallingUid());
3095         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
3096         app.mEligibleForSanitizedExposureNotification =
3097                 callingPackage.equals(mExposureNotificationPackage);
3098 
3099         app.mHasDisavowedLocation =
3100                 Utils.hasDisavowedLocationForScan(this, attributionSource, isTestModeEnabled());
3101 
3102         if (!app.mHasDisavowedLocation) {
3103             try {
3104                 if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q)) {
3105                     app.hasLocationPermission = Utils.checkCallerHasFineLocation(
3106                             this, attributionSource, app.mUserHandle);
3107                 } else {
3108                     app.hasLocationPermission = Utils.checkCallerHasCoarseOrFineLocation(
3109                             this, attributionSource, app.mUserHandle);
3110                 }
3111             } catch (SecurityException se) {
3112                 // No need to throw here. Just mark as not granted.
3113                 app.hasLocationPermission = false;
3114             }
3115         }
3116         app.mHasNetworkSettingsPermission =
3117                 Utils.checkCallerHasNetworkSettingsPermission(this);
3118         app.mHasNetworkSetupWizardPermission =
3119                 Utils.checkCallerHasNetworkSetupWizardPermission(this);
3120         app.mHasScanWithoutLocationPermission =
3121                 Utils.checkCallerHasScanWithoutLocationPermission(this);
3122         app.mAssociatedDevices = getAssociatedDevices(callingPackage);
3123         mScanManager.registerScanner(uuid);
3124 
3125         // If this fails, we should stop the scan immediately.
3126         if (!pendingIntent.addCancelListener(Runnable::run, mScanIntentCancelListener)) {
3127             Log.d(TAG, "scanning PendingIntent is already cancelled, stopping scan.");
3128             stopScan(pendingIntent, attributionSource);
3129         }
3130     }
3131 
continuePiStartScan(int scannerId, ScannerMap.App app)3132     void continuePiStartScan(int scannerId, ScannerMap.App app) {
3133         final PendingIntentInfo piInfo = app.info;
3134         final ScanClient scanClient =
3135                 new ScanClient(scannerId, piInfo.settings, piInfo.filters);
3136         scanClient.hasLocationPermission = app.hasLocationPermission;
3137         scanClient.userHandle = app.mUserHandle;
3138         scanClient.isQApp = checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.Q);
3139         scanClient.eligibleForSanitizedExposureNotification =
3140                 app.mEligibleForSanitizedExposureNotification;
3141         scanClient.hasNetworkSettingsPermission = app.mHasNetworkSettingsPermission;
3142         scanClient.hasNetworkSetupWizardPermission = app.mHasNetworkSetupWizardPermission;
3143         scanClient.hasScanWithoutLocationPermission = app.mHasScanWithoutLocationPermission;
3144         scanClient.associatedDevices = app.mAssociatedDevices;
3145         scanClient.hasDisavowedLocation = app.mHasDisavowedLocation;
3146 
3147         AppScanStats scanStats = mScannerMap.getAppScanStatsById(scannerId);
3148         if (scanStats != null) {
3149             scanClient.stats = scanStats;
3150             boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty();
3151             scanStats.recordScanStart(
3152                     piInfo.settings, piInfo.filters, isFilteredScan, false, scannerId);
3153         }
3154 
3155         mScanManager.startScan(scanClient);
3156     }
3157 
3158     @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
flushPendingBatchResults(int scannerId, AttributionSource attributionSource)3159     void flushPendingBatchResults(int scannerId, AttributionSource attributionSource) {
3160         if (!Utils.checkScanPermissionForDataDelivery(
3161                 this, attributionSource, "GattService flushPendingBatchResults")) {
3162             return;
3163         }
3164         if (DBG) {
3165             Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId);
3166         }
3167         mScanManager.flushBatchScanResults(new ScanClient(scannerId));
3168     }
3169 
3170     @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
stopScan(int scannerId, AttributionSource attributionSource)3171     void stopScan(int scannerId, AttributionSource attributionSource) {
3172         if (!Utils.checkScanPermissionForDataDelivery(
3173                 this, attributionSource, "GattService stopScan")) {
3174             return;
3175         }
3176         int scanQueueSize =
3177                 mScanManager.getBatchScanQueue().size() + mScanManager.getRegularScanQueue().size();
3178         if (DBG) {
3179             Log.d(TAG, "stopScan() - queue size =" + scanQueueSize);
3180         }
3181 
3182         AppScanStats app = null;
3183         app = mScannerMap.getAppScanStatsById(scannerId);
3184         if (app != null) {
3185             app.recordScanStop(scannerId);
3186         }
3187 
3188         mScanManager.stopScan(scannerId);
3189         mAdapterService.notifyActivityAttributionInfo(getAttributionSource(),
3190                 AdapterService.ACTIVITY_ATTRIBUTION_NO_ACTIVE_DEVICE_ADDRESS);
3191     }
3192 
3193     @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
stopScan(PendingIntent intent, AttributionSource attributionSource)3194     void stopScan(PendingIntent intent, AttributionSource attributionSource) {
3195         if (!Utils.checkScanPermissionForDataDelivery(
3196                 this, attributionSource, "GattService stopScan")) {
3197             return;
3198         }
3199         PendingIntentInfo pii = new PendingIntentInfo();
3200         pii.intent = intent;
3201         ScannerMap.App app = mScannerMap.getByContextInfo(pii);
3202         if (VDBG) {
3203             Log.d(TAG, "stopScan(PendingIntent): app found = " + app);
3204         }
3205         if (app != null) {
3206             intent.removeCancelListener(mScanIntentCancelListener);
3207             final int scannerId = app.id;
3208             stopScan(scannerId, attributionSource);
3209             // Also unregister the scanner
3210             unregisterScanner(scannerId, attributionSource);
3211         }
3212     }
3213 
3214     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
disconnectAll(AttributionSource attributionSource)3215     void disconnectAll(AttributionSource attributionSource) {
3216         if (DBG) {
3217             Log.d(TAG, "disconnectAll()");
3218         }
3219         Map<Integer, String> connMap = mClientMap.getConnectedMap();
3220         for (Map.Entry<Integer, String> entry : connMap.entrySet()) {
3221             if (DBG) {
3222                 Log.d(TAG, "disconnecting addr:" + entry.getValue());
3223             }
3224             clientDisconnect(entry.getKey(), entry.getValue(), attributionSource);
3225             //clientDisconnect(int clientIf, String address)
3226         }
3227     }
3228 
3229     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
unregAll(AttributionSource attributionSource)3230     void unregAll(AttributionSource attributionSource) {
3231         for (Integer appId : mClientMap.getAllAppsIds()) {
3232             if (DBG) {
3233                 Log.d(TAG, "unreg:" + appId);
3234             }
3235             unregisterClient(appId, attributionSource);
3236         }
3237     }
3238 
3239     /**************************************************************************
3240      * PERIODIC SCANNING
3241      *************************************************************************/
3242     @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
registerSync(ScanResult scanResult, int skip, int timeout, IPeriodicAdvertisingCallback callback, AttributionSource attributionSource)3243     void registerSync(ScanResult scanResult, int skip, int timeout,
3244             IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) {
3245         if (!Utils.checkScanPermissionForDataDelivery(
3246                 this, attributionSource, "GattService registerSync")) {
3247             return;
3248         }
3249         mPeriodicScanManager.startSync(scanResult, skip, timeout, callback);
3250     }
3251 
3252     @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
unregisterSync( IPeriodicAdvertisingCallback callback, AttributionSource attributionSource)3253     void unregisterSync(
3254             IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) {
3255         if (!Utils.checkScanPermissionForDataDelivery(
3256                 this, attributionSource, "GattService unregisterSync")) {
3257             return;
3258         }
3259         mPeriodicScanManager.stopSync(callback);
3260     }
3261 
transferSync(BluetoothDevice bda, int serviceData, int syncHandle, AttributionSource attributionSource)3262     void transferSync(BluetoothDevice bda, int serviceData, int syncHandle,
3263             AttributionSource attributionSource) {
3264         if (!Utils.checkScanPermissionForDataDelivery(
3265                 this, attributionSource, "GattService transferSync")) {
3266             return;
3267         }
3268         mPeriodicScanManager.transferSync(bda, serviceData, syncHandle);
3269     }
3270 
transferSetInfo(BluetoothDevice bda, int serviceData, int advHandle, IPeriodicAdvertisingCallback callback, AttributionSource attributionSource)3271     void transferSetInfo(BluetoothDevice bda, int serviceData,
3272                   int advHandle, IPeriodicAdvertisingCallback callback,
3273                   AttributionSource attributionSource) {
3274         if (!Utils.checkScanPermissionForDataDelivery(
3275                 this, attributionSource, "GattService transferSetInfo")) {
3276             return;
3277         }
3278         mPeriodicScanManager.transferSetInfo(bda, serviceData, advHandle, callback);
3279     }
3280 
3281     /**************************************************************************
3282      * ADVERTISING SET
3283      *************************************************************************/
3284     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData, AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters, AdvertiseData periodicData, int duration, int maxExtAdvEvents, IAdvertisingSetCallback callback, AttributionSource attributionSource)3285     void startAdvertisingSet(AdvertisingSetParameters parameters, AdvertiseData advertiseData,
3286             AdvertiseData scanResponse, PeriodicAdvertisingParameters periodicParameters,
3287             AdvertiseData periodicData, int duration, int maxExtAdvEvents,
3288             IAdvertisingSetCallback callback, AttributionSource attributionSource) {
3289         if (!Utils.checkAdvertisePermissionForDataDelivery(
3290                 this, attributionSource, "GattService startAdvertisingSet")) {
3291             return;
3292         }
3293         if (parameters.getOwnAddressType() != AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT) {
3294             Utils.enforceBluetoothPrivilegedPermission(this);
3295         }
3296         mAdvertiseManager.startAdvertisingSet(parameters, advertiseData, scanResponse,
3297                 periodicParameters, periodicData, duration, maxExtAdvEvents, callback);
3298     }
3299 
3300     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
stopAdvertisingSet(IAdvertisingSetCallback callback, AttributionSource attributionSource)3301     void stopAdvertisingSet(IAdvertisingSetCallback callback, AttributionSource attributionSource) {
3302         if (!Utils.checkAdvertisePermissionForDataDelivery(
3303                 this, attributionSource, "GattService stopAdvertisingSet")) {
3304             return;
3305         }
3306         mAdvertiseManager.stopAdvertisingSet(callback);
3307     }
3308 
3309     @RequiresPermission(allOf = {
3310             android.Manifest.permission.BLUETOOTH_ADVERTISE,
3311             android.Manifest.permission.BLUETOOTH_PRIVILEGED,
3312     })
getOwnAddress(int advertiserId, AttributionSource attributionSource)3313     void getOwnAddress(int advertiserId, AttributionSource attributionSource) {
3314         if (!Utils.checkAdvertisePermissionForDataDelivery(
3315                 this, attributionSource, "GattService getOwnAddress")) {
3316             return;
3317         }
3318         enforceBluetoothPrivilegedPermission(this);
3319         mAdvertiseManager.getOwnAddress(advertiserId);
3320     }
3321 
3322     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents, AttributionSource attributionSource)3323     void enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents,
3324             AttributionSource attributionSource) {
3325         if (!Utils.checkAdvertisePermissionForDataDelivery(
3326                 this, attributionSource, "GattService enableAdvertisingSet")) {
3327             return;
3328         }
3329         mAdvertiseManager.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents);
3330     }
3331 
3332     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
setAdvertisingData( int advertiserId, AdvertiseData data, AttributionSource attributionSource)3333     void setAdvertisingData(
3334             int advertiserId, AdvertiseData data, AttributionSource attributionSource) {
3335         if (!Utils.checkAdvertisePermissionForDataDelivery(
3336                 this, attributionSource, "GattService setAdvertisingData")) {
3337             return;
3338         }
3339         mAdvertiseManager.setAdvertisingData(advertiserId, data);
3340     }
3341 
3342     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
setScanResponseData( int advertiserId, AdvertiseData data, AttributionSource attributionSource)3343     void setScanResponseData(
3344             int advertiserId, AdvertiseData data, AttributionSource attributionSource) {
3345         if (!Utils.checkAdvertisePermissionForDataDelivery(
3346                 this, attributionSource, "GattService setScanResponseData")) {
3347             return;
3348         }
3349         mAdvertiseManager.setScanResponseData(advertiserId, data);
3350     }
3351 
3352     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters, AttributionSource attributionSource)3353     void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters,
3354             AttributionSource attributionSource) {
3355         if (!Utils.checkAdvertisePermissionForDataDelivery(
3356                 this, attributionSource, "GattService setAdvertisingParameters")) {
3357             return;
3358         }
3359         mAdvertiseManager.setAdvertisingParameters(advertiserId, parameters);
3360     }
3361 
3362     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
setPeriodicAdvertisingParameters(int advertiserId, PeriodicAdvertisingParameters parameters, AttributionSource attributionSource)3363     void setPeriodicAdvertisingParameters(int advertiserId,
3364             PeriodicAdvertisingParameters parameters, AttributionSource attributionSource) {
3365         if (!Utils.checkAdvertisePermissionForDataDelivery(
3366                 this, attributionSource, "GattService setPeriodicAdvertisingParameters")) {
3367             return;
3368         }
3369         mAdvertiseManager.setPeriodicAdvertisingParameters(advertiserId, parameters);
3370     }
3371 
3372     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
setPeriodicAdvertisingData( int advertiserId, AdvertiseData data, AttributionSource attributionSource)3373     void setPeriodicAdvertisingData(
3374             int advertiserId, AdvertiseData data, AttributionSource attributionSource) {
3375         if (!Utils.checkAdvertisePermissionForDataDelivery(
3376                 this, attributionSource, "GattService setPeriodicAdvertisingData")) {
3377             return;
3378         }
3379         mAdvertiseManager.setPeriodicAdvertisingData(advertiserId, data);
3380     }
3381 
3382     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
setPeriodicAdvertisingEnable( int advertiserId, boolean enable, AttributionSource attributionSource)3383     void setPeriodicAdvertisingEnable(
3384             int advertiserId, boolean enable, AttributionSource attributionSource) {
3385         if (!Utils.checkAdvertisePermissionForDataDelivery(
3386                 this, attributionSource, "GattService setPeriodicAdvertisingEnable")) {
3387             return;
3388         }
3389         mAdvertiseManager.setPeriodicAdvertisingEnable(advertiserId, enable);
3390     }
3391 
3392     /**************************************************************************
3393      * GATT Service functions - CLIENT
3394      *************************************************************************/
3395 
3396     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
registerClient(UUID uuid, IBluetoothGattCallback callback, boolean eatt_support, AttributionSource attributionSource)3397     void registerClient(UUID uuid, IBluetoothGattCallback callback, boolean eatt_support,
3398             AttributionSource attributionSource) {
3399         if (!Utils.checkConnectPermissionForDataDelivery(
3400                 this, attributionSource, "GattService registerClient")) {
3401             return;
3402         }
3403 
3404         if (DBG) {
3405             Log.d(TAG, "registerClient() - UUID=" + uuid);
3406         }
3407         mClientMap.add(uuid, null, callback, null, this);
3408         gattClientRegisterAppNative(uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), eatt_support);
3409     }
3410 
3411     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
unregisterClient(int clientIf, AttributionSource attributionSource)3412     void unregisterClient(int clientIf, AttributionSource attributionSource) {
3413         if (!Utils.checkConnectPermissionForDataDelivery(
3414                 this, attributionSource, "GattService unregisterClient")) {
3415             return;
3416         }
3417 
3418         if (DBG) {
3419             Log.d(TAG, "unregisterClient() - clientIf=" + clientIf);
3420         }
3421         mClientMap.remove(clientIf);
3422         gattClientUnregisterAppNative(clientIf);
3423     }
3424 
3425     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
clientConnect(int clientIf, String address, boolean isDirect, int transport, boolean opportunistic, int phy, AttributionSource attributionSource)3426     void clientConnect(int clientIf, String address, boolean isDirect, int transport,
3427             boolean opportunistic, int phy, AttributionSource attributionSource) {
3428         if (!Utils.checkConnectPermissionForDataDelivery(
3429                 this, attributionSource, "GattService clientConnect")) {
3430             return;
3431         }
3432 
3433         if (DBG) {
3434             Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect
3435                     + ", opportunistic=" + opportunistic + ", phy=" + phy);
3436         }
3437         statsLogAppPackage(address, attributionSource.getUid(), clientIf);
3438         statsLogGattConnectionStateChange(
3439                 BluetoothProfile.GATT, address, clientIf,
3440                 BluetoothProtoEnums.CONNECTION_STATE_CONNECTING, -1);
3441         gattClientConnectNative(clientIf, address, isDirect, transport, opportunistic, phy);
3442     }
3443 
3444     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
clientDisconnect(int clientIf, String address, AttributionSource attributionSource)3445     void clientDisconnect(int clientIf, String address, AttributionSource attributionSource) {
3446         if (!Utils.checkConnectPermissionForDataDelivery(
3447                 this, attributionSource, "GattService clientDisconnect")) {
3448             return;
3449         }
3450 
3451         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3452         if (DBG) {
3453             Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId);
3454         }
3455         statsLogGattConnectionStateChange(
3456                 BluetoothProfile.GATT, address, clientIf,
3457                 BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING, -1);
3458         gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0);
3459     }
3460 
3461     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions, AttributionSource attributionSource)3462     void clientSetPreferredPhy(int clientIf, String address, int txPhy, int rxPhy, int phyOptions,
3463             AttributionSource attributionSource) {
3464         if (!Utils.checkConnectPermissionForDataDelivery(
3465                 this, attributionSource, "GattService clientSetPreferredPhy")) {
3466             return;
3467         }
3468 
3469         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3470         if (connId == null) {
3471             if (DBG) {
3472                 Log.d(TAG, "clientSetPreferredPhy() - no connection to " + address);
3473             }
3474             return;
3475         }
3476 
3477         if (DBG) {
3478             Log.d(TAG, "clientSetPreferredPhy() - address=" + address + ", connId=" + connId);
3479         }
3480         gattClientSetPreferredPhyNative(clientIf, address, txPhy, rxPhy, phyOptions);
3481     }
3482 
3483     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
clientReadPhy(int clientIf, String address, AttributionSource attributionSource)3484     void clientReadPhy(int clientIf, String address, AttributionSource attributionSource) {
3485         if (!Utils.checkConnectPermissionForDataDelivery(
3486                 this, attributionSource, "GattService clientReadPhy")) {
3487             return;
3488         }
3489 
3490         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3491         if (connId == null) {
3492             if (DBG) {
3493                 Log.d(TAG, "clientReadPhy() - no connection to " + address);
3494             }
3495             return;
3496         }
3497 
3498         if (DBG) {
3499             Log.d(TAG, "clientReadPhy() - address=" + address + ", connId=" + connId);
3500         }
3501         gattClientReadPhyNative(clientIf, address);
3502     }
3503 
3504     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
numHwTrackFiltersAvailable(AttributionSource attributionSource)3505     int numHwTrackFiltersAvailable(AttributionSource attributionSource) {
3506         if (!Utils.checkConnectPermissionForDataDelivery(
3507                 this, attributionSource, "GattService numHwTrackFiltersAvailable")) {
3508             return 0;
3509         }
3510         return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements()
3511                 - mScanManager.getCurrentUsedTrackingAdvertisement());
3512     }
3513 
3514     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
getRegisteredServiceUuids(AttributionSource attributionSource)3515     synchronized List<ParcelUuid> getRegisteredServiceUuids(AttributionSource attributionSource) {
3516         if (!Utils.checkConnectPermissionForDataDelivery(
3517                 this, attributionSource, "GattService getRegisteredServiceUuids")) {
3518             return new ArrayList<>(0);
3519         }
3520         List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>();
3521         for (HandleMap.Entry entry : mHandleMap.getEntries()) {
3522             serviceUuids.add(new ParcelUuid(entry.uuid));
3523         }
3524         return serviceUuids;
3525     }
3526 
3527     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
getConnectedDevices(AttributionSource attributionSource)3528     List<String> getConnectedDevices(AttributionSource attributionSource) {
3529         if (!Utils.checkConnectPermissionForDataDelivery(
3530                 this, attributionSource, "GattService getConnectedDevices")) {
3531             return new ArrayList<>(0);
3532         }
3533 
3534         Set<String> connectedDevAddress = new HashSet<String>();
3535         connectedDevAddress.addAll(mClientMap.getConnectedDevices());
3536         connectedDevAddress.addAll(mServerMap.getConnectedDevices());
3537         List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress);
3538         return connectedDeviceList;
3539     }
3540 
3541     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
refreshDevice(int clientIf, String address, AttributionSource attributionSource)3542     void refreshDevice(int clientIf, String address, AttributionSource attributionSource) {
3543         if (!Utils.checkConnectPermissionForDataDelivery(
3544                 this, attributionSource, "GattService refreshDevice")) {
3545             return;
3546         }
3547 
3548         if (DBG) {
3549             Log.d(TAG, "refreshDevice() - address=" + address);
3550         }
3551         gattClientRefreshNative(clientIf, address);
3552     }
3553 
3554     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
discoverServices(int clientIf, String address, AttributionSource attributionSource)3555     void discoverServices(int clientIf, String address, AttributionSource attributionSource) {
3556         if (!Utils.checkConnectPermissionForDataDelivery(
3557                 this, attributionSource, "GattService discoverServices")) {
3558             return;
3559         }
3560 
3561         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3562         if (DBG) {
3563             Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId);
3564         }
3565 
3566         if (connId != null) {
3567             gattClientSearchServiceNative(connId, true, 0, 0);
3568         } else {
3569             Log.e(TAG, "discoverServices() - No connection for " + address + "...");
3570         }
3571     }
3572 
3573     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
discoverServiceByUuid( int clientIf, String address, UUID uuid, AttributionSource attributionSource)3574     void discoverServiceByUuid(
3575             int clientIf, String address, UUID uuid, AttributionSource attributionSource) {
3576         if (!Utils.checkConnectPermissionForDataDelivery(
3577                 this, attributionSource, "GattService discoverServiceByUuid")) {
3578             return;
3579         }
3580 
3581         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3582         if (connId != null) {
3583             gattClientDiscoverServiceByUuidNative(connId, uuid.getLeastSignificantBits(),
3584                     uuid.getMostSignificantBits());
3585         } else {
3586             Log.e(TAG, "discoverServiceByUuid() - No connection for " + address + "...");
3587         }
3588     }
3589 
3590     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
readCharacteristic(int clientIf, String address, int handle, int authReq, AttributionSource attributionSource)3591     void readCharacteristic(int clientIf, String address, int handle, int authReq,
3592             AttributionSource attributionSource) {
3593         if (!Utils.checkConnectPermissionForDataDelivery(
3594                 this, attributionSource, "GattService readCharacteristic")) {
3595             return;
3596         }
3597 
3598         if (VDBG) {
3599             Log.d(TAG, "readCharacteristic() - address=" + address);
3600         }
3601 
3602         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3603         if (connId == null) {
3604             Log.e(TAG, "readCharacteristic() - No connection for " + address + "...");
3605             return;
3606         }
3607 
3608         try {
3609             permissionCheck(connId, handle);
3610         } catch (SecurityException ex) {
3611             String callingPackage = attributionSource.getPackageName();
3612             // Only throws on apps with target SDK T+ as this old API did not throw prior to T
3613             if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) {
3614                 throw ex;
3615             }
3616             Log.w(TAG, "readCharacteristic() - permission check failed!");
3617             return;
3618         }
3619 
3620         gattClientReadCharacteristicNative(connId, handle, authReq);
3621     }
3622 
3623     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
readUsingCharacteristicUuid(int clientIf, String address, UUID uuid, int startHandle, int endHandle, int authReq, AttributionSource attributionSource)3624     void readUsingCharacteristicUuid(int clientIf, String address, UUID uuid, int startHandle,
3625             int endHandle, int authReq, AttributionSource attributionSource) {
3626         if (!Utils.checkConnectPermissionForDataDelivery(
3627                 this, attributionSource, "GattService readUsingCharacteristicUuid")) {
3628             return;
3629         }
3630 
3631         if (VDBG) {
3632             Log.d(TAG, "readUsingCharacteristicUuid() - address=" + address);
3633         }
3634 
3635         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3636         if (connId == null) {
3637             Log.e(TAG, "readUsingCharacteristicUuid() - No connection for " + address + "...");
3638             return;
3639         }
3640 
3641         try {
3642             permissionCheck(uuid);
3643         } catch (SecurityException ex) {
3644             String callingPackage = attributionSource.getPackageName();
3645             // Only throws on apps with target SDK T+ as this old API did not throw prior to T
3646             if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) {
3647                 throw ex;
3648             }
3649             Log.w(TAG, "readUsingCharacteristicUuid() - permission check failed!");
3650             return;
3651         }
3652 
3653         gattClientReadUsingCharacteristicUuidNative(connId, uuid.getLeastSignificantBits(),
3654                 uuid.getMostSignificantBits(), startHandle, endHandle, authReq);
3655     }
3656 
3657     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq, byte[] value, AttributionSource attributionSource)3658     int writeCharacteristic(int clientIf, String address, int handle, int writeType, int authReq,
3659             byte[] value, AttributionSource attributionSource) {
3660         if (!Utils.checkConnectPermissionForDataDelivery(
3661                 this, attributionSource, "GattService writeCharacteristic")) {
3662             return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
3663         }
3664 
3665         if (VDBG) {
3666             Log.d(TAG, "writeCharacteristic() - address=" + address);
3667         }
3668 
3669         if (mReliableQueue.contains(address)) {
3670             writeType = 3; // Prepared write
3671         }
3672 
3673         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3674         if (connId == null) {
3675             Log.e(TAG, "writeCharacteristic() - No connection for " + address + "...");
3676             return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED;
3677         }
3678         permissionCheck(connId, handle);
3679 
3680         Log.d(TAG, "writeCharacteristic() - trying to acquire permit.");
3681         // Lock the thread until onCharacteristicWrite callback comes back.
3682         synchronized (mPermits) {
3683             Integer permit = mPermits.get(address);
3684             if (permit == null) {
3685                 Log.d(TAG, "writeCharacteristic() -  atomicBoolean uninitialized!");
3686                 return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED;
3687             }
3688 
3689             boolean success = (permit == -1);
3690             if (!success) {
3691                 Log.d(TAG, "writeCharacteristic() - no permit available.");
3692                 return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
3693             }
3694             mPermits.put(address, connId);
3695         }
3696 
3697         gattClientWriteCharacteristicNative(connId, handle, writeType, authReq, value);
3698         return BluetoothStatusCodes.SUCCESS;
3699     }
3700 
3701     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
readDescriptor(int clientIf, String address, int handle, int authReq, AttributionSource attributionSource)3702     void readDescriptor(int clientIf, String address, int handle, int authReq,
3703             AttributionSource attributionSource) {
3704         if (!Utils.checkConnectPermissionForDataDelivery(
3705                 this, attributionSource, "GattService readDescriptor")) {
3706             return;
3707         }
3708 
3709         if (VDBG) {
3710             Log.d(TAG, "readDescriptor() - address=" + address);
3711         }
3712 
3713         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3714         if (connId == null) {
3715             Log.e(TAG, "readDescriptor() - No connection for " + address + "...");
3716             return;
3717         }
3718 
3719         try {
3720             permissionCheck(connId, handle);
3721         } catch (SecurityException ex) {
3722             String callingPackage = attributionSource.getPackageName();
3723             // Only throws on apps with target SDK T+ as this old API did not throw prior to T
3724             if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) {
3725                 throw ex;
3726             }
3727             Log.w(TAG, "readDescriptor() - permission check failed!");
3728             return;
3729         }
3730 
3731         gattClientReadDescriptorNative(connId, handle, authReq);
3732     }
3733 
3734     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value, AttributionSource attributionSource)3735     int writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value,
3736             AttributionSource attributionSource) {
3737         if (!Utils.checkConnectPermissionForDataDelivery(
3738                 this, attributionSource, "GattService writeDescriptor")) {
3739             return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
3740         }
3741         if (VDBG) {
3742             Log.d(TAG, "writeDescriptor() - address=" + address);
3743         }
3744 
3745         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3746         if (connId == null) {
3747             Log.e(TAG, "writeDescriptor() - No connection for " + address + "...");
3748             return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED;
3749         }
3750         permissionCheck(connId, handle);
3751 
3752         gattClientWriteDescriptorNative(connId, handle, authReq, value);
3753         return BluetoothStatusCodes.SUCCESS;
3754     }
3755 
3756     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
beginReliableWrite(int clientIf, String address, AttributionSource attributionSource)3757     void beginReliableWrite(int clientIf, String address, AttributionSource attributionSource) {
3758         if (!Utils.checkConnectPermissionForDataDelivery(
3759                 this, attributionSource, "GattService beginReliableWrite")) {
3760             return;
3761         }
3762 
3763         if (DBG) {
3764             Log.d(TAG, "beginReliableWrite() - address=" + address);
3765         }
3766         mReliableQueue.add(address);
3767     }
3768 
3769     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
endReliableWrite( int clientIf, String address, boolean execute, AttributionSource attributionSource)3770     void endReliableWrite(
3771             int clientIf, String address, boolean execute, AttributionSource attributionSource) {
3772         if (!Utils.checkConnectPermissionForDataDelivery(
3773                 this, attributionSource, "GattService endReliableWrite")) {
3774             return;
3775         }
3776 
3777         if (DBG) {
3778             Log.d(TAG, "endReliableWrite() - address=" + address + " execute: " + execute);
3779         }
3780         mReliableQueue.remove(address);
3781 
3782         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3783         if (connId != null) {
3784             gattClientExecuteWriteNative(connId, execute);
3785         }
3786     }
3787 
3788     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
registerForNotification(int clientIf, String address, int handle, boolean enable, AttributionSource attributionSource)3789     void registerForNotification(int clientIf, String address, int handle, boolean enable,
3790             AttributionSource attributionSource) {
3791         if (!Utils.checkConnectPermissionForDataDelivery(
3792                 this, attributionSource, "GattService registerForNotification")) {
3793             return;
3794         }
3795 
3796         if (DBG) {
3797             Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable);
3798         }
3799 
3800         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3801         if (connId == null) {
3802             Log.e(TAG, "registerForNotification() - No connection for " + address + "...");
3803             return;
3804         }
3805 
3806         try {
3807             permissionCheck(connId, handle);
3808         } catch (SecurityException ex) {
3809             String callingPackage = attributionSource.getPackageName();
3810             // Only throws on apps with target SDK T+ as this old API did not throw prior to T
3811             if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) {
3812                 throw ex;
3813             }
3814             Log.w(TAG, "registerForNotification() - permission check failed!");
3815             return;
3816         }
3817 
3818         gattClientRegisterForNotificationsNative(clientIf, address, handle, enable);
3819     }
3820 
3821     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
readRemoteRssi(int clientIf, String address, AttributionSource attributionSource)3822     void readRemoteRssi(int clientIf, String address, AttributionSource attributionSource) {
3823         if (!Utils.checkConnectPermissionForDataDelivery(
3824                 this, attributionSource, "GattService readRemoteRssi")) {
3825             return;
3826         }
3827 
3828         if (DBG) {
3829             Log.d(TAG, "readRemoteRssi() - address=" + address);
3830         }
3831         gattClientReadRemoteRssiNative(clientIf, address);
3832     }
3833 
3834     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
configureMTU(int clientIf, String address, int mtu, AttributionSource attributionSource)3835     void configureMTU(int clientIf, String address, int mtu, AttributionSource attributionSource) {
3836         if (!Utils.checkConnectPermissionForDataDelivery(
3837                 this, attributionSource, "GattService configureMTU")) {
3838             return;
3839         }
3840 
3841         if (DBG) {
3842             Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu);
3843         }
3844         Integer connId = mClientMap.connIdByAddress(clientIf, address);
3845         if (connId != null) {
3846             gattClientConfigureMTUNative(connId, mtu);
3847         } else {
3848             Log.e(TAG, "configureMTU() - No connection for " + address + "...");
3849         }
3850     }
3851 
3852     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
connectionParameterUpdate(int clientIf, String address, int connectionPriority, AttributionSource attributionSource)3853     void connectionParameterUpdate(int clientIf, String address, int connectionPriority,
3854             AttributionSource attributionSource) {
3855         if (!Utils.checkConnectPermissionForDataDelivery(
3856                 this, attributionSource, "GattService connectionParameterUpdate")) {
3857             return;
3858         }
3859 
3860         int minInterval;
3861         int maxInterval;
3862 
3863         // Peripheral latency
3864         int latency;
3865 
3866         // Link supervision timeout is measured in N * 10ms
3867         int timeout = 500; // 5s
3868 
3869 
3870         CompanionManager manager =
3871                 AdapterService.getAdapterService().getCompanionManager();
3872 
3873         minInterval = manager.getGattConnParameters(
3874                 address, CompanionManager.GATT_CONN_INTERVAL_MIN, connectionPriority);
3875         maxInterval = manager.getGattConnParameters(
3876                 address, CompanionManager.GATT_CONN_INTERVAL_MAX, connectionPriority);
3877         latency = manager.getGattConnParameters(
3878                 address, CompanionManager.GATT_CONN_LATENCY, connectionPriority);
3879 
3880         Log.d(TAG, "connectionParameterUpdate() - address=" + address + " params="
3881                 + connectionPriority + " interval=" + minInterval + "/" + maxInterval
3882                 + " timeout=" + timeout);
3883 
3884         gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval, latency,
3885                 timeout, 0, 0);
3886     }
3887 
3888     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
leConnectionUpdate(int clientIf, String address, int minInterval, int maxInterval, int peripheralLatency, int supervisionTimeout, int minConnectionEventLen, int maxConnectionEventLen, AttributionSource attributionSource)3889     void leConnectionUpdate(int clientIf, String address, int minInterval,
3890                             int maxInterval, int peripheralLatency,
3891                             int supervisionTimeout, int minConnectionEventLen,
3892                             int maxConnectionEventLen, AttributionSource attributionSource) {
3893         if (!Utils.checkConnectPermissionForDataDelivery(
3894                 this, attributionSource, "GattService leConnectionUpdate")) {
3895             return;
3896         }
3897 
3898         Log.d(TAG, "leConnectionUpdate() - address=" + address + ", intervals="
3899                     + minInterval + "/" + maxInterval + ", latency=" + peripheralLatency
3900                     + ", timeout=" + supervisionTimeout + "msec" + ", min_ce="
3901                     + minConnectionEventLen + ", max_ce=" + maxConnectionEventLen);
3902 
3903         gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval,
3904                                             peripheralLatency, supervisionTimeout,
3905                                             minConnectionEventLen, maxConnectionEventLen);
3906     }
3907 
3908     /**************************************************************************
3909      * Callback functions - SERVER
3910      *************************************************************************/
3911 
onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb)3912     void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb)
3913             throws RemoteException {
3914 
3915         UUID uuid = new UUID(uuidMsb, uuidLsb);
3916         if (DBG) {
3917             Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf);
3918         }
3919         ServerMap.App app = mServerMap.getByUuid(uuid);
3920         if (app != null) {
3921             app.id = serverIf;
3922             app.linkToDeath(new ServerDeathRecipient(serverIf));
3923             app.callback.onServerRegistered(status, serverIf);
3924         }
3925     }
3926 
onServiceAdded(int status, int serverIf, List<GattDbElement> service)3927     void onServiceAdded(int status, int serverIf, List<GattDbElement> service)
3928             throws RemoteException {
3929         if (DBG) {
3930             Log.d(TAG, "onServiceAdded(), status=" + status);
3931         }
3932 
3933         if (status != 0) {
3934             return;
3935         }
3936 
3937         GattDbElement svcEl = service.get(0);
3938         int srvcHandle = svcEl.attributeHandle;
3939 
3940         BluetoothGattService svc = null;
3941 
3942         for (GattDbElement el : service) {
3943             if (el.type == GattDbElement.TYPE_PRIMARY_SERVICE) {
3944                 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid,
3945                         BluetoothGattService.SERVICE_TYPE_PRIMARY, 0, false);
3946                 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle,
3947                         BluetoothGattService.SERVICE_TYPE_PRIMARY);
3948             } else if (el.type == GattDbElement.TYPE_SECONDARY_SERVICE) {
3949                 mHandleMap.addService(serverIf, el.attributeHandle, el.uuid,
3950                         BluetoothGattService.SERVICE_TYPE_SECONDARY, 0, false);
3951                 svc = new BluetoothGattService(svcEl.uuid, svcEl.attributeHandle,
3952                         BluetoothGattService.SERVICE_TYPE_SECONDARY);
3953             } else if (el.type == GattDbElement.TYPE_CHARACTERISTIC) {
3954                 mHandleMap.addCharacteristic(serverIf, el.attributeHandle, el.uuid, srvcHandle);
3955                 svc.addCharacteristic(
3956                         new BluetoothGattCharacteristic(el.uuid, el.attributeHandle, el.properties,
3957                                 el.permissions));
3958             } else if (el.type == GattDbElement.TYPE_DESCRIPTOR) {
3959                 mHandleMap.addDescriptor(serverIf, el.attributeHandle, el.uuid, srvcHandle);
3960                 List<BluetoothGattCharacteristic> chars = svc.getCharacteristics();
3961                 chars.get(chars.size() - 1)
3962                         .addDescriptor(new BluetoothGattDescriptor(el.uuid, el.attributeHandle,
3963                                 el.permissions));
3964             }
3965         }
3966         mHandleMap.setStarted(serverIf, srvcHandle, true);
3967 
3968         ServerMap.App app = mServerMap.getById(serverIf);
3969         if (app != null) {
3970             app.callback.onServiceAdded(status, svc);
3971         }
3972     }
3973 
onServiceStopped(int status, int serverIf, int srvcHandle)3974     void onServiceStopped(int status, int serverIf, int srvcHandle) throws RemoteException {
3975         if (DBG) {
3976             Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle + ", status=" + status);
3977         }
3978         if (status == 0) {
3979             mHandleMap.setStarted(serverIf, srvcHandle, false);
3980         }
3981         stopNextService(serverIf, status);
3982     }
3983 
onServiceDeleted(int status, int serverIf, int srvcHandle)3984     void onServiceDeleted(int status, int serverIf, int srvcHandle) {
3985         if (DBG) {
3986             Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle + ", status=" + status);
3987         }
3988         mHandleMap.deleteService(serverIf, srvcHandle);
3989     }
3990 
onClientConnected(String address, boolean connected, int connId, int serverIf)3991     void onClientConnected(String address, boolean connected, int connId, int serverIf)
3992             throws RemoteException {
3993 
3994         if (DBG) {
3995             Log.d(TAG,
3996                     "onClientConnected() connId=" + connId + ", address=" + address + ", connected="
3997                             + connected);
3998         }
3999 
4000         ServerMap.App app = mServerMap.getById(serverIf);
4001         if (app == null) {
4002             return;
4003         }
4004         int connectionState;
4005         if (connected) {
4006             mServerMap.addConnection(serverIf, connId, address);
4007             connectionState = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;
4008         } else {
4009             mServerMap.removeConnection(serverIf, connId);
4010             connectionState = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;
4011         }
4012 
4013         int applicationUid = -1;
4014 
4015         try {
4016           applicationUid = this.getPackageManager().getPackageUid(app.name, PackageInfoFlags.of(0));
4017 
4018         } catch (NameNotFoundException e) {
4019           Log.d(TAG, "onClientConnected() uid_not_found=" + app.name);
4020         }
4021 
4022         app.callback.onServerConnectionState((byte) 0, serverIf, connected, address);
4023         statsLogAppPackage(address, applicationUid, serverIf);
4024         statsLogGattConnectionStateChange(
4025                 BluetoothProfile.GATT_SERVER, address, serverIf, connectionState, -1);
4026     }
4027 
onServerReadCharacteristic(String address, int connId, int transId, int handle, int offset, boolean isLong)4028     void onServerReadCharacteristic(String address, int connId, int transId, int handle, int offset,
4029             boolean isLong) throws RemoteException {
4030         if (VDBG) {
4031             Log.d(TAG, "onServerReadCharacteristic() connId=" + connId + ", address=" + address
4032                     + ", handle=" + handle + ", requestId=" + transId + ", offset=" + offset);
4033         }
4034 
4035         HandleMap.Entry entry = mHandleMap.getByHandle(handle);
4036         if (entry == null) {
4037             return;
4038         }
4039 
4040         mHandleMap.addRequest(transId, handle);
4041 
4042         ServerMap.App app = mServerMap.getById(entry.serverIf);
4043         if (app == null) {
4044             return;
4045         }
4046 
4047         app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, handle);
4048     }
4049 
onServerReadDescriptor(String address, int connId, int transId, int handle, int offset, boolean isLong)4050     void onServerReadDescriptor(String address, int connId, int transId, int handle, int offset,
4051             boolean isLong) throws RemoteException {
4052         if (VDBG) {
4053             Log.d(TAG, "onServerReadDescriptor() connId=" + connId + ", address=" + address
4054                     + ", handle=" + handle + ", requestId=" + transId + ", offset=" + offset);
4055         }
4056 
4057         HandleMap.Entry entry = mHandleMap.getByHandle(handle);
4058         if (entry == null) {
4059             return;
4060         }
4061 
4062         mHandleMap.addRequest(transId, handle);
4063 
4064         ServerMap.App app = mServerMap.getById(entry.serverIf);
4065         if (app == null) {
4066             return;
4067         }
4068 
4069         app.callback.onDescriptorReadRequest(address, transId, offset, isLong, handle);
4070     }
4071 
onServerWriteCharacteristic(String address, int connId, int transId, int handle, int offset, int length, boolean needRsp, boolean isPrep, byte[] data)4072     void onServerWriteCharacteristic(String address, int connId, int transId, int handle,
4073             int offset, int length, boolean needRsp, boolean isPrep, byte[] data)
4074             throws RemoteException {
4075         if (VDBG) {
4076             Log.d(TAG, "onServerWriteCharacteristic() connId=" + connId + ", address=" + address
4077                     + ", handle=" + handle + ", requestId=" + transId + ", isPrep=" + isPrep
4078                     + ", offset=" + offset);
4079         }
4080 
4081         HandleMap.Entry entry = mHandleMap.getByHandle(handle);
4082         if (entry == null) {
4083             return;
4084         }
4085 
4086         mHandleMap.addRequest(transId, handle);
4087 
4088         ServerMap.App app = mServerMap.getById(entry.serverIf);
4089         if (app == null) {
4090             return;
4091         }
4092 
4093         app.callback.onCharacteristicWriteRequest(address, transId, offset, length, isPrep, needRsp,
4094                 handle, data);
4095     }
4096 
onServerWriteDescriptor(String address, int connId, int transId, int handle, int offset, int length, boolean needRsp, boolean isPrep, byte[] data)4097     void onServerWriteDescriptor(String address, int connId, int transId, int handle, int offset,
4098             int length, boolean needRsp, boolean isPrep, byte[] data) throws RemoteException {
4099         if (VDBG) {
4100             Log.d(TAG, "onAttributeWrite() connId=" + connId + ", address=" + address + ", handle="
4101                     + handle + ", requestId=" + transId + ", isPrep=" + isPrep + ", offset="
4102                     + offset);
4103         }
4104 
4105         HandleMap.Entry entry = mHandleMap.getByHandle(handle);
4106         if (entry == null) {
4107             return;
4108         }
4109 
4110         mHandleMap.addRequest(transId, handle);
4111 
4112         ServerMap.App app = mServerMap.getById(entry.serverIf);
4113         if (app == null) {
4114             return;
4115         }
4116 
4117         app.callback.onDescriptorWriteRequest(address, transId, offset, length, isPrep, needRsp,
4118                 handle, data);
4119     }
4120 
onExecuteWrite(String address, int connId, int transId, int execWrite)4121     void onExecuteWrite(String address, int connId, int transId, int execWrite)
4122             throws RemoteException {
4123         if (DBG) {
4124             Log.d(TAG, "onExecuteWrite() connId=" + connId + ", address=" + address + ", transId="
4125                     + transId);
4126         }
4127 
4128         ServerMap.App app = mServerMap.getByConnId(connId);
4129         if (app == null) {
4130             return;
4131         }
4132 
4133         app.callback.onExecuteWrite(address, transId, execWrite == 1);
4134     }
4135 
onResponseSendCompleted(int status, int attrHandle)4136     void onResponseSendCompleted(int status, int attrHandle) {
4137         if (DBG) {
4138             Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle);
4139         }
4140     }
4141 
onNotificationSent(int connId, int status)4142     void onNotificationSent(int connId, int status) throws RemoteException {
4143         if (VDBG) {
4144             Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status);
4145         }
4146 
4147         String address = mServerMap.addressByConnId(connId);
4148         if (address == null) {
4149             return;
4150         }
4151 
4152         ServerMap.App app = mServerMap.getByConnId(connId);
4153         if (app == null) {
4154             return;
4155         }
4156 
4157         if (!app.isCongested) {
4158             app.callback.onNotificationSent(address, status);
4159         } else {
4160             if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
4161                 status = BluetoothGatt.GATT_SUCCESS;
4162             }
4163             app.queueCallback(new CallbackInfo.Builder(address, status).build());
4164         }
4165     }
4166 
onServerCongestion(int connId, boolean congested)4167     void onServerCongestion(int connId, boolean congested) throws RemoteException {
4168         if (DBG) {
4169             Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested);
4170         }
4171 
4172         ServerMap.App app = mServerMap.getByConnId(connId);
4173         if (app == null) {
4174             return;
4175         }
4176 
4177         app.isCongested = congested;
4178         while (!app.isCongested) {
4179             CallbackInfo callbackInfo = app.popQueuedCallback();
4180             if (callbackInfo == null) {
4181                 return;
4182             }
4183             app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status);
4184         }
4185     }
4186 
onMtuChanged(int connId, int mtu)4187     void onMtuChanged(int connId, int mtu) throws RemoteException {
4188         if (DBG) {
4189             Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu);
4190         }
4191 
4192         String address = mServerMap.addressByConnId(connId);
4193         if (address == null) {
4194             return;
4195         }
4196 
4197         ServerMap.App app = mServerMap.getByConnId(connId);
4198         if (app == null) {
4199             return;
4200         }
4201 
4202         app.callback.onMtuChanged(address, mtu);
4203     }
4204 
4205     /**************************************************************************
4206      * GATT Service functions - SERVER
4207      *************************************************************************/
4208 
4209     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
registerServer(UUID uuid, IBluetoothGattServerCallback callback, boolean eatt_support, AttributionSource attributionSource)4210     void registerServer(UUID uuid, IBluetoothGattServerCallback callback, boolean eatt_support,
4211             AttributionSource attributionSource) {
4212         if (!Utils.checkConnectPermissionForDataDelivery(
4213                 this, attributionSource, "GattService registerServer")) {
4214             return;
4215         }
4216 
4217         if (DBG) {
4218             Log.d(TAG, "registerServer() - UUID=" + uuid);
4219         }
4220         mServerMap.add(uuid, null, callback, null, this);
4221         gattServerRegisterAppNative(uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), eatt_support);
4222     }
4223 
4224     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
unregisterServer(int serverIf, AttributionSource attributionSource)4225     void unregisterServer(int serverIf, AttributionSource attributionSource) {
4226         if (!Utils.checkConnectPermissionForDataDelivery(
4227                 this, attributionSource, "GattService unregisterServer")) {
4228             return;
4229         }
4230 
4231         if (DBG) {
4232             Log.d(TAG, "unregisterServer() - serverIf=" + serverIf);
4233         }
4234 
4235         deleteServices(serverIf);
4236 
4237         mServerMap.remove(serverIf);
4238         gattServerUnregisterAppNative(serverIf);
4239     }
4240 
4241     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
serverConnect(int serverIf, String address, boolean isDirect, int transport, AttributionSource attributionSource)4242     void serverConnect(int serverIf, String address, boolean isDirect, int transport,
4243             AttributionSource attributionSource) {
4244         if (!Utils.checkConnectPermissionForDataDelivery(
4245                 this, attributionSource, "GattService serverConnect")) {
4246             return;
4247         }
4248 
4249         if (DBG) {
4250             Log.d(TAG, "serverConnect() - address=" + address);
4251         }
4252         gattServerConnectNative(serverIf, address, isDirect, transport);
4253     }
4254 
4255     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
serverDisconnect(int serverIf, String address, AttributionSource attributionSource)4256     void serverDisconnect(int serverIf, String address, AttributionSource attributionSource) {
4257         if (!Utils.checkConnectPermissionForDataDelivery(
4258                 this, attributionSource, "GattService serverDisconnect")) {
4259             return;
4260         }
4261 
4262         Integer connId = mServerMap.connIdByAddress(serverIf, address);
4263         if (DBG) {
4264             Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId);
4265         }
4266 
4267         gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0);
4268     }
4269 
4270     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions, AttributionSource attributionSource)4271     void serverSetPreferredPhy(int serverIf, String address, int txPhy, int rxPhy, int phyOptions,
4272             AttributionSource attributionSource) {
4273         if (!Utils.checkConnectPermissionForDataDelivery(
4274                 this, attributionSource, "GattService serverSetPreferredPhy")) {
4275             return;
4276         }
4277 
4278         Integer connId = mServerMap.connIdByAddress(serverIf, address);
4279         if (connId == null) {
4280             if (DBG) {
4281                 Log.d(TAG, "serverSetPreferredPhy() - no connection to " + address);
4282             }
4283             return;
4284         }
4285 
4286         if (DBG) {
4287             Log.d(TAG, "serverSetPreferredPhy() - address=" + address + ", connId=" + connId);
4288         }
4289         gattServerSetPreferredPhyNative(serverIf, address, txPhy, rxPhy, phyOptions);
4290     }
4291 
4292     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
serverReadPhy(int serverIf, String address, AttributionSource attributionSource)4293     void serverReadPhy(int serverIf, String address, AttributionSource attributionSource) {
4294         if (!Utils.checkConnectPermissionForDataDelivery(
4295                 this, attributionSource, "GattService serverReadPhy")) {
4296             return;
4297         }
4298 
4299         Integer connId = mServerMap.connIdByAddress(serverIf, address);
4300         if (connId == null) {
4301             if (DBG) {
4302                 Log.d(TAG, "serverReadPhy() - no connection to " + address);
4303             }
4304             return;
4305         }
4306 
4307         if (DBG) {
4308             Log.d(TAG, "serverReadPhy() - address=" + address + ", connId=" + connId);
4309         }
4310         gattServerReadPhyNative(serverIf, address);
4311     }
4312 
4313     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
addService( int serverIf, BluetoothGattService service, AttributionSource attributionSource)4314     void addService(
4315             int serverIf, BluetoothGattService service, AttributionSource attributionSource) {
4316         if (!Utils.checkConnectPermissionForDataDelivery(
4317                 this, attributionSource, "GattService addService")) {
4318             return;
4319         }
4320 
4321         if (DBG) {
4322             Log.d(TAG, "addService() - uuid=" + service.getUuid());
4323         }
4324 
4325         List<GattDbElement> db = new ArrayList<GattDbElement>();
4326 
4327         if (service.getType() == BluetoothGattService.SERVICE_TYPE_PRIMARY) {
4328             db.add(GattDbElement.createPrimaryService(service.getUuid()));
4329         } else {
4330             db.add(GattDbElement.createSecondaryService(service.getUuid()));
4331         }
4332 
4333         for (BluetoothGattService includedService : service.getIncludedServices()) {
4334             int inclSrvcHandle = includedService.getInstanceId();
4335 
4336             if (mHandleMap.checkServiceExists(includedService.getUuid(), inclSrvcHandle)) {
4337                 db.add(GattDbElement.createIncludedService(inclSrvcHandle));
4338             } else {
4339                 Log.e(TAG,
4340                         "included service with UUID " + includedService.getUuid() + " not found!");
4341             }
4342         }
4343 
4344         for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
4345             int permission =
4346                     ((characteristic.getKeySize() - 7) << 12) + characteristic.getPermissions();
4347             db.add(GattDbElement.createCharacteristic(characteristic.getUuid(),
4348                     characteristic.getProperties(), permission));
4349 
4350             for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors()) {
4351                 permission =
4352                         ((characteristic.getKeySize() - 7) << 12) + descriptor.getPermissions();
4353                 db.add(GattDbElement.createDescriptor(descriptor.getUuid(), permission));
4354             }
4355         }
4356 
4357         gattServerAddServiceNative(serverIf, db);
4358     }
4359 
4360     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
removeService(int serverIf, int handle, AttributionSource attributionSource)4361     void removeService(int serverIf, int handle, AttributionSource attributionSource) {
4362         if (!Utils.checkConnectPermissionForDataDelivery(
4363                 this, attributionSource, "GattService removeService")) {
4364             return;
4365         }
4366 
4367         if (DBG) {
4368             Log.d(TAG, "removeService() - handle=" + handle);
4369         }
4370 
4371         gattServerDeleteServiceNative(serverIf, handle);
4372     }
4373 
4374     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
clearServices(int serverIf, AttributionSource attributionSource)4375     void clearServices(int serverIf, AttributionSource attributionSource) {
4376         if (!Utils.checkConnectPermissionForDataDelivery(
4377                 this, attributionSource, "GattService clearServices")) {
4378             return;
4379         }
4380 
4381         if (DBG) {
4382             Log.d(TAG, "clearServices()");
4383         }
4384         deleteServices(serverIf);
4385     }
4386 
4387     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
sendResponse(int serverIf, String address, int requestId, int status, int offset, byte[] value, AttributionSource attributionSource)4388     void sendResponse(int serverIf, String address, int requestId, int status, int offset,
4389             byte[] value, AttributionSource attributionSource) {
4390         if (!Utils.checkConnectPermissionForDataDelivery(
4391                 this, attributionSource, "GattService sendResponse")) {
4392             return;
4393         }
4394 
4395         if (VDBG) {
4396             Log.d(TAG, "sendResponse() - address=" + address);
4397         }
4398 
4399         int handle = 0;
4400         HandleMap.Entry entry = mHandleMap.getByRequestId(requestId);
4401         if (entry != null) {
4402             handle = entry.handle;
4403         }
4404 
4405         Integer connId = mServerMap.connIdByAddress(serverIf, address);
4406         gattServerSendResponseNative(serverIf, connId != null ? connId : 0, requestId,
4407                 (byte) status, handle, offset, value, (byte) 0);
4408         mHandleMap.deleteRequest(requestId);
4409     }
4410 
4411     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value, AttributionSource attributionSource)4412     int sendNotification(int serverIf, String address, int handle, boolean confirm, byte[] value,
4413             AttributionSource attributionSource) {
4414         if (!Utils.checkConnectPermissionForDataDelivery(
4415                 this, attributionSource, "GattService sendNotification")) {
4416             return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
4417         }
4418 
4419         if (VDBG) {
4420             Log.d(TAG, "sendNotification() - address=" + address + " handle=" + handle);
4421         }
4422 
4423         Integer connId = mServerMap.connIdByAddress(serverIf, address);
4424         if (connId == null || connId == 0) {
4425             return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED;
4426         }
4427 
4428         if (confirm) {
4429             gattServerSendIndicationNative(serverIf, handle, connId, value);
4430         } else {
4431             gattServerSendNotificationNative(serverIf, handle, connId, value);
4432         }
4433 
4434         return BluetoothStatusCodes.SUCCESS;
4435     }
4436 
4437 
4438     /**************************************************************************
4439      * Private functions
4440      *************************************************************************/
4441 
isHidSrvcUuid(final UUID uuid)4442     private boolean isHidSrvcUuid(final UUID uuid) {
4443         return HID_SERVICE_UUID.equals(uuid);
4444     }
4445 
isHidCharUuid(final UUID uuid)4446     private boolean isHidCharUuid(final UUID uuid) {
4447         for (UUID hidUuid : HID_UUIDS) {
4448             if (hidUuid.equals(uuid)) {
4449                 return true;
4450             }
4451         }
4452         return false;
4453     }
4454 
isAndroidTvRemoteSrvcUuid(final UUID uuid)4455     private boolean isAndroidTvRemoteSrvcUuid(final UUID uuid) {
4456         return ANDROID_TV_REMOTE_SERVICE_UUID.equals(uuid);
4457     }
4458 
isFidoSrvcUuid(final UUID uuid)4459     private boolean isFidoSrvcUuid(final UUID uuid) {
4460         return FIDO_SERVICE_UUID.equals(uuid);
4461     }
4462 
isLeAudioSrvcUuid(final UUID uuid)4463     private boolean isLeAudioSrvcUuid(final UUID uuid) {
4464         for (UUID leAudioUuid : LE_AUDIO_SERVICE_UUIDS) {
4465             if (leAudioUuid.equals(uuid)) {
4466                 return true;
4467             }
4468         }
4469         return false;
4470     }
4471 
isRestrictedSrvcUuid(final UUID uuid)4472     private boolean isRestrictedSrvcUuid(final UUID uuid) {
4473         return isFidoSrvcUuid(uuid)
4474                 || isAndroidTvRemoteSrvcUuid(uuid)
4475                 || isLeAudioSrvcUuid(uuid);
4476     }
4477 
getDeviceType(BluetoothDevice device)4478     private int getDeviceType(BluetoothDevice device) {
4479         int type = gattClientGetDeviceTypeNative(device.getAddress());
4480         if (DBG) {
4481             Log.d(TAG, "getDeviceType() - device=" + device + ", type=" + type);
4482         }
4483         return type;
4484     }
4485 
needsPrivilegedPermissionForScan(ScanSettings settings)4486     private boolean needsPrivilegedPermissionForScan(ScanSettings settings) {
4487         // BLE scan only mode needs special permission.
4488         if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) {
4489             return true;
4490         }
4491 
4492         // Regular scan, no special permission.
4493         if (settings == null) {
4494             return false;
4495         }
4496 
4497         // Ambient discovery mode, needs privileged permission.
4498         if (settings.getScanMode() == ScanSettings.SCAN_MODE_AMBIENT_DISCOVERY) {
4499             return true;
4500         }
4501 
4502         // Regular scan, no special permission.
4503         if (settings.getReportDelayMillis() == 0) {
4504             return false;
4505         }
4506 
4507         // Batch scan, truncated mode needs permission.
4508         return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED;
4509     }
4510 
4511     /*
4512      * The {@link ScanFilter#setDeviceAddress} API overloads are @SystemApi access methods.  This
4513      * requires that the permissions be BLUETOOTH_PRIVILEGED.
4514      */
4515     @SuppressLint("AndroidFrameworkRequiresPermission")
enforcePrivilegedPermissionIfNeeded(List<ScanFilter> filters)4516     private void enforcePrivilegedPermissionIfNeeded(List<ScanFilter> filters) {
4517         if (DBG) {
4518             Log.d(TAG, "enforcePrivilegedPermissionIfNeeded(" + filters + ")");
4519         }
4520         // Some 3p API cases may have null filters, need to allow
4521         if (filters != null) {
4522             for (ScanFilter filter : filters) {
4523                 // The only case to enforce here is if there is an address
4524                 // If there is an address, enforce if the correct combination criteria is met.
4525                 if (filter.getDeviceAddress() != null) {
4526                     // At this point we have an address, that means a caller used the
4527                     // setDeviceAddress(address) public API for the ScanFilter
4528                     // We don't want to enforce if the type is PUBLIC and the IRK is null
4529                     // However, if we have a different type that means the caller used a new
4530                     // @SystemApi such as setDeviceAddress(address, type) or
4531                     // setDeviceAddress(address, type, irk) which are both @SystemApi and require
4532                     // permissions to be enforced
4533                     if (filter.getAddressType()
4534                             == BluetoothDevice.ADDRESS_TYPE_PUBLIC && filter.getIrk() == null) {
4535                         // Do not enforce
4536                     } else {
4537                         enforceBluetoothPrivilegedPermission(this);
4538                     }
4539                 }
4540             }
4541         }
4542     }
4543 
4544     @SuppressLint("AndroidFrameworkRequiresPermission")
enforcePrivilegedPermissionIfNeeded(ScanSettings settings)4545     private void enforcePrivilegedPermissionIfNeeded(ScanSettings settings) {
4546         if (needsPrivilegedPermissionForScan(settings)) {
4547             enforceBluetoothPrivilegedPermission(this);
4548         }
4549     }
4550 
4551     // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other
4552     // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does
4553     // not have UPDATE_DEVICE_STATS permission.
4554     @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
enforceImpersonatationPermission()4555     private void enforceImpersonatationPermission() {
4556         enforceCallingOrSelfPermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
4557                 "Need UPDATE_DEVICE_STATS permission");
4558     }
4559 
4560     @SuppressLint("AndroidFrameworkRequiresPermission")
enforceImpersonatationPermissionIfNeeded(WorkSource workSource)4561     private void enforceImpersonatationPermissionIfNeeded(WorkSource workSource) {
4562         if (workSource != null) {
4563             enforceImpersonatationPermission();
4564         }
4565     }
4566 
4567     /**
4568      * Ensures the report delay is either 0 or at least the floor value (5000ms)
4569      *
4570      * @param  settings are the scan settings passed into a request to start le scanning
4571      * @return the passed in ScanSettings object if the report delay is 0 or above the floor value;
4572      *         a new ScanSettings object with the report delay being the floor value if the original
4573      *         report delay was between 0 and the floor value (exclusive of both)
4574      */
4575     @VisibleForTesting
enforceReportDelayFloor(ScanSettings settings)4576     ScanSettings enforceReportDelayFloor(ScanSettings settings) {
4577         if (settings.getReportDelayMillis() == 0) {
4578             return settings;
4579         }
4580 
4581         // Need to clear identity to pass device config permission check
4582         final long callerToken = Binder.clearCallingIdentity();
4583         try {
4584             long floor = DeviceConfig.getLong(DeviceConfig.NAMESPACE_BLUETOOTH, "report_delay",
4585                 DEFAULT_REPORT_DELAY_FLOOR);
4586 
4587             if (settings.getReportDelayMillis() > floor) {
4588                 return settings;
4589             } else {
4590                 return new ScanSettings.Builder()
4591                         .setCallbackType(settings.getCallbackType())
4592                         .setLegacy(settings.getLegacy())
4593                         .setMatchMode(settings.getMatchMode())
4594                         .setNumOfMatches(settings.getNumOfMatches())
4595                         .setPhy(settings.getPhy())
4596                         .setReportDelay(floor)
4597                         .setScanMode(settings.getScanMode())
4598                         .setScanResultType(settings.getScanResultType())
4599                         .build();
4600             }
4601         } finally {
4602             Binder.restoreCallingIdentity(callerToken);
4603         }
4604     }
4605 
stopNextService(int serverIf, int status)4606     private void stopNextService(int serverIf, int status) throws RemoteException {
4607         if (DBG) {
4608             Log.d(TAG, "stopNextService() - serverIf=" + serverIf + ", status=" + status);
4609         }
4610 
4611         if (status == 0) {
4612             List<HandleMap.Entry> entries = mHandleMap.getEntries();
4613             for (HandleMap.Entry entry : entries) {
4614                 if (entry.type != HandleMap.TYPE_SERVICE || entry.serverIf != serverIf
4615                         || !entry.started) {
4616                     continue;
4617                 }
4618 
4619                 gattServerStopServiceNative(serverIf, entry.handle);
4620                 return;
4621             }
4622         }
4623     }
4624 
deleteServices(int serverIf)4625     private void deleteServices(int serverIf) {
4626         if (DBG) {
4627             Log.d(TAG, "deleteServices() - serverIf=" + serverIf);
4628         }
4629 
4630         /*
4631          * Figure out which handles to delete.
4632          * The handles are copied into a new list to avoid race conditions.
4633          */
4634         List<Integer> handleList = new ArrayList<Integer>();
4635         List<HandleMap.Entry> entries = mHandleMap.getEntries();
4636         for (HandleMap.Entry entry : entries) {
4637             if (entry.type != HandleMap.TYPE_SERVICE || entry.serverIf != serverIf) {
4638                 continue;
4639             }
4640             handleList.add(entry.handle);
4641         }
4642 
4643         /* Now actually delete the services.... */
4644         for (Integer handle : handleList) {
4645             gattServerDeleteServiceNative(serverIf, handle);
4646         }
4647     }
4648 
dumpRegisterId(StringBuilder sb)4649     void dumpRegisterId(StringBuilder sb) {
4650         sb.append("  Scanner:\n");
4651         for (Integer appId : mScannerMap.getAllAppsIds()) {
4652             println(sb, "    app_if: " + appId + ", appName: " + mScannerMap.getById(appId).name);
4653         }
4654         sb.append("  Client:\n");
4655         for (Integer appId : mClientMap.getAllAppsIds()) {
4656             println(sb, "    app_if: " + appId + ", appName: " + mClientMap.getById(appId).name);
4657         }
4658         sb.append("  Server:\n");
4659         for (Integer appId : mServerMap.getAllAppsIds()) {
4660             println(sb, "    app_if: " + appId + ", appName: " + mServerMap.getById(appId).name);
4661         }
4662         sb.append("\n\n");
4663     }
4664 
4665     @Override
dump(StringBuilder sb)4666     public void dump(StringBuilder sb) {
4667         super.dump(sb);
4668         println(sb, "mAdvertisingServiceUuids:");
4669         for (UUID uuid : mAdvertisingServiceUuids) {
4670             println(sb, "  " + uuid);
4671         }
4672 
4673         println(sb, "mMaxScanFilters: " + mMaxScanFilters);
4674 
4675         sb.append("\nRegistered App\n");
4676         dumpRegisterId(sb);
4677 
4678         sb.append("GATT Scanner Map\n");
4679         mScannerMap.dump(sb);
4680 
4681         sb.append("GATT Advertiser Map\n");
4682         mAdvertiserMap.dumpAdvertiser(sb);
4683 
4684         sb.append("GATT Client Map\n");
4685         mClientMap.dump(sb);
4686 
4687         sb.append("GATT Server Map\n");
4688         mServerMap.dump(sb);
4689 
4690         sb.append("GATT Handle Map\n");
4691         mHandleMap.dump(sb);
4692     }
4693 
addScanEvent(BluetoothMetricsProto.ScanEvent event)4694     void addScanEvent(BluetoothMetricsProto.ScanEvent event) {
4695         synchronized (mScanEvents) {
4696             if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) {
4697                 mScanEvents.remove();
4698             }
4699             mScanEvents.add(event);
4700         }
4701     }
4702 
statsLogAppPackage(String address, int applicationUid, int sessionIndex)4703     private void statsLogAppPackage(String address, int applicationUid, int sessionIndex) {
4704         BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
4705         BluetoothStatsLog.write(
4706                 BluetoothStatsLog.BLUETOOTH_GATT_APP_INFO,
4707                 sessionIndex, mAdapterService.getMetricId(device), applicationUid);
4708         if (DBG) {
4709             Log.d(TAG, "Gatt Logging: metric_id=" + mAdapterService.getMetricId(device)
4710                     + ", app_uid=" + applicationUid);
4711         }
4712     }
4713 
statsLogGattConnectionStateChange( int profile, String address, int sessionIndex, int connectionState, int connectionStatus)4714     private void statsLogGattConnectionStateChange(
4715             int profile, String address, int sessionIndex, int connectionState,
4716             int connectionStatus) {
4717         BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address);
4718         BluetoothStatsLog.write(
4719                 BluetoothStatsLog.BLUETOOTH_CONNECTION_STATE_CHANGED, connectionState,
4720                 0 /* deprecated */, profile, new byte[0],
4721                 mAdapterService.getMetricId(device), sessionIndex, connectionStatus);
4722         if (DBG) {
4723             Log.d(TAG, "Gatt Logging: metric_id=" + mAdapterService.getMetricId(device)
4724                     + ", session_index=" + sessionIndex
4725                     + ", connection state=" + connectionState
4726                     + ", connection status=" + connectionStatus);
4727         }
4728     }
4729 
4730     @Override
dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder)4731     public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) {
4732         synchronized (mScanEvents) {
4733             builder.addAllScanEvent(mScanEvents);
4734         }
4735     }
4736 
4737     /**************************************************************************
4738      * GATT Test functions
4739      *************************************************************************/
4740 
gattTestCommand(int command, UUID uuid1, String bda1, int p1, int p2, int p3, int p4, int p5)4741     void gattTestCommand(int command, UUID uuid1, String bda1, int p1, int p2, int p3, int p4,
4742             int p5) {
4743         if (bda1 == null) {
4744             bda1 = "00:00:00:00:00:00";
4745         }
4746         if (uuid1 != null) {
4747             gattTestNative(command, uuid1.getLeastSignificantBits(), uuid1.getMostSignificantBits(),
4748                     bda1, p1, p2, p3, p4, p5);
4749         } else {
4750             gattTestNative(command, 0, 0, bda1, p1, p2, p3, p4, p5);
4751         }
4752     }
4753 
gattTestNative(int command, long uuid1Lsb, long uuid1Msb, String bda1, int p1, int p2, int p3, int p4, int p5)4754     private native void gattTestNative(int command, long uuid1Lsb, long uuid1Msb, String bda1,
4755             int p1, int p2, int p3, int p4, int p5);
4756 
4757     /**************************************************************************
4758      * Native functions prototypes
4759      *************************************************************************/
4760 
classInitNative()4761     private static native void classInitNative();
4762 
initializeNative()4763     private native void initializeNative();
4764 
cleanupNative()4765     private native void cleanupNative();
4766 
gattClientGetDeviceTypeNative(String address)4767     private native int gattClientGetDeviceTypeNative(String address);
4768 
gattClientRegisterAppNative(long appUuidLsb, long appUuidMsb, boolean eatt_support)4769     private native void gattClientRegisterAppNative(long appUuidLsb, long appUuidMsb, boolean eatt_support);
4770 
gattClientUnregisterAppNative(int clientIf)4771     private native void gattClientUnregisterAppNative(int clientIf);
4772 
gattClientConnectNative(int clientIf, String address, boolean isDirect, int transport, boolean opportunistic, int initiatingPhys)4773     private native void gattClientConnectNative(int clientIf, String address, boolean isDirect,
4774             int transport, boolean opportunistic, int initiatingPhys);
4775 
gattClientDisconnectNative(int clientIf, String address, int connId)4776     private native void gattClientDisconnectNative(int clientIf, String address, int connId);
4777 
gattClientSetPreferredPhyNative(int clientIf, String address, int txPhy, int rxPhy, int phyOptions)4778     private native void gattClientSetPreferredPhyNative(int clientIf, String address, int txPhy,
4779             int rxPhy, int phyOptions);
4780 
gattClientReadPhyNative(int clientIf, String address)4781     private native void gattClientReadPhyNative(int clientIf, String address);
4782 
gattClientRefreshNative(int clientIf, String address)4783     private native void gattClientRefreshNative(int clientIf, String address);
4784 
gattClientSearchServiceNative(int connId, boolean searchAll, long serviceUuidLsb, long serviceUuidMsb)4785     private native void gattClientSearchServiceNative(int connId, boolean searchAll,
4786             long serviceUuidLsb, long serviceUuidMsb);
4787 
gattClientDiscoverServiceByUuidNative(int connId, long serviceUuidLsb, long serviceUuidMsb)4788     private native void gattClientDiscoverServiceByUuidNative(int connId, long serviceUuidLsb,
4789             long serviceUuidMsb);
4790 
gattClientGetGattDbNative(int connId)4791     private native void gattClientGetGattDbNative(int connId);
4792 
gattClientReadCharacteristicNative(int connId, int handle, int authReq)4793     private native void gattClientReadCharacteristicNative(int connId, int handle, int authReq);
4794 
gattClientReadUsingCharacteristicUuidNative(int connId, long uuidMsb, long uuidLsb, int sHandle, int eHandle, int authReq)4795     private native void gattClientReadUsingCharacteristicUuidNative(int connId, long uuidMsb,
4796             long uuidLsb, int sHandle, int eHandle, int authReq);
4797 
gattClientReadDescriptorNative(int connId, int handle, int authReq)4798     private native void gattClientReadDescriptorNative(int connId, int handle, int authReq);
4799 
gattClientWriteCharacteristicNative(int connId, int handle, int writeType, int authReq, byte[] value)4800     private native void gattClientWriteCharacteristicNative(int connId, int handle, int writeType,
4801             int authReq, byte[] value);
4802 
gattClientWriteDescriptorNative(int connId, int handle, int authReq, byte[] value)4803     private native void gattClientWriteDescriptorNative(int connId, int handle, int authReq,
4804             byte[] value);
4805 
gattClientExecuteWriteNative(int connId, boolean execute)4806     private native void gattClientExecuteWriteNative(int connId, boolean execute);
4807 
gattClientRegisterForNotificationsNative(int clientIf, String address, int handle, boolean enable)4808     private native void gattClientRegisterForNotificationsNative(int clientIf, String address,
4809             int handle, boolean enable);
4810 
gattClientReadRemoteRssiNative(int clientIf, String address)4811     private native void gattClientReadRemoteRssiNative(int clientIf, String address);
4812 
gattClientConfigureMTUNative(int connId, int mtu)4813     private native void gattClientConfigureMTUNative(int connId, int mtu);
4814 
gattConnectionParameterUpdateNative(int clientIf, String address, int minInterval, int maxInterval, int latency, int timeout, int minConnectionEventLen, int maxConnectionEventLen)4815     private native void gattConnectionParameterUpdateNative(int clientIf, String address,
4816             int minInterval, int maxInterval, int latency, int timeout, int minConnectionEventLen,
4817             int maxConnectionEventLen);
4818 
gattServerRegisterAppNative(long appUuidLsb, long appUuidMsb, boolean eatt_support)4819     private native void gattServerRegisterAppNative(long appUuidLsb, long appUuidMsb, boolean eatt_support);
4820 
gattServerUnregisterAppNative(int serverIf)4821     private native void gattServerUnregisterAppNative(int serverIf);
4822 
gattServerConnectNative(int serverIf, String address, boolean isDirect, int transport)4823     private native void gattServerConnectNative(int serverIf, String address, boolean isDirect,
4824             int transport);
4825 
gattServerDisconnectNative(int serverIf, String address, int connId)4826     private native void gattServerDisconnectNative(int serverIf, String address, int connId);
4827 
gattServerSetPreferredPhyNative(int clientIf, String address, int txPhy, int rxPhy, int phyOptions)4828     private native void gattServerSetPreferredPhyNative(int clientIf, String address, int txPhy,
4829             int rxPhy, int phyOptions);
4830 
gattServerReadPhyNative(int clientIf, String address)4831     private native void gattServerReadPhyNative(int clientIf, String address);
4832 
gattServerAddServiceNative(int serverIf, List<GattDbElement> service)4833     private native void gattServerAddServiceNative(int serverIf, List<GattDbElement> service);
4834 
gattServerStopServiceNative(int serverIf, int svcHandle)4835     private native void gattServerStopServiceNative(int serverIf, int svcHandle);
4836 
gattServerDeleteServiceNative(int serverIf, int svcHandle)4837     private native void gattServerDeleteServiceNative(int serverIf, int svcHandle);
4838 
gattServerSendIndicationNative(int serverIf, int attrHandle, int connId, byte[] val)4839     private native void gattServerSendIndicationNative(int serverIf, int attrHandle, int connId,
4840             byte[] val);
4841 
gattServerSendNotificationNative(int serverIf, int attrHandle, int connId, byte[] val)4842     private native void gattServerSendNotificationNative(int serverIf, int attrHandle, int connId,
4843             byte[] val);
4844 
gattServerSendResponseNative(int serverIf, int connId, int transId, int status, int handle, int offset, byte[] val, int authReq)4845     private native void gattServerSendResponseNative(int serverIf, int connId, int transId,
4846             int status, int handle, int offset, byte[] val, int authReq);
4847 }
4848