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