• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 android.app.AppOpsManager;
20 import android.app.Service;
21 import android.bluetooth.BluetoothAdapter;
22 import android.bluetooth.BluetoothDevice;
23 import android.bluetooth.BluetoothGatt;
24 import android.bluetooth.BluetoothProfile;
25 import android.bluetooth.IBluetoothGatt;
26 import android.bluetooth.IBluetoothGattCallback;
27 import android.bluetooth.IBluetoothGattServerCallback;
28 import android.bluetooth.le.AdvertiseCallback;
29 import android.bluetooth.le.AdvertiseData;
30 import android.bluetooth.le.AdvertiseSettings;
31 import android.bluetooth.le.ResultStorageDescriptor;
32 import android.bluetooth.le.ScanFilter;
33 import android.bluetooth.le.ScanRecord;
34 import android.bluetooth.le.ScanResult;
35 import android.bluetooth.le.ScanSettings;
36 import android.content.Intent;
37 import android.os.Binder;
38 import android.os.IBinder;
39 import android.os.ParcelUuid;
40 import android.os.RemoteException;
41 import android.os.SystemClock;
42 import android.os.UserHandle;
43 import android.provider.Settings;
44 import android.util.Log;
45 
46 import com.android.bluetooth.R;
47 import com.android.bluetooth.Utils;
48 import com.android.bluetooth.btservice.AdapterService;
49 import com.android.bluetooth.btservice.ProfileService;
50 import com.android.bluetooth.util.NumberUtils;
51 import com.android.internal.annotations.VisibleForTesting;
52 
53 import java.util.ArrayList;
54 import java.util.Arrays;
55 import java.util.Collections;
56 import java.util.HashMap;
57 import java.util.HashSet;
58 import java.util.List;
59 import java.util.Map;
60 import java.util.Set;
61 import java.util.UUID;
62 import java.util.concurrent.TimeUnit;
63 
64 /**
65  * Provides Bluetooth Gatt profile, as a service in
66  * the Bluetooth application.
67  * @hide
68  */
69 public class GattService extends ProfileService {
70     private static final boolean DBG = GattServiceConfig.DBG;
71     private static final boolean VDBG = GattServiceConfig.VDBG;
72     private static final String TAG = GattServiceConfig.TAG_PREFIX + "GattService";
73 
74     static final int SCAN_FILTER_ENABLED = 1;
75     static final int SCAN_FILTER_MODIFIED = 2;
76 
77     private static final int MAC_ADDRESS_LENGTH = 6;
78     // Batch scan related constants.
79     private static final int TRUNCATED_RESULT_SIZE = 11;
80     private static final int TIME_STAMP_LENGTH = 2;
81 
82     // onFoundLost related constants
83     private static final int ADVT_STATE_ONFOUND = 0;
84     private static final int ADVT_STATE_ONLOST = 1;
85 
86     private static final UUID[] HID_UUIDS = {
87         UUID.fromString("00002A4A-0000-1000-8000-00805F9B34FB"),
88         UUID.fromString("00002A4B-0000-1000-8000-00805F9B34FB"),
89         UUID.fromString("00002A4C-0000-1000-8000-00805F9B34FB"),
90         UUID.fromString("00002A4D-0000-1000-8000-00805F9B34FB")
91     };
92 
93     /**
94      * Search queue to serialize remote onbject inspection.
95      */
96     SearchQueue mSearchQueue = new SearchQueue();
97 
98     /**
99      * List of our registered clients.
100      */
101 
102     class ClientMap extends ContextMap<IBluetoothGattCallback> {}
103     ClientMap mClientMap = new ClientMap();
104 
105     /**
106      * List of our registered server apps.
107      */
108     class ServerMap extends ContextMap<IBluetoothGattServerCallback> {}
109     ServerMap mServerMap = new ServerMap();
110 
111     /**
112      * Server handle map.
113      */
114     HandleMap mHandleMap = new HandleMap();
115     private List<UUID> mAdvertisingServiceUuids = new ArrayList<UUID>();
116 
117     private int mMaxScanFilters;
118 
119     /**
120      * Pending service declaration queue
121      */
122     private List<ServiceDeclaration> mServiceDeclarations = new ArrayList<ServiceDeclaration>();
123 
addDeclaration()124     private ServiceDeclaration addDeclaration() {
125         synchronized (mServiceDeclarations) {
126             mServiceDeclarations.add(new ServiceDeclaration());
127         }
128         return getActiveDeclaration();
129     }
130 
getActiveDeclaration()131     private ServiceDeclaration getActiveDeclaration() {
132         synchronized (mServiceDeclarations) {
133             if (mServiceDeclarations.size() > 0)
134                 return mServiceDeclarations.get(mServiceDeclarations.size() - 1);
135         }
136         return null;
137     }
138 
getPendingDeclaration()139     private ServiceDeclaration getPendingDeclaration() {
140         synchronized (mServiceDeclarations) {
141             if (mServiceDeclarations.size() > 0)
142                 return mServiceDeclarations.get(0);
143         }
144         return null;
145     }
146 
removePendingDeclaration()147     private void removePendingDeclaration() {
148         synchronized (mServiceDeclarations) {
149             if (mServiceDeclarations.size() > 0)
150                 mServiceDeclarations.remove(0);
151         }
152     }
153 
154     private AdvertiseManager mAdvertiseManager;
155     private ScanManager mScanManager;
156     private AppOpsManager mAppOps;
157 
158     /**
159      * Reliable write queue
160      */
161     private Set<String> mReliableQueue = new HashSet<String>();
162 
163     static {
classInitNative()164         classInitNative();
165     }
166 
getName()167     protected String getName() {
168         return TAG;
169     }
170 
initBinder()171     protected IProfileServiceBinder initBinder() {
172         return new BluetoothGattBinder(this);
173     }
174 
start()175     protected boolean start() {
176         if (DBG) Log.d(TAG, "start()");
177         initializeNative();
178         mAppOps = getSystemService(AppOpsManager.class);
179         mAdvertiseManager = new AdvertiseManager(this, AdapterService.getAdapterService());
180         mAdvertiseManager.start();
181 
182         mScanManager = new ScanManager(this);
183         mScanManager.start();
184 
185         return true;
186     }
187 
stop()188     protected boolean stop() {
189         if (DBG) Log.d(TAG, "stop()");
190         mClientMap.clear();
191         mServerMap.clear();
192         mSearchQueue.clear();
193         mHandleMap.clear();
194         mServiceDeclarations.clear();
195         mReliableQueue.clear();
196         if (mAdvertiseManager != null) mAdvertiseManager.cleanup();
197         if (mScanManager != null) mScanManager.cleanup();
198         return true;
199     }
200 
cleanup()201     protected boolean cleanup() {
202         if (DBG) Log.d(TAG, "cleanup()");
203         cleanupNative();
204         if (mAdvertiseManager != null) mAdvertiseManager.cleanup();
205         if (mScanManager != null) mScanManager.cleanup();
206         return true;
207     }
208 
209     @Override
onStartCommand(Intent intent, int flags, int startId)210     public int onStartCommand(Intent intent, int flags, int startId) {
211         if (GattDebugUtils.handleDebugAction(this, intent)) {
212             return Service.START_NOT_STICKY;
213         }
214         return super.onStartCommand(intent, flags, startId);
215     }
216 
217     /**
218      * DeathReceipient handlers used to unregister applications that
219      * disconnect ungracefully (ie. crash or forced close).
220      */
221 
222     class ClientDeathRecipient implements IBinder.DeathRecipient {
223         int mAppIf;
224 
ClientDeathRecipient(int appIf)225         public ClientDeathRecipient(int appIf) {
226             mAppIf = appIf;
227         }
228 
229         @Override
binderDied()230         public void binderDied() {
231             if (DBG) Log.d(TAG, "Binder is dead - unregistering client (" + mAppIf + ")!");
232 
233             if (isScanClient(mAppIf)) {
234                 ScanClient client = new ScanClient(mAppIf, false);
235                 client.appDied = true;
236                 stopScan(client);
237             } else {
238                 AdvertiseClient client = new AdvertiseClient(mAppIf);
239                 client.appDied = true;
240                 stopMultiAdvertising(client);
241             }
242         }
243 
isScanClient(int clientIf)244         private boolean isScanClient(int clientIf) {
245             for (ScanClient client : mScanManager.getRegularScanQueue()) {
246                 if (client.clientIf == clientIf) {
247                     return true;
248                 }
249             }
250             for (ScanClient client : mScanManager.getBatchScanQueue()) {
251                 if (client.clientIf == clientIf) {
252                     return true;
253                 }
254             }
255             return false;
256         }
257     }
258 
259     class ServerDeathRecipient implements IBinder.DeathRecipient {
260         int mAppIf;
261 
ServerDeathRecipient(int appIf)262         public ServerDeathRecipient(int appIf) {
263             mAppIf = appIf;
264         }
265 
binderDied()266         public void binderDied() {
267             if (DBG) Log.d(TAG, "Binder is dead - unregistering server (" + mAppIf + ")!");
268             unregisterServer(mAppIf);
269         }
270     }
271 
272     /**
273      * Handlers for incoming service calls
274      */
275     private static class BluetoothGattBinder extends IBluetoothGatt.Stub implements IProfileServiceBinder {
276         private GattService mService;
277 
BluetoothGattBinder(GattService svc)278         public BluetoothGattBinder(GattService svc) {
279             mService = svc;
280         }
281 
cleanup()282         public boolean cleanup()  {
283             mService = null;
284             return true;
285         }
286 
getService()287         private GattService getService() {
288             if (mService  != null && mService.isAvailable()) return mService;
289             Log.e(TAG, "getService() - Service requested, but not available!");
290             return null;
291         }
292 
getDevicesMatchingConnectionStates(int[] states)293         public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
294             GattService service = getService();
295             if (service == null) return new ArrayList<BluetoothDevice>();
296             return service.getDevicesMatchingConnectionStates(states);
297         }
298 
registerClient(ParcelUuid uuid, IBluetoothGattCallback callback)299         public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) {
300             GattService service = getService();
301             if (service == null) return;
302             service.registerClient(uuid.getUuid(), callback);
303         }
304 
unregisterClient(int clientIf)305         public void unregisterClient(int clientIf) {
306             GattService service = getService();
307             if (service == null) return;
308             service.unregisterClient(clientIf);
309         }
310 
311         @Override
startScan(int appIf, boolean isServer, ScanSettings settings, List<ScanFilter> filters, List storages, String callingPackage)312         public void startScan(int appIf, boolean isServer, ScanSettings settings,
313                 List<ScanFilter> filters, List storages, String callingPackage) {
314             GattService service = getService();
315             if (service == null) return;
316             service.startScan(appIf, isServer, settings, filters, storages, callingPackage);
317         }
318 
stopScan(int appIf, boolean isServer)319         public void stopScan(int appIf, boolean isServer) {
320             GattService service = getService();
321             if (service == null) return;
322             service.stopScan(new ScanClient(appIf, isServer));
323         }
324 
325         @Override
flushPendingBatchResults(int appIf, boolean isServer)326         public void flushPendingBatchResults(int appIf, boolean isServer) {
327             GattService service = getService();
328             if (service == null) return;
329             service.flushPendingBatchResults(appIf, isServer);
330         }
331 
clientConnect(int clientIf, String address, boolean isDirect, int transport)332         public void clientConnect(int clientIf, String address, boolean isDirect, int transport) {
333             GattService service = getService();
334             if (service == null) return;
335             service.clientConnect(clientIf, address, isDirect, transport);
336         }
337 
clientDisconnect(int clientIf, String address)338         public void clientDisconnect(int clientIf, String address) {
339             GattService service = getService();
340             if (service == null) return;
341             service.clientDisconnect(clientIf, address);
342         }
343 
refreshDevice(int clientIf, String address)344         public void refreshDevice(int clientIf, String address) {
345             GattService service = getService();
346             if (service == null) return;
347             service.refreshDevice(clientIf, address);
348         }
349 
discoverServices(int clientIf, String address)350         public void discoverServices(int clientIf, String address) {
351             GattService service = getService();
352             if (service == null) return;
353             service.discoverServices(clientIf, address);
354         }
355 
readCharacteristic(int clientIf, String address, int srvcType, int srvcInstanceId, ParcelUuid srvcId, int charInstanceId, ParcelUuid charId, int authReq)356         public void readCharacteristic(int clientIf, String address, int srvcType,
357                                        int srvcInstanceId, ParcelUuid srvcId,
358                                        int charInstanceId, ParcelUuid charId,
359                                        int authReq) {
360             GattService service = getService();
361             if (service == null) return;
362             service.readCharacteristic(clientIf, address, srvcType, srvcInstanceId,
363                                        srvcId.getUuid(), charInstanceId,
364                                        charId.getUuid(), authReq);
365         }
366 
writeCharacteristic(int clientIf, String address, int srvcType, int srvcInstanceId, ParcelUuid srvcId, int charInstanceId, ParcelUuid charId, int writeType, int authReq, byte[] value)367         public void writeCharacteristic(int clientIf, String address, int srvcType,
368                              int srvcInstanceId, ParcelUuid srvcId,
369                              int charInstanceId, ParcelUuid charId,
370                              int writeType, int authReq, byte[] value) {
371             GattService service = getService();
372             if (service == null) return;
373             service.writeCharacteristic(clientIf, address, srvcType, srvcInstanceId,
374                                        srvcId.getUuid(), charInstanceId,
375                                        charId.getUuid(), writeType, authReq,
376                                        value);
377         }
378 
readDescriptor(int clientIf, String address, int srvcType, int srvcInstanceId, ParcelUuid srvcId, int charInstanceId, ParcelUuid charId, int descrInstanceId, ParcelUuid descrId, int authReq)379         public void readDescriptor(int clientIf, String address, int srvcType,
380                             int srvcInstanceId, ParcelUuid srvcId,
381                             int charInstanceId, ParcelUuid charId,
382                             int descrInstanceId, ParcelUuid descrId,
383                             int authReq) {
384             GattService service = getService();
385             if (service == null) return;
386             service.readDescriptor(clientIf, address, srvcType,
387                                    srvcInstanceId, srvcId.getUuid(),
388                                    charInstanceId, charId.getUuid(),
389                                    descrInstanceId, descrId.getUuid(),
390                                    authReq);
391         }
392 
writeDescriptor(int clientIf, String address, int srvcType, int srvcInstanceId, ParcelUuid srvcId, int charInstanceId, ParcelUuid charId, int descrInstanceId, ParcelUuid descrId, int writeType, int authReq, byte[] value)393         public void writeDescriptor(int clientIf, String address, int srvcType,
394                             int srvcInstanceId, ParcelUuid srvcId,
395                             int charInstanceId, ParcelUuid charId,
396                             int descrInstanceId, ParcelUuid descrId,
397                             int writeType, int authReq, byte[] value) {
398             GattService service = getService();
399             if (service == null) return;
400             service.writeDescriptor(clientIf, address, srvcType,
401                                     srvcInstanceId, srvcId.getUuid(),
402                                     charInstanceId, charId.getUuid(),
403                                     descrInstanceId, descrId.getUuid(),
404                                     writeType, authReq, value);
405         }
406 
beginReliableWrite(int clientIf, String address)407         public void beginReliableWrite(int clientIf, String address) {
408             GattService service = getService();
409             if (service == null) return;
410             service.beginReliableWrite(clientIf, address);
411         }
412 
endReliableWrite(int clientIf, String address, boolean execute)413         public void endReliableWrite(int clientIf, String address, boolean execute) {
414             GattService service = getService();
415             if (service == null) return;
416             service.endReliableWrite(clientIf, address, execute);
417         }
418 
registerForNotification(int clientIf, String address, int srvcType, int srvcInstanceId, ParcelUuid srvcId, int charInstanceId, ParcelUuid charId, boolean enable)419         public void registerForNotification(int clientIf, String address, int srvcType,
420                             int srvcInstanceId, ParcelUuid srvcId,
421                             int charInstanceId, ParcelUuid charId,
422                             boolean enable) {
423             GattService service = getService();
424             if (service == null) return;
425             service.registerForNotification(clientIf, address, srvcType, srvcInstanceId,
426                                        srvcId.getUuid(), charInstanceId,
427                                        charId.getUuid(), enable);
428         }
429 
readRemoteRssi(int clientIf, String address)430         public void readRemoteRssi(int clientIf, String address) {
431             GattService service = getService();
432             if (service == null) return;
433             service.readRemoteRssi(clientIf, address);
434         }
435 
configureMTU(int clientIf, String address, int mtu)436         public void configureMTU(int clientIf, String address, int mtu) {
437             GattService service = getService();
438             if (service == null) return;
439             service.configureMTU(clientIf, address, mtu);
440         }
441 
connectionParameterUpdate(int clientIf, String address, int connectionPriority)442         public void connectionParameterUpdate(int clientIf, String address,
443                                               int connectionPriority) {
444             GattService service = getService();
445             if (service == null) return;
446             service.connectionParameterUpdate(clientIf, address, connectionPriority);
447         }
448 
registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback)449         public void registerServer(ParcelUuid uuid, IBluetoothGattServerCallback callback) {
450             GattService service = getService();
451             if (service == null) return;
452             service.registerServer(uuid.getUuid(), callback);
453         }
454 
unregisterServer(int serverIf)455         public void unregisterServer(int serverIf) {
456             GattService service = getService();
457             if (service == null) return;
458             service.unregisterServer(serverIf);
459         }
460 
serverConnect(int serverIf, String address, boolean isDirect, int transport)461         public void serverConnect(int serverIf, String address, boolean isDirect, int transport) {
462             GattService service = getService();
463             if (service == null) return;
464             service.serverConnect(serverIf, address, isDirect, transport);
465         }
466 
serverDisconnect(int serverIf, String address)467         public void serverDisconnect(int serverIf, String address) {
468             GattService service = getService();
469             if (service == null) return;
470             service.serverDisconnect(serverIf, address);
471         }
472 
beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, int minHandles, ParcelUuid srvcId, boolean advertisePreferred)473         public void beginServiceDeclaration(int serverIf, int srvcType,
474                                             int srvcInstanceId, int minHandles,
475                                             ParcelUuid srvcId, boolean advertisePreferred) {
476             GattService service = getService();
477             if (service == null) return;
478             service.beginServiceDeclaration(serverIf, srvcType, srvcInstanceId,
479                                minHandles, srvcId.getUuid(), advertisePreferred);
480         }
481 
addIncludedService(int serverIf, int srvcType, int srvcInstanceId, ParcelUuid srvcId)482         public void addIncludedService(int serverIf, int srvcType,
483                             int srvcInstanceId, ParcelUuid srvcId) {
484             GattService service = getService();
485             if (service == null) return;
486             service.addIncludedService(serverIf, srvcType, srvcInstanceId,
487                                             srvcId.getUuid());
488         }
489 
addCharacteristic(int serverIf, ParcelUuid charId, int properties, int permissions)490         public void addCharacteristic(int serverIf, ParcelUuid charId,
491                             int properties, int permissions) {
492             GattService service = getService();
493             if (service == null) return;
494             service.addCharacteristic(serverIf, charId.getUuid(), properties,
495                                       permissions);
496         }
497 
addDescriptor(int serverIf, ParcelUuid descId, int permissions)498         public void addDescriptor(int serverIf, ParcelUuid descId,
499                            int permissions) {
500             GattService service = getService();
501             if (service == null) return;
502             service.addDescriptor(serverIf, descId.getUuid(), permissions);
503         }
504 
endServiceDeclaration(int serverIf)505         public void endServiceDeclaration(int serverIf) {
506             GattService service = getService();
507             if (service == null) return;
508             service.endServiceDeclaration(serverIf);
509         }
510 
removeService(int serverIf, int srvcType, int srvcInstanceId, ParcelUuid srvcId)511         public void removeService(int serverIf, int srvcType,
512                            int srvcInstanceId, ParcelUuid srvcId) {
513             GattService service = getService();
514             if (service == null) return;
515             service.removeService(serverIf, srvcType, srvcInstanceId,
516                                   srvcId.getUuid());
517         }
518 
clearServices(int serverIf)519         public void clearServices(int serverIf) {
520             GattService service = getService();
521             if (service == null) return;
522             service.clearServices(serverIf);
523         }
524 
sendResponse(int serverIf, String address, int requestId, int status, int offset, byte[] value)525         public void sendResponse(int serverIf, String address, int requestId,
526                                  int status, int offset, byte[] value) {
527             GattService service = getService();
528             if (service == null) return;
529             service.sendResponse(serverIf, address, requestId, status, offset, value);
530         }
531 
sendNotification(int serverIf, String address, int srvcType, int srvcInstanceId, ParcelUuid srvcId, int charInstanceId, ParcelUuid charId, boolean confirm, byte[] value)532         public void sendNotification(int serverIf, String address, int srvcType,
533                                               int srvcInstanceId, ParcelUuid srvcId,
534                                               int charInstanceId, ParcelUuid charId,
535                                               boolean confirm, byte[] value) {
536             GattService service = getService();
537             if (service == null) return;
538             service.sendNotification(serverIf, address, srvcType, srvcInstanceId,
539                 srvcId.getUuid(), charInstanceId, charId.getUuid(), confirm, value);
540         }
541 
542         @Override
startMultiAdvertising(int clientIf, AdvertiseData advertiseData, AdvertiseData scanResponse, AdvertiseSettings settings)543         public void startMultiAdvertising(int clientIf, AdvertiseData advertiseData,
544                 AdvertiseData scanResponse, AdvertiseSettings settings) {
545             GattService service = getService();
546             if (service == null) return;
547             service.startMultiAdvertising(clientIf, advertiseData, scanResponse, settings);
548         }
549 
550         @Override
stopMultiAdvertising(int clientIf)551         public void stopMultiAdvertising(int clientIf) {
552             GattService service = getService();
553             if (service == null) return;
554             service.stopMultiAdvertising(new AdvertiseClient(clientIf));
555         }
556 
557         @Override
disconnectAll()558         public void disconnectAll() {
559             GattService service = getService();
560             if (service == null) return;
561             service.disconnectAll();
562         }
563 
564         @Override
unregAll()565         public void unregAll() {
566             GattService service = getService();
567             if (service == null) return;
568             service.unregAll();
569         }
570 
571         @Override
numHwTrackFiltersAvailable()572         public int numHwTrackFiltersAvailable() {
573             GattService service = getService();
574             if (service == null) return 0;
575             return service.numHwTrackFiltersAvailable();
576         }
577     };
578 
579     /**************************************************************************
580      * Callback functions - CLIENT
581      *************************************************************************/
582 
onScanResult(String address, int rssi, byte[] adv_data)583     void onScanResult(String address, int rssi, byte[] adv_data) {
584         if (VDBG) Log.d(TAG, "onScanResult() - address=" + address
585                     + ", rssi=" + rssi);
586         List<UUID> remoteUuids = parseUuids(adv_data);
587         for (ScanClient client : mScanManager.getRegularScanQueue()) {
588             if (client.uuids.length > 0) {
589                 int matches = 0;
590                 for (UUID search : client.uuids) {
591                     for (UUID remote: remoteUuids) {
592                         if (remote.equals(search)) {
593                             ++matches;
594                             break; // Only count 1st match in case of duplicates
595                         }
596                     }
597                 }
598 
599                 if (matches < client.uuids.length) continue;
600             }
601 
602             if (!client.isServer) {
603                 ClientMap.App app = mClientMap.getById(client.clientIf);
604                 if (app != null) {
605                     BluetoothDevice device = BluetoothAdapter.getDefaultAdapter()
606                             .getRemoteDevice(address);
607                     ScanResult result = new ScanResult(device, ScanRecord.parseFromBytes(adv_data),
608                             rssi, SystemClock.elapsedRealtimeNanos());
609                     // Do no report if location mode is OFF or the client has no location permission
610                     // PEERS_MAC_ADDRESS permission holders always get results
611                     if (hasScanResultPermission(client) && matchesFilters(client, result)) {
612                         try {
613                             ScanSettings settings = client.settings;
614                             if ((settings.getCallbackType() &
615                                     ScanSettings.CALLBACK_TYPE_ALL_MATCHES) != 0) {
616                                 app.callback.onScanResult(result);
617                             }
618                         } catch (RemoteException e) {
619                             Log.e(TAG, "Exception: " + e);
620                             mClientMap.remove(client.clientIf);
621                             mScanManager.stopScan(client);
622                         }
623                     }
624                 }
625             } else {
626                 ServerMap.App app = mServerMap.getById(client.clientIf);
627                 if (app != null) {
628                     try {
629                         app.callback.onScanResult(address, rssi, adv_data);
630                     } catch (RemoteException e) {
631                         Log.e(TAG, "Exception: " + e);
632                         mServerMap.remove(client.clientIf);
633                         mScanManager.stopScan(client);
634                     }
635                 }
636             }
637         }
638     }
639 
640     /** Determines if the given scan client has the appropriate permissions to receive callbacks. */
hasScanResultPermission(final ScanClient client)641     private boolean hasScanResultPermission(final ScanClient client) {
642         final boolean requiresLocationEnabled =
643                 getResources().getBoolean(R.bool.strict_location_check);
644         final boolean locationEnabledSetting = Settings.Secure.getInt(getContentResolver(),
645                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF)
646                 != Settings.Secure.LOCATION_MODE_OFF;
647         final boolean locationEnabled = !requiresLocationEnabled || locationEnabledSetting
648                 || client.legacyForegroundApp;
649         return (client.hasPeersMacAddressPermission
650                 || (client.hasLocationPermission && locationEnabled));
651     }
652 
653     // Check if a scan record matches a specific filters.
matchesFilters(ScanClient client, ScanResult scanResult)654     private boolean matchesFilters(ScanClient client, ScanResult scanResult) {
655         if (client.filters == null || client.filters.isEmpty()) {
656             return true;
657         }
658         for (ScanFilter filter : client.filters) {
659             if (filter.matches(scanResult)) {
660                 return true;
661             }
662         }
663         return false;
664     }
665 
onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb)666     void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb)
667             throws RemoteException {
668         UUID uuid = new UUID(uuidMsb, uuidLsb);
669         if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf);
670         ClientMap.App app = mClientMap.getByUuid(uuid);
671         if (app != null) {
672             if (status == 0) {
673                 app.id = clientIf;
674                 app.linkToDeath(new ClientDeathRecipient(clientIf));
675             } else {
676                 mClientMap.remove(uuid);
677             }
678             app.callback.onClientRegistered(status, clientIf);
679         }
680     }
681 
onConnected(int clientIf, int connId, int status, String address)682     void onConnected(int clientIf, int connId, int status, String address)
683             throws RemoteException  {
684         if (DBG) Log.d(TAG, "onConnected() - clientIf=" + clientIf
685             + ", connId=" + connId + ", address=" + address);
686 
687         if (status == 0) mClientMap.addConnection(clientIf, connId, address);
688         ClientMap.App app = mClientMap.getById(clientIf);
689         if (app != null) {
690             app.callback.onClientConnectionState(status, clientIf,
691                                 (status==BluetoothGatt.GATT_SUCCESS), address);
692         }
693     }
694 
onDisconnected(int clientIf, int connId, int status, String address)695     void onDisconnected(int clientIf, int connId, int status, String address)
696             throws RemoteException {
697         if (DBG) Log.d(TAG, "onDisconnected() - clientIf=" + clientIf
698             + ", connId=" + connId + ", address=" + address);
699 
700         mClientMap.removeConnection(clientIf, connId);
701         mSearchQueue.removeConnId(connId);
702         ClientMap.App app = mClientMap.getById(clientIf);
703         if (app != null) {
704             app.callback.onClientConnectionState(status, clientIf, false, address);
705         }
706     }
707 
onSearchCompleted(int connId, int status)708     void onSearchCompleted(int connId, int status) throws RemoteException {
709         if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status);
710         // We got all services, now let's explore characteristics...
711         continueSearch(connId, status);
712     }
713 
onSearchResult(int connId, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb)714     void onSearchResult(int connId, int srvcType,
715             int srvcInstId, long srvcUuidLsb, long srvcUuidMsb)
716             throws RemoteException {
717         UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb);
718         String address = mClientMap.addressByConnId(connId);
719 
720         if (VDBG) Log.d(TAG, "onSearchResult() - address=" + address + ", uuid=" + uuid);
721 
722         mSearchQueue.add(connId, srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb);
723 
724         ClientMap.App app = mClientMap.getByConnId(connId);
725         if (app != null) {
726             app.callback.onGetService(address, srvcType, srvcInstId,
727                                         new ParcelUuid(uuid));
728         }
729     }
730 
onGetCharacteristic(int connId, int status, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int charInstId, long charUuidLsb, long charUuidMsb, int charProp)731     void onGetCharacteristic(int connId, int status, int srvcType,
732             int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
733             int charInstId, long charUuidLsb, long charUuidMsb,
734             int charProp) throws RemoteException {
735 
736         UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
737         UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
738         String address = mClientMap.addressByConnId(connId);
739 
740         if (VDBG) Log.d(TAG, "onGetCharacteristic() - address=" + address
741             + ", status=" + status + ", charUuid=" + charUuid + ", prop=" + charProp);
742 
743         if (status == 0) {
744             mSearchQueue.add(connId, srvcType,
745                             srvcInstId, srvcUuidLsb, srvcUuidMsb,
746                             charInstId, charUuidLsb, charUuidMsb);
747 
748             ClientMap.App app = mClientMap.getByConnId(connId);
749             if (app != null) {
750                 app.callback.onGetCharacteristic(address, srvcType,
751                             srvcInstId, new ParcelUuid(srvcUuid),
752                             charInstId, new ParcelUuid(charUuid), charProp);
753             }
754 
755             // Get next characteristic in the current service
756             gattClientGetCharacteristicNative(connId, srvcType,
757                                         srvcInstId, srvcUuidLsb, srvcUuidMsb,
758                                         charInstId, charUuidLsb, charUuidMsb);
759         } else {
760             // Check for included services next
761             gattClientGetIncludedServiceNative(connId,
762                 srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb,
763                 0,0,0,0);
764         }
765     }
766 
onGetDescriptor(int connId, int status, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int charInstId, long charUuidLsb, long charUuidMsb, int descrInstId, long descrUuidLsb, long descrUuidMsb)767     void onGetDescriptor(int connId, int status, int srvcType,
768             int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
769             int charInstId, long charUuidLsb, long charUuidMsb,
770             int descrInstId, long descrUuidLsb, long descrUuidMsb) throws RemoteException {
771 
772         UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
773         UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
774         UUID descUuid = new UUID(descrUuidMsb, descrUuidLsb);
775         String address = mClientMap.addressByConnId(connId);
776 
777         if (VDBG) Log.d(TAG, "onGetDescriptor() - address=" + address
778             + ", status=" + status + ", descUuid=" + descUuid);
779 
780         if (status == 0) {
781             ClientMap.App app = mClientMap.getByConnId(connId);
782             if (app != null) {
783                 app.callback.onGetDescriptor(address, srvcType,
784                             srvcInstId, new ParcelUuid(srvcUuid),
785                             charInstId, new ParcelUuid(charUuid),
786                             descrInstId, new ParcelUuid(descUuid));
787             }
788 
789             // Get next descriptor for the current characteristic
790             gattClientGetDescriptorNative(connId, srvcType,
791                                     srvcInstId, srvcUuidLsb, srvcUuidMsb,
792                                     charInstId, charUuidLsb, charUuidMsb,
793                                     descrInstId, descrUuidLsb, descrUuidMsb);
794         } else {
795             // Explore the next service
796             continueSearch(connId, 0);
797         }
798     }
799 
onGetIncludedService(int connId, int status, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int inclSrvcType, int inclSrvcInstId, long inclSrvcUuidLsb, long inclSrvcUuidMsb)800     void onGetIncludedService(int connId, int status, int srvcType,
801             int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int inclSrvcType,
802             int inclSrvcInstId, long inclSrvcUuidLsb, long inclSrvcUuidMsb)
803             throws RemoteException {
804         UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
805         UUID inclSrvcUuid = new UUID(inclSrvcUuidMsb, inclSrvcUuidLsb);
806         String address = mClientMap.addressByConnId(connId);
807 
808         if (VDBG) Log.d(TAG, "onGetIncludedService() - address=" + address
809             + ", status=" + status + ", uuid=" + srvcUuid
810             + ", inclUuid=" + inclSrvcUuid);
811 
812         if (status == 0) {
813             ClientMap.App app = mClientMap.getByConnId(connId);
814             if (app != null) {
815                 app.callback.onGetIncludedService(address,
816                     srvcType, srvcInstId, new ParcelUuid(srvcUuid),
817                     inclSrvcType, inclSrvcInstId, new ParcelUuid(inclSrvcUuid));
818             }
819 
820             // Find additional included services
821             gattClientGetIncludedServiceNative(connId,
822                 srvcType, srvcInstId, srvcUuidLsb, srvcUuidMsb,
823                 inclSrvcType, inclSrvcInstId, inclSrvcUuidLsb, inclSrvcUuidMsb);
824         } else {
825             // Discover descriptors now
826             continueSearch(connId, 0);
827         }
828     }
829 
onRegisterForNotifications(int connId, int status, int registered, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int charInstId, long charUuidLsb, long charUuidMsb)830     void onRegisterForNotifications(int connId, int status, int registered, int srvcType,
831             int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
832             int charInstId, long charUuidLsb, long charUuidMsb) {
833         UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
834         UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
835         String address = mClientMap.addressByConnId(connId);
836 
837         if (DBG) Log.d(TAG, "onRegisterForNotifications() - address=" + address
838             + ", status=" + status + ", registered=" + registered
839             + ", charUuid=" + charUuid);
840     }
841 
onNotify(int connId, String address, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int charInstId, long charUuidLsb, long charUuidMsb, boolean isNotify, byte[] data)842     void onNotify(int connId, String address, int srvcType,
843             int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
844             int charInstId, long charUuidLsb, long charUuidMsb,
845             boolean isNotify, byte[] data) throws RemoteException {
846         UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
847         UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
848 
849         if (VDBG) Log.d(TAG, "onNotify() - address=" + address
850             + ", charUuid=" + charUuid + ", length=" + data.length);
851 
852 
853         if (isHidUuid(charUuid) &&
854                (0 != checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED))) {
855             return;
856         }
857 
858         ClientMap.App app = mClientMap.getByConnId(connId);
859         if (app != null) {
860             app.callback.onNotify(address, srvcType,
861                         srvcInstId, new ParcelUuid(srvcUuid),
862                         charInstId, new ParcelUuid(charUuid),
863                         data);
864         }
865     }
866 
onReadCharacteristic(int connId, int status, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int charInstId, long charUuidLsb, long charUuidMsb, int charType, byte[] data)867     void onReadCharacteristic(int connId, int status, int srvcType,
868             int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
869             int charInstId, long charUuidLsb, long charUuidMsb,
870             int charType, byte[] data) throws RemoteException {
871 
872         UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
873         UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
874         String address = mClientMap.addressByConnId(connId);
875 
876         if (VDBG) Log.d(TAG, "onReadCharacteristic() - address=" + address
877             + ", status=" + status + ", length=" + data.length);
878 
879         ClientMap.App app = mClientMap.getByConnId(connId);
880         if (app != null) {
881             app.callback.onCharacteristicRead(address, status, srvcType,
882                         srvcInstId, new ParcelUuid(srvcUuid),
883                         charInstId, new ParcelUuid(charUuid), data);
884         }
885     }
886 
onWriteCharacteristic(int connId, int status, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int charInstId, long charUuidLsb, long charUuidMsb)887     void onWriteCharacteristic(int connId, int status, int srvcType,
888             int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
889             int charInstId, long charUuidLsb, long charUuidMsb)
890             throws RemoteException {
891 
892         UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
893         UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
894         String address = mClientMap.addressByConnId(connId);
895 
896         if (VDBG) Log.d(TAG, "onWriteCharacteristic() - address=" + address
897             + ", status=" + status);
898 
899         ClientMap.App app = mClientMap.getByConnId(connId);
900         if (app == null) return;
901 
902         if (!app.isCongested) {
903             app.callback.onCharacteristicWrite(address, status, srvcType,
904                     srvcInstId, new ParcelUuid(srvcUuid),
905                     charInstId, new ParcelUuid(charUuid));
906         } else {
907             if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
908                 status = BluetoothGatt.GATT_SUCCESS;
909             }
910             CallbackInfo callbackInfo = new CallbackInfo(address, status, srvcType,
911                     srvcInstId, srvcUuid, charInstId, charUuid);
912             app.queueCallback(callbackInfo);
913         }
914     }
915 
onExecuteCompleted(int connId, int status)916     void onExecuteCompleted(int connId, int status) throws RemoteException {
917         String address = mClientMap.addressByConnId(connId);
918         if (VDBG) Log.d(TAG, "onExecuteCompleted() - address=" + address
919             + ", status=" + status);
920 
921         ClientMap.App app = mClientMap.getByConnId(connId);
922         if (app != null) {
923             app.callback.onExecuteWrite(address, status);
924         }
925     }
926 
onReadDescriptor(int connId, int status, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int charInstId, long charUuidLsb, long charUuidMsb, int descrInstId, long descrUuidLsb, long descrUuidMsb, int charType, byte[] data)927     void onReadDescriptor(int connId, int status, int srvcType,
928             int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
929             int charInstId, long charUuidLsb, long charUuidMsb,
930             int descrInstId, long descrUuidLsb, long descrUuidMsb,
931             int charType, byte[] data) throws RemoteException {
932 
933         UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
934         UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
935         UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb);
936         String address = mClientMap.addressByConnId(connId);
937 
938         if (VDBG) Log.d(TAG, "onReadDescriptor() - address=" + address
939             + ", status=" + status + ", length=" + data.length);
940 
941         ClientMap.App app = mClientMap.getByConnId(connId);
942         if (app != null) {
943             app.callback.onDescriptorRead(address, status, srvcType,
944                         srvcInstId, new ParcelUuid(srvcUuid),
945                         charInstId, new ParcelUuid(charUuid),
946                         descrInstId, new ParcelUuid(descrUuid), data);
947         }
948     }
949 
onWriteDescriptor(int connId, int status, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int charInstId, long charUuidLsb, long charUuidMsb, int descrInstId, long descrUuidLsb, long descrUuidMsb)950     void onWriteDescriptor(int connId, int status, int srvcType,
951             int srvcInstId, long srvcUuidLsb, long srvcUuidMsb,
952             int charInstId, long charUuidLsb, long charUuidMsb,
953             int descrInstId, long descrUuidLsb, long descrUuidMsb) throws RemoteException {
954 
955         UUID srvcUuid = new UUID(srvcUuidMsb, srvcUuidLsb);
956         UUID charUuid = new UUID(charUuidMsb, charUuidLsb);
957         UUID descrUuid = new UUID(descrUuidMsb, descrUuidLsb);
958         String address = mClientMap.addressByConnId(connId);
959 
960         if (VDBG) Log.d(TAG, "onWriteDescriptor() - address=" + address
961             + ", status=" + status);
962 
963         ClientMap.App app = mClientMap.getByConnId(connId);
964         if (app != null) {
965             app.callback.onDescriptorWrite(address, status, srvcType,
966                         srvcInstId, new ParcelUuid(srvcUuid),
967                         charInstId, new ParcelUuid(charUuid),
968                         descrInstId, new ParcelUuid(descrUuid));
969         }
970     }
971 
onReadRemoteRssi(int clientIf, String address, int rssi, int status)972     void onReadRemoteRssi(int clientIf, String address,
973                     int rssi, int status) throws RemoteException{
974         if (DBG) Log.d(TAG, "onReadRemoteRssi() - clientIf=" + clientIf + " address=" +
975                      address + ", rssi=" + rssi + ", status=" + status);
976 
977         ClientMap.App app = mClientMap.getById(clientIf);
978         if (app != null) {
979             app.callback.onReadRemoteRssi(address, rssi, status);
980         }
981     }
982 
onScanFilterEnableDisabled(int action, int status, int clientIf)983     void onScanFilterEnableDisabled(int action, int status, int clientIf) {
984         if (DBG) {
985             Log.d(TAG, "onScanFilterEnableDisabled() - clientIf=" + clientIf + ", status=" + status
986                     + ", action=" + action);
987         }
988         mScanManager.callbackDone(clientIf, status);
989     }
990 
onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace)991     void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) {
992         if (DBG) {
993             Log.d(TAG, "onScanFilterParamsConfigured() - clientIf=" + clientIf
994                     + ", status=" + status + ", action=" + action
995                     + ", availableSpace=" + availableSpace);
996         }
997         mScanManager.callbackDone(clientIf, status);
998     }
999 
onScanFilterConfig(int action, int status, int clientIf, int filterType, int availableSpace)1000     void onScanFilterConfig(int action, int status, int clientIf, int filterType,
1001             int availableSpace) {
1002         if (DBG) {
1003             Log.d(TAG, "onScanFilterConfig() - clientIf=" + clientIf + ", action = " + action
1004                     + " status = " + status + ", filterType=" + filterType
1005                     + ", availableSpace=" + availableSpace);
1006         }
1007 
1008         mScanManager.callbackDone(clientIf, status);
1009     }
1010 
onBatchScanStorageConfigured(int status, int clientIf)1011     void onBatchScanStorageConfigured(int status, int clientIf) {
1012         if (DBG) {
1013             Log.d(TAG, "onBatchScanStorageConfigured() - clientIf="+ clientIf + ", status=" + status);
1014         }
1015         mScanManager.callbackDone(clientIf, status);
1016     }
1017 
1018     // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped.
onBatchScanStartStopped(int startStopAction, int status, int clientIf)1019     void onBatchScanStartStopped(int startStopAction, int status, int clientIf) {
1020         if (DBG) {
1021             Log.d(TAG, "onBatchScanStartStopped() - clientIf=" + clientIf
1022                     + ", status=" + status + ", startStopAction=" + startStopAction);
1023         }
1024         mScanManager.callbackDone(clientIf, status);
1025     }
1026 
onBatchScanReports(int status, int clientIf, int reportType, int numRecords, byte[] recordData)1027     void onBatchScanReports(int status, int clientIf, int reportType, int numRecords,
1028             byte[] recordData) throws RemoteException {
1029         if (DBG) {
1030             Log.d(TAG, "onBatchScanReports() - clientIf=" + clientIf + ", status=" + status
1031                     + ", reportType=" + reportType + ", numRecords=" + numRecords);
1032         }
1033         mScanManager.callbackDone(clientIf, status);
1034         Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData);
1035         if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) {
1036             // We only support single client for truncated mode.
1037             ClientMap.App app = mClientMap.getById(clientIf);
1038             if (app == null) return;
1039             app.callback.onBatchScanResults(new ArrayList<ScanResult>(results));
1040         } else {
1041             for (ScanClient client : mScanManager.getFullBatchScanQueue()) {
1042                 // Deliver results for each client.
1043                 deliverBatchScan(client, results);
1044             }
1045         }
1046     }
1047 
1048     // Check and deliver scan results for different scan clients.
deliverBatchScan(ScanClient client, Set<ScanResult> allResults)1049     private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) throws
1050             RemoteException {
1051         ClientMap.App app = mClientMap.getById(client.clientIf);
1052         if (app == null) return;
1053         if (client.filters == null || client.filters.isEmpty()) {
1054             app.callback.onBatchScanResults(new ArrayList<ScanResult>(allResults));
1055         }
1056         // Reconstruct the scan results.
1057         List<ScanResult> results = new ArrayList<ScanResult>();
1058         for (ScanResult scanResult : allResults) {
1059             if (matchesFilters(client, scanResult)) {
1060                 results.add(scanResult);
1061             }
1062         }
1063         app.callback.onBatchScanResults(results);
1064     }
1065 
parseBatchScanResults(int numRecords, int reportType, byte[] batchRecord)1066     private Set<ScanResult> parseBatchScanResults(int numRecords, int reportType,
1067             byte[] batchRecord) {
1068         if (numRecords == 0) {
1069             return Collections.emptySet();
1070         }
1071         if (DBG) Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos());
1072         if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) {
1073             return parseTruncatedResults(numRecords, batchRecord);
1074         } else {
1075             return parseFullResults(numRecords, batchRecord);
1076         }
1077     }
1078 
parseTruncatedResults(int numRecords, byte[] batchRecord)1079     private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) {
1080         if (DBG) Log.d(TAG, "batch record " + Arrays.toString(batchRecord));
1081         Set<ScanResult> results = new HashSet<ScanResult>(numRecords);
1082         long now = SystemClock.elapsedRealtimeNanos();
1083         for (int i = 0; i < numRecords; ++i) {
1084             byte[] record = extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE,
1085                     TRUNCATED_RESULT_SIZE);
1086             byte[] address = extractBytes(record, 0, 6);
1087             reverse(address);
1088             BluetoothDevice device = mAdapter.getRemoteDevice(address);
1089             int rssi = record[8];
1090             long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2));
1091             results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]),
1092                     rssi, timestampNanos));
1093         }
1094         return results;
1095     }
1096 
1097     @VisibleForTesting
parseTimestampNanos(byte[] data)1098     long parseTimestampNanos(byte[] data) {
1099         long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data);
1100         // Timestamp is in every 50 ms.
1101         return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50);
1102     }
1103 
parseFullResults(int numRecords, byte[] batchRecord)1104     private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) {
1105         Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord));
1106         Set<ScanResult> results = new HashSet<ScanResult>(numRecords);
1107         int position = 0;
1108         long now = SystemClock.elapsedRealtimeNanos();
1109         while (position < batchRecord.length) {
1110             byte[] address = extractBytes(batchRecord, position, 6);
1111             // TODO: remove temp hack.
1112             reverse(address);
1113             BluetoothDevice device = mAdapter.getRemoteDevice(address);
1114             position += 6;
1115             // Skip address type.
1116             position++;
1117             // Skip tx power level.
1118             position++;
1119             int rssi = batchRecord[position++];
1120             long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2));
1121             position += 2;
1122 
1123             // Combine advertise packet and scan response packet.
1124             int advertisePacketLen = batchRecord[position++];
1125             byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen);
1126             position += advertisePacketLen;
1127             int scanResponsePacketLen = batchRecord[position++];
1128             byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen);
1129             position += scanResponsePacketLen;
1130             byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen];
1131             System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen);
1132             System.arraycopy(scanResponseBytes, 0, scanRecord,
1133                     advertisePacketLen, scanResponsePacketLen);
1134             Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord));
1135             results.add(new ScanResult(device, ScanRecord.parseFromBytes(scanRecord),
1136                     rssi, timestampNanos));
1137         }
1138         return results;
1139     }
1140 
1141     // Reverse byte array.
reverse(byte[] address)1142     private void reverse(byte[] address) {
1143         int len = address.length;
1144         for (int i = 0; i < len / 2; ++i) {
1145             byte b = address[i];
1146             address[i] = address[len - 1 - i];
1147             address[len - 1 - i] = b;
1148         }
1149     }
1150 
1151     // Helper method to extract bytes from byte array.
extractBytes(byte[] scanRecord, int start, int length)1152     private static byte[] extractBytes(byte[] scanRecord, int start, int length) {
1153         byte[] bytes = new byte[length];
1154         System.arraycopy(scanRecord, start, bytes, 0, length);
1155         return bytes;
1156     }
1157 
onBatchScanThresholdCrossed(int clientIf)1158     void onBatchScanThresholdCrossed(int clientIf) {
1159         if (DBG) {
1160             Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf);
1161         }
1162         boolean isServer = false;
1163         flushPendingBatchResults(clientIf, isServer);
1164     }
1165 
CreateonTrackAdvFoundLostObject(int client_if, int adv_pkt_len, byte[] adv_pkt, int scan_rsp_len, byte[] scan_rsp, int filt_index, int adv_state, int adv_info_present, String address, int addr_type, int tx_power, int rssi_value, int time_stamp)1166     AdvtFilterOnFoundOnLostInfo CreateonTrackAdvFoundLostObject(int client_if, int adv_pkt_len,
1167                     byte[] adv_pkt, int scan_rsp_len, byte[] scan_rsp, int filt_index, int adv_state,
1168                     int adv_info_present, String address, int addr_type, int tx_power, int rssi_value,
1169                     int time_stamp) {
1170 
1171         return new AdvtFilterOnFoundOnLostInfo(client_if, adv_pkt_len, adv_pkt,
1172                     scan_rsp_len, scan_rsp, filt_index, adv_state,
1173                     adv_info_present, address, addr_type, tx_power,
1174                     rssi_value, time_stamp);
1175     }
1176 
onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo)1177     void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException {
1178         if (DBG) Log.d(TAG, "onTrackAdvFoundLost() - clientIf= " + trackingInfo.getClientIf()
1179                     + " address = " + trackingInfo.getAddress()
1180                     + " adv_state = " + trackingInfo.getAdvState());
1181 
1182         ClientMap.App app = mClientMap.getById(trackingInfo.getClientIf());
1183         if (app == null || app.callback == null) {
1184             Log.e(TAG, "app or callback is null");
1185             return;
1186         }
1187 
1188         BluetoothDevice device = BluetoothAdapter.getDefaultAdapter()
1189                         .getRemoteDevice(trackingInfo.getAddress());
1190         int advertiserState = trackingInfo.getAdvState();
1191         ScanResult result = new ScanResult(device,
1192                         ScanRecord.parseFromBytes(trackingInfo.getResult()),
1193                         trackingInfo.getRSSIValue(), SystemClock.elapsedRealtimeNanos());
1194 
1195         for (ScanClient client : mScanManager.getRegularScanQueue()) {
1196             if (client.clientIf == trackingInfo.getClientIf()) {
1197                 ScanSettings settings = client.settings;
1198                 if ((advertiserState == ADVT_STATE_ONFOUND)
1199                         && ((settings.getCallbackType()
1200                                 & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0)) {
1201                     app.callback.onFoundOrLost(true, result);
1202                 } else if ((advertiserState == ADVT_STATE_ONLOST)
1203                                 && ((settings.getCallbackType()
1204                                         & ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0)) {
1205                     app.callback.onFoundOrLost(false, result);
1206                 } else {
1207                     Log.d(TAG, "Not reporting onlost/onfound : " + advertiserState
1208                                 + " clientIf = " + client.clientIf
1209                                 + " callbackType " + settings.getCallbackType());
1210                 }
1211             }
1212         }
1213     }
1214 
onScanParamSetupCompleted(int status, int clientIf)1215     void onScanParamSetupCompleted(int status, int clientIf) throws RemoteException {
1216         ClientMap.App app = mClientMap.getById(clientIf);
1217         if (app == null || app.callback == null) {
1218             Log.e(TAG, "Advertise app or callback is null");
1219             return;
1220         }
1221         Log.d(TAG, "onScanParamSetupCompleted : " + status);
1222     }
1223 
1224     // callback from AdvertiseManager for advertise status dispatch.
onMultipleAdvertiseCallback(int clientIf, int status, boolean isStart, AdvertiseSettings settings)1225     void onMultipleAdvertiseCallback(int clientIf, int status, boolean isStart,
1226             AdvertiseSettings settings) throws RemoteException {
1227         ClientMap.App app = mClientMap.getById(clientIf);
1228         if (app == null || app.callback == null) {
1229             Log.e(TAG, "Advertise app or callback is null");
1230             return;
1231         }
1232         app.callback.onMultiAdvertiseCallback(status, isStart, settings);
1233     }
1234 
1235     // callback from ScanManager for dispatch of errors apps.
onScanManagerErrorCallback(int clientIf, int errorCode)1236     void onScanManagerErrorCallback(int clientIf, int errorCode) throws RemoteException {
1237         ClientMap.App app = mClientMap.getById(clientIf);
1238         if (app == null || app.callback == null) {
1239             Log.e(TAG, "App or callback is null");
1240             return;
1241         }
1242         app.callback.onScanManagerErrorCallback(errorCode);
1243     }
1244 
onConfigureMTU(int connId, int status, int mtu)1245     void onConfigureMTU(int connId, int status, int mtu) throws RemoteException {
1246         String address = mClientMap.addressByConnId(connId);
1247 
1248         if (DBG) Log.d(TAG, "onConfigureMTU() address=" + address + ", status="
1249             + status + ", mtu=" + mtu);
1250 
1251         ClientMap.App app = mClientMap.getByConnId(connId);
1252         if (app != null) {
1253             app.callback.onConfigureMTU(address, mtu, status);
1254         }
1255     }
1256 
1257     // Callback for standard advertising instance.
onAdvertiseCallback(int status, int clientIf)1258     void onAdvertiseCallback(int status, int clientIf) {
1259         if (DBG) Log.d(TAG, "onAdvertiseCallback,- clientIf=" + clientIf + ", status=" + status);
1260         mAdvertiseManager.callbackDone(clientIf, status);
1261     }
1262 
1263     // Followings are callbacks for Bluetooth LE Advertise operations.
1264     // Start advertising flow is
1265     //     enable advertising instance -> onAdvertiseInstaceEnabled
1266     // ->  set advertise data          -> onAdvertiseDataSet
1267     // ->  set scan response           -> onAdvertiseDataSet
1268 
1269     // Callback when advertise instance is enabled.
onAdvertiseInstanceEnabled(int status, int clientIf)1270     void onAdvertiseInstanceEnabled(int status, int clientIf) {
1271         if (DBG) Log.d(TAG, "onAdvertiseInstanceEnabled() - "
1272                 + "clientIf=" + clientIf + ", status=" + status);
1273         mAdvertiseManager.callbackDone(clientIf, status);
1274     }
1275 
1276     // Not really used.
onAdvertiseDataUpdated(int status, int client_if)1277     void onAdvertiseDataUpdated(int status, int client_if) {
1278         if (DBG) Log.d(TAG, "onAdvertiseDataUpdated() - client_if=" + client_if
1279             + ", status=" + status);
1280     }
1281 
1282     // Callback when advertise data or scan response is set.
onAdvertiseDataSet(int status, int clientIf)1283     void onAdvertiseDataSet(int status, int clientIf) {
1284         if (DBG) Log.d(TAG, "onAdvertiseDataSet() - clientIf=" + clientIf
1285             + ", status=" + status);
1286         mAdvertiseManager.callbackDone(clientIf, status);
1287     }
1288 
1289     // Callback when advertise instance is disabled
onAdvertiseInstanceDisabled(int status, int clientIf)1290     void onAdvertiseInstanceDisabled(int status, int clientIf) throws RemoteException {
1291         if (DBG) Log.d(TAG, "onAdvertiseInstanceDisabled() - clientIf=" + clientIf
1292             + ", status=" + status);
1293         ClientMap.App app = mClientMap.getById(clientIf);
1294         if (app != null) {
1295             Log.d(TAG, "Client app is not null!");
1296             boolean isStart = false;
1297             if (status == 0) {
1298                 app.callback.onMultiAdvertiseCallback(AdvertiseCallback.ADVERTISE_SUCCESS,
1299                         isStart, null);
1300             } else {
1301                 app.callback.onMultiAdvertiseCallback(
1302                         AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR, isStart, null);
1303             }
1304         }
1305     }
1306 
onClientCongestion(int connId, boolean congested)1307     void onClientCongestion(int connId, boolean congested) throws RemoteException {
1308         if (VDBG) Log.d(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested);
1309 
1310         ClientMap.App app = mClientMap.getByConnId(connId);
1311 
1312         if (app != null) {
1313             app.isCongested = congested;
1314             while(!app.isCongested) {
1315                 CallbackInfo callbackInfo = app.popQueuedCallback();
1316                 if (callbackInfo == null)  return;
1317                 app.callback.onCharacteristicWrite(callbackInfo.address,
1318                         callbackInfo.status, callbackInfo.srvcType,
1319                         callbackInfo.srvcInstId, new ParcelUuid(callbackInfo.srvcUuid),
1320                         callbackInfo.charInstId, new ParcelUuid(callbackInfo.charUuid));
1321             }
1322         }
1323     }
1324 
1325     /**************************************************************************
1326      * GATT Service functions - Shared CLIENT/SERVER
1327      *************************************************************************/
1328 
getDevicesMatchingConnectionStates(int[] states)1329     List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
1330         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1331 
1332         final int DEVICE_TYPE_BREDR = 0x1;
1333 
1334         Map<BluetoothDevice, Integer> deviceStates = new HashMap<BluetoothDevice,
1335                                                                  Integer>();
1336 
1337         // Add paired LE devices
1338 
1339         Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices();
1340         for (BluetoothDevice device : bondedDevices) {
1341             if (getDeviceType(device) != DEVICE_TYPE_BREDR) {
1342                 deviceStates.put(device, BluetoothProfile.STATE_DISCONNECTED);
1343             }
1344         }
1345 
1346         // Add connected deviceStates
1347 
1348         Set<String> connectedDevices = new HashSet<String>();
1349         connectedDevices.addAll(mClientMap.getConnectedDevices());
1350         connectedDevices.addAll(mServerMap.getConnectedDevices());
1351 
1352         for (String address : connectedDevices ) {
1353             BluetoothDevice device = mAdapter.getRemoteDevice(address);
1354             if (device != null) {
1355                 deviceStates.put(device, BluetoothProfile.STATE_CONNECTED);
1356             }
1357         }
1358 
1359         // Create matching device sub-set
1360 
1361         List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();
1362 
1363         for (Map.Entry<BluetoothDevice, Integer> entry : deviceStates.entrySet()) {
1364             for(int state : states) {
1365                 if (entry.getValue() == state) {
1366                     deviceList.add(entry.getKey());
1367                 }
1368             }
1369         }
1370 
1371         return deviceList;
1372     }
1373 
startScan(int appIf, boolean isServer, ScanSettings settings, List<ScanFilter> filters, List<List<ResultStorageDescriptor>> storages, String callingPackage)1374     void startScan(int appIf, boolean isServer, ScanSettings settings,
1375             List<ScanFilter> filters, List<List<ResultStorageDescriptor>> storages,
1376             String callingPackage) {
1377         if (DBG) Log.d(TAG, "start scan with filters");
1378         enforceAdminPermission();
1379         if (needsPrivilegedPermissionForScan(settings)) {
1380             enforcePrivilegedPermission();
1381         }
1382         final ScanClient scanClient = new ScanClient(appIf, isServer, settings, filters, storages);
1383         scanClient.hasLocationPermission = Utils.checkCallerHasLocationPermission(this, mAppOps,
1384                 callingPackage);
1385         scanClient.hasPeersMacAddressPermission = Utils.checkCallerHasPeersMacAddressPermission(
1386                 this);
1387         scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, callingPackage);
1388         mScanManager.startScan(scanClient);
1389     }
1390 
flushPendingBatchResults(int clientIf, boolean isServer)1391     void flushPendingBatchResults(int clientIf, boolean isServer) {
1392         if (DBG) Log.d(TAG, "flushPendingBatchResults - clientIf=" + clientIf +
1393                 ", isServer=" + isServer);
1394         mScanManager.flushBatchScanResults(new ScanClient(clientIf, isServer));
1395     }
1396 
stopScan(ScanClient client)1397     void stopScan(ScanClient client) {
1398         enforceAdminPermission();
1399         int scanQueueSize = mScanManager.getBatchScanQueue().size() +
1400                 mScanManager.getRegularScanQueue().size();
1401         if (DBG) Log.d(TAG, "stopScan() - queue size =" + scanQueueSize);
1402         mScanManager.stopScan(client);
1403     }
1404 
disconnectAll()1405     void disconnectAll() {
1406         if (DBG) Log.d(TAG, "disconnectAll()");
1407         Map<Integer, String> connMap = mClientMap.getConnectedMap();
1408         for(Map.Entry<Integer, String> entry:connMap.entrySet()){
1409             if (DBG) Log.d(TAG, "disconnecting addr:" + entry.getValue());
1410             clientDisconnect(entry.getKey(), entry.getValue());
1411             //clientDisconnect(int clientIf, String address)
1412         }
1413     }
1414 
unregAll()1415     void unregAll() {
1416         for(ClientMap.App app:mClientMap.mApps){
1417             if (DBG) Log.d(TAG, "unreg:" + app.id);
1418             unregisterClient(app.id);
1419         }
1420     }
1421 
1422     /**************************************************************************
1423      * GATT Service functions - CLIENT
1424      *************************************************************************/
1425 
registerClient(UUID uuid, IBluetoothGattCallback callback)1426     void registerClient(UUID uuid, IBluetoothGattCallback callback) {
1427         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1428 
1429         if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid);
1430         mClientMap.add(uuid, callback);
1431         gattClientRegisterAppNative(uuid.getLeastSignificantBits(),
1432                                     uuid.getMostSignificantBits());
1433     }
1434 
unregisterClient(int clientIf)1435     void unregisterClient(int clientIf) {
1436         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1437 
1438         if (DBG) Log.d(TAG, "unregisterClient() - clientIf=" + clientIf);
1439         mClientMap.remove(clientIf);
1440         gattClientUnregisterAppNative(clientIf);
1441     }
1442 
clientConnect(int clientIf, String address, boolean isDirect, int transport)1443     void clientConnect(int clientIf, String address, boolean isDirect, int transport) {
1444         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1445 
1446         if (DBG) Log.d(TAG, "clientConnect() - address=" + address + ", isDirect=" + isDirect);
1447         gattClientConnectNative(clientIf, address, isDirect, transport);
1448     }
1449 
clientDisconnect(int clientIf, String address)1450     void clientDisconnect(int clientIf, String address) {
1451         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1452 
1453         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1454         if (DBG) Log.d(TAG, "clientDisconnect() - address=" + address + ", connId=" + connId);
1455 
1456         gattClientDisconnectNative(clientIf, address, connId != null ? connId : 0);
1457     }
1458 
startMultiAdvertising(int clientIf, AdvertiseData advertiseData, AdvertiseData scanResponse, AdvertiseSettings settings)1459     void startMultiAdvertising(int clientIf, AdvertiseData advertiseData,
1460             AdvertiseData scanResponse, AdvertiseSettings settings) {
1461         enforceAdminPermission();
1462         mAdvertiseManager.startAdvertising(new AdvertiseClient(clientIf, settings, advertiseData,
1463                 scanResponse));
1464     }
1465 
stopMultiAdvertising(AdvertiseClient client)1466     void stopMultiAdvertising(AdvertiseClient client) {
1467         enforceAdminPermission();
1468         mAdvertiseManager.stopAdvertising(client);
1469     }
1470 
numHwTrackFiltersAvailable()1471     int numHwTrackFiltersAvailable() {
1472         return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements()
1473                     - mScanManager.getCurrentUsedTrackingAdvertisement());
1474     }
1475 
getRegisteredServiceUuids()1476     synchronized List<ParcelUuid> getRegisteredServiceUuids() {
1477         Utils.enforceAdminPermission(this);
1478         List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>();
1479         for (HandleMap.Entry entry : mHandleMap.mEntries) {
1480             serviceUuids.add(new ParcelUuid(entry.uuid));
1481         }
1482         return serviceUuids;
1483     }
1484 
getConnectedDevices()1485     List<String> getConnectedDevices() {
1486         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1487 
1488         Set<String> connectedDevAddress = new HashSet<String>();
1489         connectedDevAddress.addAll(mClientMap.getConnectedDevices());
1490         connectedDevAddress.addAll(mServerMap.getConnectedDevices());
1491         List<String> connectedDeviceList = new ArrayList<String>(connectedDevAddress);
1492         return connectedDeviceList;
1493     }
1494 
refreshDevice(int clientIf, String address)1495     void refreshDevice(int clientIf, String address) {
1496         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1497 
1498         if (DBG) Log.d(TAG, "refreshDevice() - address=" + address);
1499         gattClientRefreshNative(clientIf, address);
1500     }
1501 
discoverServices(int clientIf, String address)1502     void discoverServices(int clientIf, String address) {
1503         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1504 
1505         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1506         if (DBG) Log.d(TAG, "discoverServices() - address=" + address + ", connId=" + connId);
1507 
1508         if (connId != null)
1509             gattClientSearchServiceNative(connId, true, 0, 0);
1510         else
1511             Log.e(TAG, "discoverServices() - No connection for " + address + "...");
1512     }
1513 
readCharacteristic(int clientIf, String address, int srvcType, int srvcInstanceId, UUID srvcUuid, int charInstanceId, UUID charUuid, int authReq)1514     void readCharacteristic(int clientIf, String address, int srvcType,
1515                             int srvcInstanceId, UUID srvcUuid,
1516                             int charInstanceId, UUID charUuid, int authReq) {
1517         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1518         if (isHidUuid(charUuid)) enforcePrivilegedPermission();
1519 
1520         if (VDBG) Log.d(TAG, "readCharacteristic() - address=" + address);
1521 
1522         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1523         if (connId != null)
1524             gattClientReadCharacteristicNative(connId, srvcType,
1525                 srvcInstanceId, srvcUuid.getLeastSignificantBits(),
1526                 srvcUuid.getMostSignificantBits(), charInstanceId,
1527                 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(),
1528                 authReq);
1529         else
1530             Log.e(TAG, "readCharacteristic() - No connection for " + address + "...");
1531     }
1532 
writeCharacteristic(int clientIf, String address, int srvcType, int srvcInstanceId, UUID srvcUuid, int charInstanceId, UUID charUuid, int writeType, int authReq, byte[] value)1533     void writeCharacteristic(int clientIf, String address, int srvcType,
1534                              int srvcInstanceId, UUID srvcUuid,
1535                              int charInstanceId, UUID charUuid, int writeType,
1536                              int authReq, byte[] value) {
1537         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1538         if (isHidUuid(charUuid)) enforcePrivilegedPermission();
1539 
1540         if (VDBG) Log.d(TAG, "writeCharacteristic() - address=" + address);
1541 
1542         if (mReliableQueue.contains(address)) writeType = 3; // Prepared write
1543 
1544         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1545         if (connId != null)
1546             gattClientWriteCharacteristicNative(connId, srvcType,
1547                 srvcInstanceId, srvcUuid.getLeastSignificantBits(),
1548                 srvcUuid.getMostSignificantBits(), charInstanceId,
1549                 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(),
1550                 writeType, authReq, value);
1551         else
1552             Log.e(TAG, "writeCharacteristic() - No connection for " + address + "...");
1553     }
1554 
readDescriptor(int clientIf, String address, int srvcType, int srvcInstanceId, UUID srvcUuid, int charInstanceId, UUID charUuid, int descrInstanceId, UUID descrUuid, int authReq)1555     void readDescriptor(int clientIf, String address, int srvcType,
1556                             int srvcInstanceId, UUID srvcUuid,
1557                             int charInstanceId, UUID charUuid,
1558                             int descrInstanceId, UUID descrUuid,
1559                             int authReq) {
1560         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1561         if (isHidUuid(charUuid)) enforcePrivilegedPermission();
1562 
1563         if (VDBG) Log.d(TAG, "readDescriptor() - address=" + address);
1564 
1565         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1566         if (connId != null)
1567             gattClientReadDescriptorNative(connId, srvcType,
1568                 srvcInstanceId,
1569                 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(),
1570                 charInstanceId,
1571                 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(),
1572                 descrInstanceId,
1573                 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(),
1574                 authReq);
1575         else
1576             Log.e(TAG, "readDescriptor() - No connection for " + address + "...");
1577     };
1578 
writeDescriptor(int clientIf, String address, int srvcType, int srvcInstanceId, UUID srvcUuid, int charInstanceId, UUID charUuid, int descrInstanceId, UUID descrUuid, int writeType, int authReq, byte[] value)1579     void writeDescriptor(int clientIf, String address, int srvcType,
1580                             int srvcInstanceId, UUID srvcUuid,
1581                             int charInstanceId, UUID charUuid,
1582                             int descrInstanceId, UUID descrUuid,
1583                             int writeType, int authReq, byte[] value) {
1584         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1585         if (isHidUuid(charUuid)) enforcePrivilegedPermission();
1586 
1587         if (VDBG) Log.d(TAG, "writeDescriptor() - address=" + address);
1588 
1589         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1590         if (connId != null)
1591             gattClientWriteDescriptorNative(connId, srvcType,
1592                 srvcInstanceId,
1593                 srvcUuid.getLeastSignificantBits(), srvcUuid.getMostSignificantBits(),
1594                 charInstanceId,
1595                 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(),
1596                 descrInstanceId,
1597                 descrUuid.getLeastSignificantBits(), descrUuid.getMostSignificantBits(),
1598                 writeType, authReq, value);
1599         else
1600             Log.e(TAG, "writeDescriptor() - No connection for " + address + "...");
1601     }
1602 
beginReliableWrite(int clientIf, String address)1603     void beginReliableWrite(int clientIf, String address) {
1604         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1605 
1606         if (DBG) Log.d(TAG, "beginReliableWrite() - address=" + address);
1607         mReliableQueue.add(address);
1608     }
1609 
endReliableWrite(int clientIf, String address, boolean execute)1610     void endReliableWrite(int clientIf, String address, boolean execute) {
1611         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1612 
1613         if (DBG) Log.d(TAG, "endReliableWrite() - address=" + address
1614                                 + " execute: " + execute);
1615         mReliableQueue.remove(address);
1616 
1617         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1618         if (connId != null) gattClientExecuteWriteNative(connId, execute);
1619     }
1620 
registerForNotification(int clientIf, String address, int srvcType, int srvcInstanceId, UUID srvcUuid, int charInstanceId, UUID charUuid, boolean enable)1621     void registerForNotification(int clientIf, String address, int srvcType,
1622                 int srvcInstanceId, UUID srvcUuid,
1623                 int charInstanceId, UUID charUuid,
1624                 boolean enable) {
1625         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1626         if (isHidUuid(charUuid)) enforcePrivilegedPermission();
1627 
1628         if (DBG) Log.d(TAG, "registerForNotification() - address=" + address + " enable: " + enable);
1629 
1630         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1631         if (connId != null) {
1632             gattClientRegisterForNotificationsNative(clientIf, address,
1633                 srvcType, srvcInstanceId, srvcUuid.getLeastSignificantBits(),
1634                 srvcUuid.getMostSignificantBits(), charInstanceId,
1635                 charUuid.getLeastSignificantBits(), charUuid.getMostSignificantBits(),
1636                 enable);
1637         } else {
1638             Log.e(TAG, "registerForNotification() - No connection for " + address + "...");
1639         }
1640     }
1641 
readRemoteRssi(int clientIf, String address)1642     void readRemoteRssi(int clientIf, String address) {
1643         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1644 
1645         if (DBG) Log.d(TAG, "readRemoteRssi() - address=" + address);
1646         gattClientReadRemoteRssiNative(clientIf, address);
1647     }
1648 
configureMTU(int clientIf, String address, int mtu)1649     void configureMTU(int clientIf, String address, int mtu) {
1650         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1651 
1652         if (DBG) Log.d(TAG, "configureMTU() - address=" + address + " mtu=" + mtu);
1653         Integer connId = mClientMap.connIdByAddress(clientIf, address);
1654         if (connId != null) {
1655             gattClientConfigureMTUNative(connId, mtu);
1656         } else {
1657             Log.e(TAG, "configureMTU() - No connection for " + address + "...");
1658         }
1659     }
1660 
connectionParameterUpdate(int clientIf, String address, int connectionPriority)1661     void connectionParameterUpdate(int clientIf, String address, int connectionPriority) {
1662         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1663 
1664         // Default spec recommended interval is 30->50 ms
1665         int minInterval = 24; // 24 * 1.25ms = 30ms
1666         int maxInterval = 40; // 40 * 1.25ms = 50ms
1667 
1668         // Slave latency
1669         int latency = 0;
1670 
1671         // Link supervision timeout is measured in N * 10ms
1672         int timeout = 2000; // 20s
1673 
1674         switch (connectionPriority)
1675         {
1676             case BluetoothGatt.CONNECTION_PRIORITY_HIGH:
1677                 minInterval = 9; // 11.25ms
1678                 maxInterval = 12; // 15ms
1679                 break;
1680 
1681             case BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER:
1682                 minInterval = 80; // 100ms
1683                 maxInterval = 100; // 125ms
1684                 latency = 2;
1685                 break;
1686         }
1687 
1688         if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address
1689             + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval);
1690         gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval,
1691                                             latency, timeout);
1692     }
1693 
1694     /**************************************************************************
1695      * Callback functions - SERVER
1696      *************************************************************************/
1697 
onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb)1698     void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb)
1699             throws RemoteException {
1700 
1701         UUID uuid = new UUID(uuidMsb, uuidLsb);
1702         if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf);
1703         ServerMap.App app = mServerMap.getByUuid(uuid);
1704         if (app != null) {
1705             app.id = serverIf;
1706             app.linkToDeath(new ServerDeathRecipient(serverIf));
1707             app.callback.onServerRegistered(status, serverIf);
1708         }
1709     }
1710 
onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int srvcHandle)1711     void onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId,
1712                         long srvcUuidLsb, long srvcUuidMsb, int srvcHandle)
1713                         throws RemoteException {
1714         UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb);
1715         if (DBG) Log.d(TAG, "onServiceAdded() UUID=" + uuid + ", status=" + status
1716             + ", handle=" + srvcHandle);
1717         if (status == 0) {
1718             mHandleMap.addService(serverIf, srvcHandle, uuid, srvcType, srvcInstId,
1719                 mAdvertisingServiceUuids.remove(uuid));
1720         }
1721 
1722         continueServiceDeclaration(serverIf, status, srvcHandle);
1723     }
1724 
onIncludedServiceAdded(int status, int serverIf, int srvcHandle, int includedSrvcHandle)1725     void onIncludedServiceAdded(int status, int serverIf, int srvcHandle,
1726                                 int includedSrvcHandle) throws RemoteException {
1727         if (DBG) Log.d(TAG, "onIncludedServiceAdded() status=" + status
1728             + ", service=" + srvcHandle + ", included=" + includedSrvcHandle);
1729         continueServiceDeclaration(serverIf, status, srvcHandle);
1730     }
1731 
onCharacteristicAdded(int status, int serverIf, long charUuidLsb, long charUuidMsb, int srvcHandle, int charHandle)1732     void onCharacteristicAdded(int status, int serverIf,
1733                                long charUuidLsb, long charUuidMsb,
1734                                int srvcHandle, int charHandle)
1735                                throws RemoteException {
1736             UUID uuid = new UUID(charUuidMsb, charUuidLsb);
1737         if (DBG) Log.d(TAG, "onCharacteristicAdded() UUID=" + uuid + ", status=" + status
1738             + ", srvcHandle=" + srvcHandle + ", charHandle=" + charHandle);
1739         if (status == 0)
1740             mHandleMap.addCharacteristic(serverIf, charHandle, uuid, srvcHandle);
1741         continueServiceDeclaration(serverIf, status, srvcHandle);
1742     }
1743 
onDescriptorAdded(int status, int serverIf, long descrUuidLsb, long descrUuidMsb, int srvcHandle, int descrHandle)1744     void onDescriptorAdded(int status, int serverIf,
1745                            long descrUuidLsb, long descrUuidMsb,
1746                            int srvcHandle, int descrHandle)
1747                            throws RemoteException {
1748             UUID uuid = new UUID(descrUuidMsb, descrUuidLsb);
1749         if (DBG) Log.d(TAG, "onDescriptorAdded() UUID=" + uuid + ", status=" + status
1750             + ", srvcHandle=" + srvcHandle + ", descrHandle=" + descrHandle);
1751         if (status == 0)
1752             mHandleMap.addDescriptor(serverIf, descrHandle, uuid, srvcHandle);
1753         continueServiceDeclaration(serverIf, status, srvcHandle);
1754     }
1755 
onServiceStarted(int status, int serverIf, int srvcHandle)1756     void onServiceStarted(int status, int serverIf, int srvcHandle)
1757             throws RemoteException {
1758         if (DBG) Log.d(TAG, "onServiceStarted() srvcHandle=" + srvcHandle
1759             + ", status=" + status);
1760         if (status == 0)
1761             mHandleMap.setStarted(serverIf, srvcHandle, true);
1762     }
1763 
onServiceStopped(int status, int serverIf, int srvcHandle)1764     void onServiceStopped(int status, int serverIf, int srvcHandle)
1765             throws RemoteException {
1766         if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle
1767             + ", status=" + status);
1768         if (status == 0)
1769             mHandleMap.setStarted(serverIf, srvcHandle, false);
1770         stopNextService(serverIf, status);
1771     }
1772 
onServiceDeleted(int status, int serverIf, int srvcHandle)1773     void onServiceDeleted(int status, int serverIf, int srvcHandle) {
1774         if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle
1775             + ", status=" + status);
1776         mHandleMap.deleteService(serverIf, srvcHandle);
1777     }
1778 
onClientConnected(String address, boolean connected, int connId, int serverIf)1779     void onClientConnected(String address, boolean connected, int connId, int serverIf)
1780             throws RemoteException {
1781 
1782         if (DBG) Log.d(TAG, "onConnected() connId=" + connId
1783             + ", address=" + address + ", connected=" + connected);
1784 
1785         ServerMap.App app = mServerMap.getById(serverIf);
1786         if (app == null) return;
1787 
1788         if (connected) {
1789             mServerMap.addConnection(serverIf, connId, address);
1790         } else {
1791             mServerMap.removeConnection(serverIf, connId);
1792         }
1793 
1794         app.callback.onServerConnectionState((byte)0, serverIf, connected, address);
1795     }
1796 
onAttributeRead(String address, int connId, int transId, int attrHandle, int offset, boolean isLong)1797     void onAttributeRead(String address, int connId, int transId,
1798                             int attrHandle, int offset, boolean isLong)
1799                             throws RemoteException {
1800         if (VDBG) Log.d(TAG, "onAttributeRead() connId=" + connId
1801             + ", address=" + address + ", handle=" + attrHandle
1802             + ", requestId=" + transId + ", offset=" + offset);
1803 
1804         HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle);
1805         if (entry == null) return;
1806 
1807         mHandleMap.addRequest(transId, attrHandle);
1808 
1809         ServerMap.App app = mServerMap.getById(entry.serverIf);
1810         if (app == null) return;
1811 
1812         switch(entry.type) {
1813             case HandleMap.TYPE_CHARACTERISTIC:
1814             {
1815                 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle);
1816                 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong,
1817                     serviceEntry.serviceType, serviceEntry.instance,
1818                     new ParcelUuid(serviceEntry.uuid), entry.instance,
1819                     new ParcelUuid(entry.uuid));
1820                 break;
1821             }
1822 
1823             case HandleMap.TYPE_DESCRIPTOR:
1824             {
1825                 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle);
1826                 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle);
1827                 app.callback.onDescriptorReadRequest(address, transId, offset, isLong,
1828                     serviceEntry.serviceType, serviceEntry.instance,
1829                     new ParcelUuid(serviceEntry.uuid), charEntry.instance,
1830                     new ParcelUuid(charEntry.uuid),
1831                     new ParcelUuid(entry.uuid));
1832                 break;
1833             }
1834 
1835             default:
1836                 Log.e(TAG, "onAttributeRead() - Requested unknown attribute type.");
1837                 break;
1838         }
1839     }
1840 
onAttributeWrite(String address, int connId, int transId, int attrHandle, int offset, int length, boolean needRsp, boolean isPrep, byte[] data)1841     void onAttributeWrite(String address, int connId, int transId,
1842                             int attrHandle, int offset, int length,
1843                             boolean needRsp, boolean isPrep,
1844                             byte[] data)
1845                             throws RemoteException {
1846         if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId
1847             + ", address=" + address + ", handle=" + attrHandle
1848             + ", requestId=" + transId + ", isPrep=" + isPrep
1849             + ", offset=" + offset);
1850 
1851         HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle);
1852         if (entry == null) return;
1853 
1854         mHandleMap.addRequest(transId, attrHandle);
1855 
1856         ServerMap.App app = mServerMap.getById(entry.serverIf);
1857         if (app == null) return;
1858 
1859         switch(entry.type) {
1860             case HandleMap.TYPE_CHARACTERISTIC:
1861             {
1862                 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle);
1863                 app.callback.onCharacteristicWriteRequest(address, transId,
1864                             offset, length, isPrep, needRsp,
1865                             serviceEntry.serviceType, serviceEntry.instance,
1866                             new ParcelUuid(serviceEntry.uuid), entry.instance,
1867                             new ParcelUuid(entry.uuid), data);
1868                 break;
1869             }
1870 
1871             case HandleMap.TYPE_DESCRIPTOR:
1872             {
1873                 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle);
1874                 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle);
1875                 app.callback.onDescriptorWriteRequest(address, transId,
1876                             offset, length, isPrep, needRsp,
1877                             serviceEntry.serviceType, serviceEntry.instance,
1878                             new ParcelUuid(serviceEntry.uuid), charEntry.instance,
1879                             new ParcelUuid(charEntry.uuid),
1880                             new ParcelUuid(entry.uuid), data);
1881                 break;
1882             }
1883 
1884             default:
1885                 Log.e(TAG, "onAttributeWrite() - Requested unknown attribute type.");
1886                 break;
1887         }
1888     }
1889 
onExecuteWrite(String address, int connId, int transId, int execWrite)1890     void onExecuteWrite(String address, int connId, int transId, int execWrite)
1891             throws RemoteException {
1892         if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId
1893             + ", address=" + address + ", transId=" + transId);
1894 
1895         ServerMap.App app = mServerMap.getByConnId(connId);
1896         if (app == null) return;
1897 
1898         app.callback.onExecuteWrite(address, transId, execWrite == 1);
1899     }
1900 
onResponseSendCompleted(int status, int attrHandle)1901     void onResponseSendCompleted(int status, int attrHandle) {
1902         if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle);
1903     }
1904 
onNotificationSent(int connId, int status)1905     void onNotificationSent(int connId, int status) throws RemoteException {
1906         if (VDBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status);
1907 
1908         String address = mServerMap.addressByConnId(connId);
1909         if (address == null) return;
1910 
1911         ServerMap.App app = mServerMap.getByConnId(connId);
1912         if (app == null) return;
1913 
1914         if (!app.isCongested) {
1915             app.callback.onNotificationSent(address, status);
1916         } else {
1917             if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
1918                 status = BluetoothGatt.GATT_SUCCESS;
1919             }
1920             app.queueCallback(new CallbackInfo(address, status));
1921         }
1922     }
1923 
onServerCongestion(int connId, boolean congested)1924     void onServerCongestion(int connId, boolean congested) throws RemoteException {
1925         if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested);
1926 
1927         ServerMap.App app = mServerMap.getByConnId(connId);
1928         if (app == null) return;
1929 
1930         app.isCongested = congested;
1931         while(!app.isCongested) {
1932             CallbackInfo callbackInfo = app.popQueuedCallback();
1933             if (callbackInfo == null) return;
1934             app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status);
1935         }
1936     }
1937 
onMtuChanged(int connId, int mtu)1938     void onMtuChanged(int connId, int mtu) throws RemoteException {
1939         if (DBG) Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu);
1940 
1941         String address = mServerMap.addressByConnId(connId);
1942         if (address == null) return;
1943 
1944         ServerMap.App app = mServerMap.getByConnId(connId);
1945         if (app == null) return;
1946 
1947         app.callback.onMtuChanged(address, mtu);
1948     }
1949 
1950     /**************************************************************************
1951      * GATT Service functions - SERVER
1952      *************************************************************************/
1953 
registerServer(UUID uuid, IBluetoothGattServerCallback callback)1954     void registerServer(UUID uuid, IBluetoothGattServerCallback callback) {
1955         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1956 
1957         if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid);
1958         mServerMap.add(uuid, callback);
1959         gattServerRegisterAppNative(uuid.getLeastSignificantBits(),
1960                                     uuid.getMostSignificantBits());
1961     }
1962 
unregisterServer(int serverIf)1963     void unregisterServer(int serverIf) {
1964         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1965 
1966         if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf);
1967 
1968         deleteServices(serverIf);
1969 
1970         mServerMap.remove(serverIf);
1971         gattServerUnregisterAppNative(serverIf);
1972     }
1973 
serverConnect(int serverIf, String address, boolean isDirect, int transport)1974     void serverConnect(int serverIf, String address, boolean isDirect, int transport) {
1975         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1976 
1977         if (DBG) Log.d(TAG, "serverConnect() - address=" + address);
1978         gattServerConnectNative(serverIf, address, isDirect,transport);
1979     }
1980 
serverDisconnect(int serverIf, String address)1981     void serverDisconnect(int serverIf, String address) {
1982         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1983 
1984         Integer connId = mServerMap.connIdByAddress(serverIf, address);
1985         if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId);
1986 
1987         gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0);
1988     }
1989 
beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, int minHandles, UUID srvcUuid, boolean advertisePreferred)1990     void beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId,
1991                                  int minHandles, UUID srvcUuid, boolean advertisePreferred) {
1992         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1993 
1994         if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid);
1995         ServiceDeclaration serviceDeclaration = addDeclaration();
1996         serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles,
1997             advertisePreferred);
1998     }
1999 
addIncludedService(int serverIf, int srvcType, int srvcInstanceId, UUID srvcUuid)2000     void addIncludedService(int serverIf, int srvcType, int srvcInstanceId,
2001                             UUID srvcUuid) {
2002         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2003 
2004         if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid);
2005         getActiveDeclaration().addIncludedService(srvcUuid, srvcType, srvcInstanceId);
2006     }
2007 
addCharacteristic(int serverIf, UUID charUuid, int properties, int permissions)2008     void addCharacteristic(int serverIf, UUID charUuid, int properties,
2009                            int permissions) {
2010         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2011 
2012         if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid);
2013         getActiveDeclaration().addCharacteristic(charUuid, properties, permissions);
2014     }
2015 
addDescriptor(int serverIf, UUID descUuid, int permissions)2016     void addDescriptor(int serverIf, UUID descUuid, int permissions) {
2017         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2018 
2019         if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid);
2020         getActiveDeclaration().addDescriptor(descUuid, permissions);
2021     }
2022 
endServiceDeclaration(int serverIf)2023     void endServiceDeclaration(int serverIf) {
2024         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2025 
2026         if (DBG) Log.d(TAG, "endServiceDeclaration()");
2027 
2028         if (getActiveDeclaration() == getPendingDeclaration()) {
2029             try {
2030                 continueServiceDeclaration(serverIf, (byte)0, 0);
2031             } catch (RemoteException e) {
2032                 Log.e(TAG,""+e);
2033             }
2034         }
2035     }
2036 
removeService(int serverIf, int srvcType, int srvcInstanceId, UUID srvcUuid)2037     void removeService(int serverIf, int srvcType,
2038                   int srvcInstanceId, UUID srvcUuid) {
2039         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2040 
2041         if (DBG) Log.d(TAG, "removeService() - uuid=" + srvcUuid);
2042 
2043         int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId);
2044         if (srvcHandle == 0) return;
2045         gattServerDeleteServiceNative(serverIf, srvcHandle);
2046     }
2047 
clearServices(int serverIf)2048     void clearServices(int serverIf) {
2049         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2050 
2051         if (DBG) Log.d(TAG, "clearServices()");
2052         deleteServices(serverIf);
2053     }
2054 
sendResponse(int serverIf, String address, int requestId, int status, int offset, byte[] value)2055     void sendResponse(int serverIf, String address, int requestId,
2056                       int status, int offset, byte[] value) {
2057         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2058 
2059         if (VDBG) Log.d(TAG, "sendResponse() - address=" + address);
2060 
2061         int handle = 0;
2062         HandleMap.Entry entry = mHandleMap.getByRequestId(requestId);
2063         if (entry != null) handle = entry.handle;
2064 
2065         int connId = mServerMap.connIdByAddress(serverIf, address);
2066         gattServerSendResponseNative(serverIf, connId, requestId, (byte)status,
2067                                      handle, offset, value, (byte)0);
2068         mHandleMap.deleteRequest(requestId);
2069     }
2070 
sendNotification(int serverIf, String address, int srvcType, int srvcInstanceId, UUID srvcUuid, int charInstanceId, UUID charUuid, boolean confirm, byte[] value)2071     void sendNotification(int serverIf, String address, int srvcType,
2072                                  int srvcInstanceId, UUID srvcUuid,
2073                                  int charInstanceId, UUID charUuid,
2074                                  boolean confirm, byte[] value) {
2075         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2076 
2077         if (VDBG) Log.d(TAG, "sendNotification() - address=" + address);
2078 
2079         int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId);
2080         if (srvcHandle == 0) return;
2081 
2082         int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId);
2083         if (charHandle == 0) return;
2084 
2085         int connId = mServerMap.connIdByAddress(serverIf, address);
2086         if (connId == 0) return;
2087 
2088         if (confirm) {
2089             gattServerSendIndicationNative(serverIf, charHandle, connId, value);
2090         } else {
2091             gattServerSendNotificationNative(serverIf, charHandle, connId, value);
2092         }
2093     }
2094 
2095 
2096     /**************************************************************************
2097      * Private functions
2098      *************************************************************************/
2099 
isHidUuid(final UUID uuid)2100     private boolean isHidUuid(final UUID uuid) {
2101         for (UUID hid_uuid : HID_UUIDS) {
2102             if (hid_uuid.equals(uuid)) return true;
2103         }
2104         return false;
2105     }
2106 
getDeviceType(BluetoothDevice device)2107     private int getDeviceType(BluetoothDevice device) {
2108         int type = gattClientGetDeviceTypeNative(device.getAddress());
2109         if (DBG) Log.d(TAG, "getDeviceType() - device=" + device
2110             + ", type=" + type);
2111         return type;
2112     }
2113 
enforceAdminPermission()2114     private void enforceAdminPermission() {
2115         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
2116     }
2117 
needsPrivilegedPermissionForScan(ScanSettings settings)2118     private boolean needsPrivilegedPermissionForScan(ScanSettings settings) {
2119         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
2120         // BLE scan only mode needs special permission.
2121         if (adapter.getState() != BluetoothAdapter.STATE_ON) return true;
2122 
2123         // Regular scan, no special permission.
2124         if (settings == null) return false;
2125 
2126         // Regular scan, no special permission.
2127         if (settings.getReportDelayMillis() == 0) return false;
2128 
2129         // Batch scan, truncated mode needs permission.
2130         return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED;
2131     }
2132 
2133     // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be
2134     // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission.
enforcePrivilegedPermission()2135     private void enforcePrivilegedPermission() {
2136         enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
2137             "Need BLUETOOTH_PRIVILEGED permission");
2138     }
2139 
continueSearch(int connId, int status)2140     private void continueSearch(int connId, int status) throws RemoteException {
2141         if (status == 0 && !mSearchQueue.isEmpty()) {
2142             SearchQueue.Entry svc = mSearchQueue.pop();
2143 
2144             if (svc.charUuidLsb == 0) {
2145                 // Characteristic is up next
2146                 gattClientGetCharacteristicNative(svc.connId, svc.srvcType,
2147                     svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb, 0, 0, 0);
2148             } else {
2149                 // Descriptor is up next
2150                 gattClientGetDescriptorNative(svc.connId, svc.srvcType,
2151                     svc.srvcInstId, svc.srvcUuidLsb, svc.srvcUuidMsb,
2152                     svc.charInstId, svc.charUuidLsb, svc.charUuidMsb, 0, 0, 0);
2153             }
2154         } else {
2155             ClientMap.App app = mClientMap.getByConnId(connId);
2156             if (app != null) {
2157                 app.callback.onSearchComplete(mClientMap.addressByConnId(connId), status);
2158             }
2159         }
2160     }
2161 
continueServiceDeclaration(int serverIf, int status, int srvcHandle)2162     private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException {
2163         if (mServiceDeclarations.size() == 0) return;
2164         if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle);
2165 
2166         boolean finished = false;
2167 
2168         ServiceDeclaration.Entry entry = null;
2169         if (status == 0)
2170             entry = getPendingDeclaration().getNext();
2171 
2172         if (entry != null) {
2173             if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type="
2174                 + entry.type);
2175             switch(entry.type) {
2176                 case ServiceDeclaration.TYPE_SERVICE:
2177                     if (entry.advertisePreferred) {
2178                         mAdvertisingServiceUuids.add(entry.uuid);
2179                     }
2180                     gattServerAddServiceNative(serverIf, entry.serviceType,
2181                         entry.instance,
2182                         entry.uuid.getLeastSignificantBits(),
2183                         entry.uuid.getMostSignificantBits(),
2184                         getPendingDeclaration().getNumHandles());
2185                     break;
2186 
2187                 case ServiceDeclaration.TYPE_CHARACTERISTIC:
2188                     gattServerAddCharacteristicNative(serverIf, srvcHandle,
2189                         entry.uuid.getLeastSignificantBits(),
2190                         entry.uuid.getMostSignificantBits(),
2191                         entry.properties, entry.permissions);
2192                     break;
2193 
2194                 case ServiceDeclaration.TYPE_DESCRIPTOR:
2195                     gattServerAddDescriptorNative(serverIf, srvcHandle,
2196                         entry.uuid.getLeastSignificantBits(),
2197                         entry.uuid.getMostSignificantBits(),
2198                         entry.permissions);
2199                     break;
2200 
2201                 case ServiceDeclaration.TYPE_INCLUDED_SERVICE:
2202                 {
2203                     int inclSrvc = mHandleMap.getServiceHandle(entry.uuid,
2204                                             entry.serviceType, entry.instance);
2205                     if (inclSrvc != 0) {
2206                         gattServerAddIncludedServiceNative(serverIf, srvcHandle,
2207                                                            inclSrvc);
2208                     } else {
2209                         finished = true;
2210                     }
2211                     break;
2212                 }
2213             }
2214         } else {
2215             gattServerStartServiceNative(serverIf, srvcHandle,
2216                 (byte)BluetoothDevice.TRANSPORT_BREDR | BluetoothDevice.TRANSPORT_LE);
2217             finished = true;
2218         }
2219 
2220         if (finished) {
2221             if (DBG) Log.d(TAG, "continueServiceDeclaration() - completed.");
2222             ServerMap.App app = mServerMap.getById(serverIf);
2223             if (app != null) {
2224                 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(srvcHandle);
2225 
2226                 if (serviceEntry != null) {
2227                     app.callback.onServiceAdded(status, serviceEntry.serviceType,
2228                         serviceEntry.instance, new ParcelUuid(serviceEntry.uuid));
2229                 } else {
2230                     app.callback.onServiceAdded(status, 0, 0, null);
2231                 }
2232             }
2233             removePendingDeclaration();
2234 
2235             if (getPendingDeclaration() != null) {
2236                 continueServiceDeclaration(serverIf, (byte)0, 0);
2237             }
2238         }
2239     }
2240 
stopNextService(int serverIf, int status)2241     private void stopNextService(int serverIf, int status) throws RemoteException {
2242         if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf
2243             + ", status=" + status);
2244 
2245         if (status == 0) {
2246             List<HandleMap.Entry> entries = mHandleMap.getEntries();
2247             for(HandleMap.Entry entry : entries) {
2248                 if (entry.type != HandleMap.TYPE_SERVICE ||
2249                     entry.serverIf != serverIf ||
2250                     entry.started == false)
2251                         continue;
2252 
2253                 gattServerStopServiceNative(serverIf, entry.handle);
2254                 return;
2255             }
2256         }
2257     }
2258 
deleteServices(int serverIf)2259     private void deleteServices(int serverIf) {
2260         if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf);
2261 
2262         /*
2263          * Figure out which handles to delete.
2264          * The handles are copied into a new list to avoid race conditions.
2265          */
2266         List<Integer> handleList = new ArrayList<Integer>();
2267         List<HandleMap.Entry> entries = mHandleMap.getEntries();
2268         for(HandleMap.Entry entry : entries) {
2269             if (entry.type != HandleMap.TYPE_SERVICE ||
2270                 entry.serverIf != serverIf)
2271                     continue;
2272             handleList.add(entry.handle);
2273         }
2274 
2275         /* Now actually delete the services.... */
2276         for(Integer handle : handleList) {
2277             gattServerDeleteServiceNative(serverIf, handle);
2278         }
2279     }
2280 
parseUuids(byte[] adv_data)2281     private List<UUID> parseUuids(byte[] adv_data) {
2282         List<UUID> uuids = new ArrayList<UUID>();
2283 
2284         int offset = 0;
2285         while(offset < (adv_data.length-2)) {
2286             int len = adv_data[offset++];
2287             if (len == 0) break;
2288 
2289             int type = adv_data[offset++];
2290             switch (type) {
2291                 case 0x02: // Partial list of 16-bit UUIDs
2292                 case 0x03: // Complete list of 16-bit UUIDs
2293                     while (len > 1) {
2294                         int uuid16 = adv_data[offset++];
2295                         uuid16 += (adv_data[offset++] << 8);
2296                         len -= 2;
2297                         uuids.add(UUID.fromString(String.format(
2298                             "%08x-0000-1000-8000-00805f9b34fb", uuid16)));
2299                     }
2300                     break;
2301 
2302                 default:
2303                     offset += (len - 1);
2304                     break;
2305             }
2306         }
2307 
2308         return uuids;
2309     }
2310 
2311     @Override
dump(StringBuilder sb)2312     public void dump(StringBuilder sb) {
2313         super.dump(sb);
2314         println(sb, "mAdvertisingServiceUuids:");
2315         for (UUID uuid : mAdvertisingServiceUuids) {
2316             println(sb, "  " + uuid);
2317         }
2318         for (ServiceDeclaration declaration : mServiceDeclarations) {
2319             println(sb, "  " + declaration);
2320         }
2321         println(sb, "mMaxScanFilters: " + mMaxScanFilters);
2322 
2323         sb.append("\nGATT Client Map\n");
2324         mClientMap.dump(sb);
2325 
2326         sb.append("\nGATT Server Map\n");
2327         mServerMap.dump(sb);
2328 
2329         sb.append("\nGATT Handle Map\n");
2330         mHandleMap.dump(sb);
2331     }
2332 
2333     /**************************************************************************
2334      * GATT Test functions
2335      *************************************************************************/
2336 
gattTestCommand(int command, UUID uuid1, String bda1, int p1, int p2, int p3, int p4, int p5)2337     void gattTestCommand(int command, UUID uuid1, String bda1,
2338                          int p1, int p2, int p3, int p4, int p5) {
2339         if (bda1 == null) bda1 = "00:00:00:00:00:00";
2340         if (uuid1 != null)
2341             gattTestNative(command, uuid1.getLeastSignificantBits(),
2342                        uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5);
2343         else
2344             gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5);
2345     }
2346 
gattTestNative(int command, long uuid1_lsb, long uuid1_msb, String bda1, int p1, int p2, int p3, int p4, int p5)2347     private native void gattTestNative(int command,
2348                                     long uuid1_lsb, long uuid1_msb, String bda1,
2349                                     int p1, int p2, int p3, int p4, int p5);
2350 
2351     /**************************************************************************
2352      * Native functions prototypes
2353      *************************************************************************/
2354 
classInitNative()2355     private native static void classInitNative();
initializeNative()2356     private native void initializeNative();
cleanupNative()2357     private native void cleanupNative();
2358 
gattClientGetDeviceTypeNative(String address)2359     private native int gattClientGetDeviceTypeNative(String address);
2360 
gattClientRegisterAppNative(long app_uuid_lsb, long app_uuid_msb)2361     private native void gattClientRegisterAppNative(long app_uuid_lsb,
2362                                                     long app_uuid_msb);
2363 
gattClientUnregisterAppNative(int clientIf)2364     private native void gattClientUnregisterAppNative(int clientIf);
2365 
gattClientConnectNative(int clientIf, String address, boolean isDirect, int transport)2366     private native void gattClientConnectNative(int clientIf, String address,
2367             boolean isDirect, int transport);
2368 
gattClientDisconnectNative(int clientIf, String address, int conn_id)2369     private native void gattClientDisconnectNative(int clientIf, String address,
2370             int conn_id);
2371 
gattClientRefreshNative(int clientIf, String address)2372     private native void gattClientRefreshNative(int clientIf, String address);
2373 
gattClientSearchServiceNative(int conn_id, boolean search_all, long service_uuid_lsb, long service_uuid_msb)2374     private native void gattClientSearchServiceNative(int conn_id,
2375             boolean search_all, long service_uuid_lsb, long service_uuid_msb);
2376 
gattClientGetCharacteristicNative(int conn_id, int service_type, int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb)2377     private native void gattClientGetCharacteristicNative(int conn_id,
2378             int service_type, int service_id_inst_id, long service_id_uuid_lsb,
2379             long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb,
2380             long char_id_uuid_msb);
2381 
gattClientGetDescriptorNative(int conn_id, int service_type, int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb)2382     private native void gattClientGetDescriptorNative(int conn_id, int service_type,
2383             int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb,
2384             int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb,
2385             int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb);
2386 
gattClientGetIncludedServiceNative(int conn_id, int service_type, int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, int incl_service_id_inst_id, int incl_service_type, long incl_service_id_uuid_lsb, long incl_service_id_uuid_msb)2387     private native void gattClientGetIncludedServiceNative(int conn_id,
2388             int service_type, int service_id_inst_id,
2389             long service_id_uuid_lsb, long service_id_uuid_msb,
2390             int incl_service_id_inst_id, int incl_service_type,
2391             long incl_service_id_uuid_lsb, long incl_service_id_uuid_msb);
2392 
gattClientReadCharacteristicNative(int conn_id, int service_type, int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, int authReq)2393     private native void gattClientReadCharacteristicNative(int conn_id,
2394             int service_type, int service_id_inst_id, long service_id_uuid_lsb,
2395             long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb,
2396             long char_id_uuid_msb, int authReq);
2397 
gattClientReadDescriptorNative(int conn_id, int service_type, int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, int authReq)2398     private native void gattClientReadDescriptorNative(int conn_id, int service_type,
2399             int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb,
2400             int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb,
2401             int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb,
2402             int authReq);
2403 
gattClientWriteCharacteristicNative(int conn_id, int service_type, int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, int write_type, int auth_req, byte[] value)2404     private native void gattClientWriteCharacteristicNative(int conn_id,
2405             int service_type, int service_id_inst_id, long service_id_uuid_lsb,
2406             long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb,
2407             long char_id_uuid_msb, int write_type, int auth_req, byte[] value);
2408 
gattClientWriteDescriptorNative(int conn_id, int service_type, int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb, int write_type, int auth_req, byte[] value)2409     private native void gattClientWriteDescriptorNative(int conn_id, int service_type,
2410             int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb,
2411             int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb,
2412             int descr_id_inst_id, long descr_id_uuid_lsb, long descr_id_uuid_msb,
2413             int write_type, int auth_req, byte[] value);
2414 
gattClientExecuteWriteNative(int conn_id, boolean execute)2415     private native void gattClientExecuteWriteNative(int conn_id, boolean execute);
2416 
gattClientRegisterForNotificationsNative(int clientIf, String address, int service_type, int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb, boolean enable)2417     private native void gattClientRegisterForNotificationsNative(int clientIf,
2418             String address, int service_type, int service_id_inst_id,
2419             long service_id_uuid_lsb, long service_id_uuid_msb,
2420             int char_id_inst_id, long char_id_uuid_lsb, long char_id_uuid_msb,
2421             boolean enable);
2422 
gattClientReadRemoteRssiNative(int clientIf, String address)2423     private native void gattClientReadRemoteRssiNative(int clientIf,
2424             String address);
2425 
gattClientConfigureMTUNative(int conn_id, int mtu)2426     private native void gattClientConfigureMTUNative(int conn_id, int mtu);
2427 
gattConnectionParameterUpdateNative(int client_if, String address, int minInterval, int maxInterval, int latency, int timeout)2428     private native void gattConnectionParameterUpdateNative(int client_if, String address,
2429             int minInterval, int maxInterval, int latency, int timeout);
2430 
gattServerRegisterAppNative(long app_uuid_lsb, long app_uuid_msb)2431     private native void gattServerRegisterAppNative(long app_uuid_lsb,
2432                                                     long app_uuid_msb);
2433 
gattServerUnregisterAppNative(int serverIf)2434     private native void gattServerUnregisterAppNative(int serverIf);
2435 
gattServerConnectNative(int server_if, String address, boolean is_direct, int transport)2436     private native void gattServerConnectNative(int server_if, String address,
2437                                              boolean is_direct, int transport);
2438 
gattServerDisconnectNative(int serverIf, String address, int conn_id)2439     private native void gattServerDisconnectNative(int serverIf, String address,
2440                                               int conn_id);
2441 
gattServerAddServiceNative(int server_if, int service_type, int service_id_inst_id, long service_id_uuid_lsb, long service_id_uuid_msb, int num_handles)2442     private native void gattServerAddServiceNative (int server_if,
2443             int service_type, int service_id_inst_id,
2444             long service_id_uuid_lsb, long service_id_uuid_msb,
2445             int num_handles);
2446 
gattServerAddIncludedServiceNative(int server_if, int svc_handle, int included_svc_handle)2447     private native void gattServerAddIncludedServiceNative (int server_if,
2448             int svc_handle, int included_svc_handle);
2449 
gattServerAddCharacteristicNative(int server_if, int svc_handle, long char_uuid_lsb, long char_uuid_msb, int properties, int permissions)2450     private native void gattServerAddCharacteristicNative (int server_if,
2451             int svc_handle, long char_uuid_lsb, long char_uuid_msb,
2452             int properties, int permissions);
2453 
gattServerAddDescriptorNative(int server_if, int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, int permissions)2454     private native void gattServerAddDescriptorNative (int server_if,
2455             int svc_handle, long desc_uuid_lsb, long desc_uuid_msb,
2456             int permissions);
2457 
gattServerStartServiceNative(int server_if, int svc_handle, int transport )2458     private native void gattServerStartServiceNative (int server_if,
2459             int svc_handle, int transport );
2460 
gattServerStopServiceNative(int server_if, int svc_handle)2461     private native void gattServerStopServiceNative (int server_if,
2462                                                      int svc_handle);
2463 
gattServerDeleteServiceNative(int server_if, int svc_handle)2464     private native void gattServerDeleteServiceNative (int server_if,
2465                                                        int svc_handle);
2466 
gattServerSendIndicationNative(int server_if, int attr_handle, int conn_id, byte[] val)2467     private native void gattServerSendIndicationNative (int server_if,
2468             int attr_handle, int conn_id, byte[] val);
2469 
gattServerSendNotificationNative(int server_if, int attr_handle, int conn_id, byte[] val)2470     private native void gattServerSendNotificationNative (int server_if,
2471             int attr_handle, int conn_id, byte[] val);
2472 
gattServerSendResponseNative(int server_if, int conn_id, int trans_id, int status, int handle, int offset, byte[] val, int auth_req)2473     private native void gattServerSendResponseNative (int server_if,
2474             int conn_id, int trans_id, int status, int handle, int offset,
2475             byte[] val, int auth_req);
2476 }
2477