• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.bluetooth.gatt;
18 
19 import android.app.AppOpsManager;
20 import android.app.Service;
21 import android.bluetooth.BluetoothAdapter;
22 import android.bluetooth.BluetoothDevice;
23 import android.bluetooth.BluetoothGatt;
24 import android.bluetooth.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         int minInterval;
1598         int maxInterval;
1599 
1600         // Slave latency
1601         int latency;
1602 
1603         // Link supervision timeout is measured in N * 10ms
1604         int timeout = 2000; // 20s
1605 
1606         switch (connectionPriority)
1607         {
1608             case BluetoothGatt.CONNECTION_PRIORITY_HIGH:
1609                 minInterval = getResources().getInteger(R.integer.gatt_high_priority_min_interval);
1610                 maxInterval = getResources().getInteger(R.integer.gatt_high_priority_max_interval);
1611                 latency = getResources().getInteger(R.integer.gatt_high_priority_latency);
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 = getResources().getInteger(R.integer.gatt_low_power_latency);
1618                 break;
1619 
1620             default:
1621                 // Using the values for CONNECTION_PRIORITY_BALANCED.
1622                 minInterval =
1623                         getResources().getInteger(R.integer.gatt_balanced_priority_min_interval);
1624                 maxInterval =
1625                         getResources().getInteger(R.integer.gatt_balanced_priority_max_interval);
1626                 latency = getResources().getInteger(R.integer.gatt_balanced_priority_latency);
1627                 break;
1628         }
1629 
1630         if (DBG) Log.d(TAG, "connectionParameterUpdate() - address=" + address
1631             + "params=" + connectionPriority + " interval=" + minInterval + "/" + maxInterval);
1632         gattConnectionParameterUpdateNative(clientIf, address, minInterval, maxInterval,
1633                                             latency, timeout);
1634     }
1635 
1636     /**************************************************************************
1637      * Callback functions - SERVER
1638      *************************************************************************/
1639 
onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb)1640     void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb)
1641             throws RemoteException {
1642 
1643         UUID uuid = new UUID(uuidMsb, uuidLsb);
1644         if (DBG) Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf);
1645         ServerMap.App app = mServerMap.getByUuid(uuid);
1646         if (app != null) {
1647             app.id = serverIf;
1648             app.linkToDeath(new ServerDeathRecipient(serverIf));
1649             app.callback.onServerRegistered(status, serverIf);
1650         }
1651     }
1652 
onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId, long srvcUuidLsb, long srvcUuidMsb, int srvcHandle)1653     void onServiceAdded(int status, int serverIf, int srvcType, int srvcInstId,
1654                         long srvcUuidLsb, long srvcUuidMsb, int srvcHandle)
1655                         throws RemoteException {
1656         UUID uuid = new UUID(srvcUuidMsb, srvcUuidLsb);
1657         if (DBG) Log.d(TAG, "onServiceAdded() UUID=" + uuid + ", status=" + status
1658             + ", handle=" + srvcHandle);
1659         if (status == 0) {
1660             mHandleMap.addService(serverIf, srvcHandle, uuid, srvcType, srvcInstId,
1661                 mAdvertisingServiceUuids.remove(uuid));
1662         }
1663 
1664         continueServiceDeclaration(serverIf, status, srvcHandle);
1665     }
1666 
onIncludedServiceAdded(int status, int serverIf, int srvcHandle, int includedSrvcHandle)1667     void onIncludedServiceAdded(int status, int serverIf, int srvcHandle,
1668                                 int includedSrvcHandle) throws RemoteException {
1669         if (DBG) Log.d(TAG, "onIncludedServiceAdded() status=" + status
1670             + ", service=" + srvcHandle + ", included=" + includedSrvcHandle);
1671         continueServiceDeclaration(serverIf, status, srvcHandle);
1672     }
1673 
onCharacteristicAdded(int status, int serverIf, long charUuidLsb, long charUuidMsb, int srvcHandle, int charHandle)1674     void onCharacteristicAdded(int status, int serverIf,
1675                                long charUuidLsb, long charUuidMsb,
1676                                int srvcHandle, int charHandle)
1677                                throws RemoteException {
1678             UUID uuid = new UUID(charUuidMsb, charUuidLsb);
1679         if (DBG) Log.d(TAG, "onCharacteristicAdded() UUID=" + uuid + ", status=" + status
1680             + ", srvcHandle=" + srvcHandle + ", charHandle=" + charHandle);
1681         if (status == 0)
1682             mHandleMap.addCharacteristic(serverIf, charHandle, uuid, srvcHandle);
1683         continueServiceDeclaration(serverIf, status, srvcHandle);
1684     }
1685 
onDescriptorAdded(int status, int serverIf, long descrUuidLsb, long descrUuidMsb, int srvcHandle, int descrHandle)1686     void onDescriptorAdded(int status, int serverIf,
1687                            long descrUuidLsb, long descrUuidMsb,
1688                            int srvcHandle, int descrHandle)
1689                            throws RemoteException {
1690             UUID uuid = new UUID(descrUuidMsb, descrUuidLsb);
1691         if (DBG) Log.d(TAG, "onDescriptorAdded() UUID=" + uuid + ", status=" + status
1692             + ", srvcHandle=" + srvcHandle + ", descrHandle=" + descrHandle);
1693         if (status == 0)
1694             mHandleMap.addDescriptor(serverIf, descrHandle, uuid, srvcHandle);
1695         continueServiceDeclaration(serverIf, status, srvcHandle);
1696     }
1697 
onServiceStarted(int status, int serverIf, int srvcHandle)1698     void onServiceStarted(int status, int serverIf, int srvcHandle)
1699             throws RemoteException {
1700         if (DBG) Log.d(TAG, "onServiceStarted() srvcHandle=" + srvcHandle
1701             + ", status=" + status);
1702         if (status == 0)
1703             mHandleMap.setStarted(serverIf, srvcHandle, true);
1704     }
1705 
onServiceStopped(int status, int serverIf, int srvcHandle)1706     void onServiceStopped(int status, int serverIf, int srvcHandle)
1707             throws RemoteException {
1708         if (DBG) Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle
1709             + ", status=" + status);
1710         if (status == 0)
1711             mHandleMap.setStarted(serverIf, srvcHandle, false);
1712         stopNextService(serverIf, status);
1713     }
1714 
onServiceDeleted(int status, int serverIf, int srvcHandle)1715     void onServiceDeleted(int status, int serverIf, int srvcHandle) {
1716         if (DBG) Log.d(TAG, "onServiceDeleted() srvcHandle=" + srvcHandle
1717             + ", status=" + status);
1718         mHandleMap.deleteService(serverIf, srvcHandle);
1719     }
1720 
onClientConnected(String address, boolean connected, int connId, int serverIf)1721     void onClientConnected(String address, boolean connected, int connId, int serverIf)
1722             throws RemoteException {
1723 
1724         if (DBG) Log.d(TAG, "onConnected() connId=" + connId
1725             + ", address=" + address + ", connected=" + connected);
1726 
1727         ServerMap.App app = mServerMap.getById(serverIf);
1728         if (app == null) return;
1729 
1730         if (connected) {
1731             mServerMap.addConnection(serverIf, connId, address);
1732         } else {
1733             mServerMap.removeConnection(serverIf, connId);
1734         }
1735 
1736         app.callback.onServerConnectionState((byte)0, serverIf, connected, address);
1737     }
1738 
onAttributeRead(String address, int connId, int transId, int attrHandle, int offset, boolean isLong)1739     void onAttributeRead(String address, int connId, int transId,
1740                             int attrHandle, int offset, boolean isLong)
1741                             throws RemoteException {
1742         if (VDBG) Log.d(TAG, "onAttributeRead() connId=" + connId
1743             + ", address=" + address + ", handle=" + attrHandle
1744             + ", requestId=" + transId + ", offset=" + offset);
1745 
1746         HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle);
1747         if (entry == null) return;
1748 
1749         mHandleMap.addRequest(transId, attrHandle);
1750 
1751         ServerMap.App app = mServerMap.getById(entry.serverIf);
1752         if (app == null) return;
1753 
1754         switch(entry.type) {
1755             case HandleMap.TYPE_CHARACTERISTIC:
1756             {
1757                 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle);
1758                 app.callback.onCharacteristicReadRequest(address, transId, offset, isLong,
1759                     serviceEntry.serviceType, serviceEntry.instance,
1760                     new ParcelUuid(serviceEntry.uuid), entry.instance,
1761                     new ParcelUuid(entry.uuid));
1762                 break;
1763             }
1764 
1765             case HandleMap.TYPE_DESCRIPTOR:
1766             {
1767                 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle);
1768                 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle);
1769                 app.callback.onDescriptorReadRequest(address, transId, offset, isLong,
1770                     serviceEntry.serviceType, serviceEntry.instance,
1771                     new ParcelUuid(serviceEntry.uuid), charEntry.instance,
1772                     new ParcelUuid(charEntry.uuid),
1773                     new ParcelUuid(entry.uuid));
1774                 break;
1775             }
1776 
1777             default:
1778                 Log.e(TAG, "onAttributeRead() - Requested unknown attribute type.");
1779                 break;
1780         }
1781     }
1782 
onAttributeWrite(String address, int connId, int transId, int attrHandle, int offset, int length, boolean needRsp, boolean isPrep, byte[] data)1783     void onAttributeWrite(String address, int connId, int transId,
1784                             int attrHandle, int offset, int length,
1785                             boolean needRsp, boolean isPrep,
1786                             byte[] data)
1787                             throws RemoteException {
1788         if (VDBG) Log.d(TAG, "onAttributeWrite() connId=" + connId
1789             + ", address=" + address + ", handle=" + attrHandle
1790             + ", requestId=" + transId + ", isPrep=" + isPrep
1791             + ", offset=" + offset);
1792 
1793         HandleMap.Entry entry = mHandleMap.getByHandle(attrHandle);
1794         if (entry == null) return;
1795 
1796         mHandleMap.addRequest(transId, attrHandle);
1797 
1798         ServerMap.App app = mServerMap.getById(entry.serverIf);
1799         if (app == null) return;
1800 
1801         switch(entry.type) {
1802             case HandleMap.TYPE_CHARACTERISTIC:
1803             {
1804                 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle);
1805                 app.callback.onCharacteristicWriteRequest(address, transId,
1806                             offset, length, isPrep, needRsp,
1807                             serviceEntry.serviceType, serviceEntry.instance,
1808                             new ParcelUuid(serviceEntry.uuid), entry.instance,
1809                             new ParcelUuid(entry.uuid), data);
1810                 break;
1811             }
1812 
1813             case HandleMap.TYPE_DESCRIPTOR:
1814             {
1815                 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(entry.serviceHandle);
1816                 HandleMap.Entry charEntry = mHandleMap.getByHandle(entry.charHandle);
1817                 app.callback.onDescriptorWriteRequest(address, transId,
1818                             offset, length, isPrep, needRsp,
1819                             serviceEntry.serviceType, serviceEntry.instance,
1820                             new ParcelUuid(serviceEntry.uuid), charEntry.instance,
1821                             new ParcelUuid(charEntry.uuid),
1822                             new ParcelUuid(entry.uuid), data);
1823                 break;
1824             }
1825 
1826             default:
1827                 Log.e(TAG, "onAttributeWrite() - Requested unknown attribute type.");
1828                 break;
1829         }
1830     }
1831 
onExecuteWrite(String address, int connId, int transId, int execWrite)1832     void onExecuteWrite(String address, int connId, int transId, int execWrite)
1833             throws RemoteException {
1834         if (DBG) Log.d(TAG, "onExecuteWrite() connId=" + connId
1835             + ", address=" + address + ", transId=" + transId);
1836 
1837         ServerMap.App app = mServerMap.getByConnId(connId);
1838         if (app == null) return;
1839 
1840         app.callback.onExecuteWrite(address, transId, execWrite == 1);
1841     }
1842 
onResponseSendCompleted(int status, int attrHandle)1843     void onResponseSendCompleted(int status, int attrHandle) {
1844         if (DBG) Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle);
1845     }
1846 
onNotificationSent(int connId, int status)1847     void onNotificationSent(int connId, int status) throws RemoteException {
1848         if (VDBG) Log.d(TAG, "onNotificationSent() connId=" + connId + ", status=" + status);
1849 
1850         String address = mServerMap.addressByConnId(connId);
1851         if (address == null) return;
1852 
1853         ServerMap.App app = mServerMap.getByConnId(connId);
1854         if (app == null) return;
1855 
1856         if (!app.isCongested) {
1857             app.callback.onNotificationSent(address, status);
1858         } else {
1859             if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
1860                 status = BluetoothGatt.GATT_SUCCESS;
1861             }
1862             app.queueCallback(new CallbackInfo(address, status));
1863         }
1864     }
1865 
onServerCongestion(int connId, boolean congested)1866     void onServerCongestion(int connId, boolean congested) throws RemoteException {
1867         if (DBG) Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested);
1868 
1869         ServerMap.App app = mServerMap.getByConnId(connId);
1870         if (app == null) return;
1871 
1872         app.isCongested = congested;
1873         while(!app.isCongested) {
1874             CallbackInfo callbackInfo = app.popQueuedCallback();
1875             if (callbackInfo == null) return;
1876             app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status);
1877         }
1878     }
1879 
onMtuChanged(int connId, int mtu)1880     void onMtuChanged(int connId, int mtu) throws RemoteException {
1881         if (DBG) Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu);
1882 
1883         String address = mServerMap.addressByConnId(connId);
1884         if (address == null) return;
1885 
1886         ServerMap.App app = mServerMap.getByConnId(connId);
1887         if (app == null) return;
1888 
1889         app.callback.onMtuChanged(address, mtu);
1890     }
1891 
1892     /**************************************************************************
1893      * GATT Service functions - SERVER
1894      *************************************************************************/
1895 
registerServer(UUID uuid, IBluetoothGattServerCallback callback)1896     void registerServer(UUID uuid, IBluetoothGattServerCallback callback) {
1897         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1898 
1899         if (DBG) Log.d(TAG, "registerServer() - UUID=" + uuid);
1900         mServerMap.add(uuid, callback, this);
1901         gattServerRegisterAppNative(uuid.getLeastSignificantBits(),
1902                                     uuid.getMostSignificantBits());
1903     }
1904 
unregisterServer(int serverIf)1905     void unregisterServer(int serverIf) {
1906         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1907 
1908         if (DBG) Log.d(TAG, "unregisterServer() - serverIf=" + serverIf);
1909 
1910         deleteServices(serverIf);
1911 
1912         mServerMap.remove(serverIf);
1913         gattServerUnregisterAppNative(serverIf);
1914     }
1915 
serverConnect(int serverIf, String address, boolean isDirect, int transport)1916     void serverConnect(int serverIf, String address, boolean isDirect, int transport) {
1917         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1918 
1919         if (DBG) Log.d(TAG, "serverConnect() - address=" + address);
1920         gattServerConnectNative(serverIf, address, isDirect,transport);
1921     }
1922 
serverDisconnect(int serverIf, String address)1923     void serverDisconnect(int serverIf, String address) {
1924         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1925 
1926         Integer connId = mServerMap.connIdByAddress(serverIf, address);
1927         if (DBG) Log.d(TAG, "serverDisconnect() - address=" + address + ", connId=" + connId);
1928 
1929         gattServerDisconnectNative(serverIf, address, connId != null ? connId : 0);
1930     }
1931 
beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId, int minHandles, UUID srvcUuid, boolean advertisePreferred)1932     void beginServiceDeclaration(int serverIf, int srvcType, int srvcInstanceId,
1933                                  int minHandles, UUID srvcUuid, boolean advertisePreferred) {
1934         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1935 
1936         if (DBG) Log.d(TAG, "beginServiceDeclaration() - uuid=" + srvcUuid);
1937         ServiceDeclaration serviceDeclaration = addDeclaration();
1938         serviceDeclaration.addService(srvcUuid, srvcType, srvcInstanceId, minHandles,
1939             advertisePreferred);
1940     }
1941 
addIncludedService(int serverIf, int srvcType, int srvcInstanceId, UUID srvcUuid)1942     void addIncludedService(int serverIf, int srvcType, int srvcInstanceId,
1943                             UUID srvcUuid) {
1944         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1945 
1946         if (DBG) Log.d(TAG, "addIncludedService() - uuid=" + srvcUuid);
1947         getActiveDeclaration().addIncludedService(srvcUuid, srvcType, srvcInstanceId);
1948     }
1949 
addCharacteristic(int serverIf, UUID charUuid, int properties, int permissions)1950     void addCharacteristic(int serverIf, UUID charUuid, int properties,
1951                            int permissions) {
1952         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1953 
1954         if (DBG) Log.d(TAG, "addCharacteristic() - uuid=" + charUuid);
1955         getActiveDeclaration().addCharacteristic(charUuid, properties, permissions);
1956     }
1957 
addDescriptor(int serverIf, UUID descUuid, int permissions)1958     void addDescriptor(int serverIf, UUID descUuid, int permissions) {
1959         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1960 
1961         if (DBG) Log.d(TAG, "addDescriptor() - uuid=" + descUuid);
1962         getActiveDeclaration().addDescriptor(descUuid, permissions);
1963     }
1964 
endServiceDeclaration(int serverIf)1965     void endServiceDeclaration(int serverIf) {
1966         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1967 
1968         if (DBG) Log.d(TAG, "endServiceDeclaration()");
1969 
1970         if (getActiveDeclaration() == getPendingDeclaration()) {
1971             try {
1972                 continueServiceDeclaration(serverIf, (byte)0, 0);
1973             } catch (RemoteException e) {
1974                 Log.e(TAG,""+e);
1975             }
1976         }
1977     }
1978 
removeService(int serverIf, int srvcType, int srvcInstanceId, UUID srvcUuid)1979     void removeService(int serverIf, int srvcType,
1980                   int srvcInstanceId, UUID srvcUuid) {
1981         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1982 
1983         if (DBG) Log.d(TAG, "removeService() - uuid=" + srvcUuid);
1984 
1985         int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId);
1986         if (srvcHandle == 0) return;
1987         gattServerDeleteServiceNative(serverIf, srvcHandle);
1988     }
1989 
clearServices(int serverIf)1990     void clearServices(int serverIf) {
1991         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
1992 
1993         if (DBG) Log.d(TAG, "clearServices()");
1994         deleteServices(serverIf);
1995     }
1996 
sendResponse(int serverIf, String address, int requestId, int status, int offset, byte[] value)1997     void sendResponse(int serverIf, String address, int requestId,
1998                       int status, int offset, byte[] value) {
1999         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2000 
2001         if (VDBG) Log.d(TAG, "sendResponse() - address=" + address);
2002 
2003         int handle = 0;
2004         HandleMap.Entry entry = mHandleMap.getByRequestId(requestId);
2005         if (entry != null) handle = entry.handle;
2006 
2007         int connId = mServerMap.connIdByAddress(serverIf, address);
2008         gattServerSendResponseNative(serverIf, connId, requestId, (byte)status,
2009                                      handle, offset, value, (byte)0);
2010         mHandleMap.deleteRequest(requestId);
2011     }
2012 
sendNotification(int serverIf, String address, int srvcType, int srvcInstanceId, UUID srvcUuid, int charInstanceId, UUID charUuid, boolean confirm, byte[] value)2013     void sendNotification(int serverIf, String address, int srvcType,
2014                                  int srvcInstanceId, UUID srvcUuid,
2015                                  int charInstanceId, UUID charUuid,
2016                                  boolean confirm, byte[] value) {
2017         enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
2018 
2019         if (VDBG) Log.d(TAG, "sendNotification() - address=" + address);
2020 
2021         int srvcHandle = mHandleMap.getServiceHandle(srvcUuid, srvcType, srvcInstanceId);
2022         if (srvcHandle == 0) return;
2023 
2024         int charHandle = mHandleMap.getCharacteristicHandle(srvcHandle, charUuid, charInstanceId);
2025         if (charHandle == 0) return;
2026 
2027         int connId = mServerMap.connIdByAddress(serverIf, address);
2028         if (connId == 0) return;
2029 
2030         if (confirm) {
2031             gattServerSendIndicationNative(serverIf, charHandle, connId, value);
2032         } else {
2033             gattServerSendNotificationNative(serverIf, charHandle, connId, value);
2034         }
2035     }
2036 
2037 
2038     /**************************************************************************
2039      * Private functions
2040      *************************************************************************/
2041 
isRestrictedCharUuid(final UUID charUuid)2042     private boolean isRestrictedCharUuid(final UUID charUuid) {
2043       return isHidUuid(charUuid);
2044     }
2045 
isRestrictedSrvcUuid(final UUID srvcUuid)2046     private boolean isRestrictedSrvcUuid(final UUID srvcUuid) {
2047       return isFidoUUID(srvcUuid);
2048     }
2049 
isHidUuid(final UUID uuid)2050     private boolean isHidUuid(final UUID uuid) {
2051         for (UUID hid_uuid : HID_UUIDS) {
2052             if (hid_uuid.equals(uuid)) return true;
2053         }
2054         return false;
2055     }
2056 
isFidoUUID(final UUID uuid)2057     private boolean isFidoUUID(final UUID uuid) {
2058         for (UUID fido_uuid : FIDO_UUIDS) {
2059             if (fido_uuid.equals(uuid)) return true;
2060         }
2061         return false;
2062     }
2063 
getDeviceType(BluetoothDevice device)2064     private int getDeviceType(BluetoothDevice device) {
2065         int type = gattClientGetDeviceTypeNative(device.getAddress());
2066         if (DBG) Log.d(TAG, "getDeviceType() - device=" + device
2067             + ", type=" + type);
2068         return type;
2069     }
2070 
enforceAdminPermission()2071     private void enforceAdminPermission() {
2072         enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
2073     }
2074 
needsPrivilegedPermissionForScan(ScanSettings settings)2075     private boolean needsPrivilegedPermissionForScan(ScanSettings settings) {
2076         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
2077         // BLE scan only mode needs special permission.
2078         if (adapter.getState() != BluetoothAdapter.STATE_ON) return true;
2079 
2080         // Regular scan, no special permission.
2081         if (settings == null) return false;
2082 
2083         // Regular scan, no special permission.
2084         if (settings.getReportDelayMillis() == 0) return false;
2085 
2086         // Batch scan, truncated mode needs permission.
2087         return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED;
2088     }
2089 
2090     // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be
2091     // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission.
enforcePrivilegedPermission()2092     private void enforcePrivilegedPermission() {
2093         enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
2094             "Need BLUETOOTH_PRIVILEGED permission");
2095     }
2096 
2097     // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other
2098     // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does
2099     // not have UPDATE_DEVICE_STATS permission.
enforceImpersonatationPermission()2100     private void enforceImpersonatationPermission() {
2101         enforceCallingOrSelfPermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
2102                 "Need UPDATE_DEVICE_STATS permission");
2103     }
2104 
continueServiceDeclaration(int serverIf, int status, int srvcHandle)2105     private void continueServiceDeclaration(int serverIf, int status, int srvcHandle) throws RemoteException {
2106         if (mServiceDeclarations.size() == 0) return;
2107         if (DBG) Log.d(TAG, "continueServiceDeclaration() - srvcHandle=" + srvcHandle);
2108 
2109         boolean finished = false;
2110 
2111         ServiceDeclaration.Entry entry = null;
2112         if (status == 0)
2113             entry = getPendingDeclaration().getNext();
2114 
2115         if (entry != null) {
2116             if (DBG) Log.d(TAG, "continueServiceDeclaration() - next entry type="
2117                 + entry.type);
2118             switch(entry.type) {
2119                 case ServiceDeclaration.TYPE_SERVICE:
2120                     if (entry.advertisePreferred) {
2121                         mAdvertisingServiceUuids.add(entry.uuid);
2122                     }
2123                     gattServerAddServiceNative(serverIf, entry.serviceType,
2124                         entry.instance,
2125                         entry.uuid.getLeastSignificantBits(),
2126                         entry.uuid.getMostSignificantBits(),
2127                         getPendingDeclaration().getNumHandles());
2128                     break;
2129 
2130                 case ServiceDeclaration.TYPE_CHARACTERISTIC:
2131                     gattServerAddCharacteristicNative(serverIf, srvcHandle,
2132                         entry.uuid.getLeastSignificantBits(),
2133                         entry.uuid.getMostSignificantBits(),
2134                         entry.properties, entry.permissions);
2135                     break;
2136 
2137                 case ServiceDeclaration.TYPE_DESCRIPTOR:
2138                     gattServerAddDescriptorNative(serverIf, srvcHandle,
2139                         entry.uuid.getLeastSignificantBits(),
2140                         entry.uuid.getMostSignificantBits(),
2141                         entry.permissions);
2142                     break;
2143 
2144                 case ServiceDeclaration.TYPE_INCLUDED_SERVICE:
2145                 {
2146                     int inclSrvc = mHandleMap.getServiceHandle(entry.uuid,
2147                                             entry.serviceType, entry.instance);
2148                     if (inclSrvc != 0) {
2149                         gattServerAddIncludedServiceNative(serverIf, srvcHandle,
2150                                                            inclSrvc);
2151                     } else {
2152                         finished = true;
2153                     }
2154                     break;
2155                 }
2156             }
2157         } else {
2158             gattServerStartServiceNative(serverIf, srvcHandle,
2159                 (byte)BluetoothDevice.TRANSPORT_BREDR | BluetoothDevice.TRANSPORT_LE);
2160             finished = true;
2161         }
2162 
2163         if (finished) {
2164             if (DBG) Log.d(TAG, "continueServiceDeclaration() - completed.");
2165             ServerMap.App app = mServerMap.getById(serverIf);
2166             if (app != null) {
2167                 HandleMap.Entry serviceEntry = mHandleMap.getByHandle(srvcHandle);
2168 
2169                 if (serviceEntry != null) {
2170                     app.callback.onServiceAdded(status, serviceEntry.serviceType,
2171                         serviceEntry.instance, new ParcelUuid(serviceEntry.uuid));
2172                 } else {
2173                     app.callback.onServiceAdded(status, 0, 0, null);
2174                 }
2175             }
2176             removePendingDeclaration();
2177 
2178             if (getPendingDeclaration() != null) {
2179                 continueServiceDeclaration(serverIf, (byte)0, 0);
2180             }
2181         }
2182     }
2183 
stopNextService(int serverIf, int status)2184     private void stopNextService(int serverIf, int status) throws RemoteException {
2185         if (DBG) Log.d(TAG, "stopNextService() - serverIf=" + serverIf
2186             + ", status=" + status);
2187 
2188         if (status == 0) {
2189             List<HandleMap.Entry> entries = mHandleMap.getEntries();
2190             for(HandleMap.Entry entry : entries) {
2191                 if (entry.type != HandleMap.TYPE_SERVICE ||
2192                     entry.serverIf != serverIf ||
2193                     entry.started == false)
2194                         continue;
2195 
2196                 gattServerStopServiceNative(serverIf, entry.handle);
2197                 return;
2198             }
2199         }
2200     }
2201 
deleteServices(int serverIf)2202     private void deleteServices(int serverIf) {
2203         if (DBG) Log.d(TAG, "deleteServices() - serverIf=" + serverIf);
2204 
2205         /*
2206          * Figure out which handles to delete.
2207          * The handles are copied into a new list to avoid race conditions.
2208          */
2209         List<Integer> handleList = new ArrayList<Integer>();
2210         List<HandleMap.Entry> entries = mHandleMap.getEntries();
2211         for(HandleMap.Entry entry : entries) {
2212             if (entry.type != HandleMap.TYPE_SERVICE ||
2213                 entry.serverIf != serverIf)
2214                     continue;
2215             handleList.add(entry.handle);
2216         }
2217 
2218         /* Now actually delete the services.... */
2219         for(Integer handle : handleList) {
2220             gattServerDeleteServiceNative(serverIf, handle);
2221         }
2222     }
2223 
parseUuids(byte[] adv_data)2224     private List<UUID> parseUuids(byte[] adv_data) {
2225         List<UUID> uuids = new ArrayList<UUID>();
2226 
2227         int offset = 0;
2228         while(offset < (adv_data.length-2)) {
2229             int len = adv_data[offset++];
2230             if (len == 0) break;
2231 
2232             int type = adv_data[offset++];
2233             switch (type) {
2234                 case 0x02: // Partial list of 16-bit UUIDs
2235                 case 0x03: // Complete list of 16-bit UUIDs
2236                     while (len > 1) {
2237                         int uuid16 = adv_data[offset++];
2238                         uuid16 += (adv_data[offset++] << 8);
2239                         len -= 2;
2240                         uuids.add(UUID.fromString(String.format(
2241                             "%08x-0000-1000-8000-00805f9b34fb", uuid16)));
2242                     }
2243                     break;
2244 
2245                 default:
2246                     offset += (len - 1);
2247                     break;
2248             }
2249         }
2250 
2251         return uuids;
2252     }
2253 
2254     @Override
dump(StringBuilder sb)2255     public void dump(StringBuilder sb) {
2256         super.dump(sb);
2257         println(sb, "mAdvertisingServiceUuids:");
2258         for (UUID uuid : mAdvertisingServiceUuids) {
2259             println(sb, "  " + uuid);
2260         }
2261         for (ServiceDeclaration declaration : mServiceDeclarations) {
2262             println(sb, "  " + declaration);
2263         }
2264         println(sb, "mMaxScanFilters: " + mMaxScanFilters);
2265 
2266         sb.append("\nGATT Client Map\n");
2267         mClientMap.dump(sb);
2268 
2269         sb.append("GATT Server Map\n");
2270         mServerMap.dump(sb);
2271 
2272         sb.append("GATT Handle Map\n");
2273         mHandleMap.dump(sb);
2274     }
2275 
addScanResult()2276     void addScanResult() {
2277         if (mScanEvents.isEmpty())
2278             return;
2279 
2280         BluetoothProto.ScanEvent curr = mScanEvents.get(mScanEvents.size() - 1);
2281         curr.setNumberResults(curr.getNumberResults() + 1);
2282     }
2283 
addScanEvent(BluetoothProto.ScanEvent event)2284     void addScanEvent(BluetoothProto.ScanEvent event) {
2285         synchronized(mScanEvents) {
2286             if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT)
2287                 mScanEvents.remove(0);
2288             mScanEvents.add(event);
2289         }
2290     }
2291 
2292     @Override
dumpProto(BluetoothProto.BluetoothLog proto)2293     public void dumpProto(BluetoothProto.BluetoothLog proto) {
2294         synchronized(mScanEvents) {
2295             for (BluetoothProto.ScanEvent event : mScanEvents) {
2296                 proto.addScanEvent(event);
2297             }
2298         }
2299     }
2300 
2301     /**************************************************************************
2302      * GATT Test functions
2303      *************************************************************************/
2304 
gattTestCommand(int command, UUID uuid1, String bda1, int p1, int p2, int p3, int p4, int p5)2305     void gattTestCommand(int command, UUID uuid1, String bda1,
2306                          int p1, int p2, int p3, int p4, int p5) {
2307         if (bda1 == null) bda1 = "00:00:00:00:00:00";
2308         if (uuid1 != null)
2309             gattTestNative(command, uuid1.getLeastSignificantBits(),
2310                        uuid1.getMostSignificantBits(), bda1, p1, p2, p3, p4, p5);
2311         else
2312             gattTestNative(command, 0,0, bda1, p1, p2, p3, p4, p5);
2313     }
2314 
gattTestNative(int command, long uuid1_lsb, long uuid1_msb, String bda1, int p1, int p2, int p3, int p4, int p5)2315     private native void gattTestNative(int command,
2316                                     long uuid1_lsb, long uuid1_msb, String bda1,
2317                                     int p1, int p2, int p3, int p4, int p5);
2318 
2319     /**************************************************************************
2320      * Native functions prototypes
2321      *************************************************************************/
2322 
classInitNative()2323     private native static void classInitNative();
initializeNative()2324     private native void initializeNative();
cleanupNative()2325     private native void cleanupNative();
2326 
gattClientGetDeviceTypeNative(String address)2327     private native int gattClientGetDeviceTypeNative(String address);
2328 
gattClientRegisterAppNative(long app_uuid_lsb, long app_uuid_msb)2329     private native void gattClientRegisterAppNative(long app_uuid_lsb,
2330                                                     long app_uuid_msb);
2331 
gattClientUnregisterAppNative(int clientIf)2332     private native void gattClientUnregisterAppNative(int clientIf);
2333 
gattClientConnectNative(int clientIf, String address, boolean isDirect, int transport)2334     private native void gattClientConnectNative(int clientIf, String address,
2335             boolean isDirect, int transport);
2336 
gattClientDisconnectNative(int clientIf, String address, int conn_id)2337     private native void gattClientDisconnectNative(int clientIf, String address,
2338             int conn_id);
2339 
gattClientRefreshNative(int clientIf, String address)2340     private native void gattClientRefreshNative(int clientIf, String address);
2341 
gattClientSearchServiceNative(int conn_id, boolean search_all, long service_uuid_lsb, long service_uuid_msb)2342     private native void gattClientSearchServiceNative(int conn_id,
2343             boolean search_all, long service_uuid_lsb, long service_uuid_msb);
2344 
gattClientGetGattDbNative(int conn_id)2345     private native void gattClientGetGattDbNative(int conn_id);
2346 
gattClientReadCharacteristicNative(int conn_id, int handle, int authReq)2347     private native void gattClientReadCharacteristicNative(int conn_id, int handle, int authReq);
2348 
gattClientReadDescriptorNative(int conn_id, int handle, int authReq)2349     private native void gattClientReadDescriptorNative(int conn_id, int handle, int authReq);
2350 
gattClientWriteCharacteristicNative(int conn_id, int handle, int write_type, int auth_req, byte[] value)2351     private native void gattClientWriteCharacteristicNative(int conn_id,
2352             int handle, int write_type, int auth_req, byte[] value);
2353 
gattClientWriteDescriptorNative(int conn_id, int handle, int write_type, int auth_req, byte[] value)2354     private native void gattClientWriteDescriptorNative(int conn_id, int handle,
2355             int write_type, int auth_req, byte[] value);
2356 
gattClientExecuteWriteNative(int conn_id, boolean execute)2357     private native void gattClientExecuteWriteNative(int conn_id, boolean execute);
2358 
gattClientRegisterForNotificationsNative(int clientIf, String address, int handle, boolean enable)2359     private native void gattClientRegisterForNotificationsNative(int clientIf,
2360             String address, int handle, boolean enable);
2361 
gattClientReadRemoteRssiNative(int clientIf, String address)2362     private native void gattClientReadRemoteRssiNative(int clientIf,
2363             String address);
2364 
gattClientConfigureMTUNative(int conn_id, int mtu)2365     private native void gattClientConfigureMTUNative(int conn_id, int mtu);
2366 
gattConnectionParameterUpdateNative(int client_if, String address, int minInterval, int maxInterval, int latency, int timeout)2367     private native void gattConnectionParameterUpdateNative(int client_if, String address,
2368             int minInterval, int maxInterval, int latency, int timeout);
2369 
gattServerRegisterAppNative(long app_uuid_lsb, long app_uuid_msb)2370     private native void gattServerRegisterAppNative(long app_uuid_lsb,
2371                                                     long app_uuid_msb);
2372 
gattServerUnregisterAppNative(int serverIf)2373     private native void gattServerUnregisterAppNative(int serverIf);
2374 
gattServerConnectNative(int server_if, String address, boolean is_direct, int transport)2375     private native void gattServerConnectNative(int server_if, String address,
2376                                              boolean is_direct, int transport);
2377 
gattServerDisconnectNative(int serverIf, String address, int conn_id)2378     private native void gattServerDisconnectNative(int serverIf, String address,
2379                                               int conn_id);
2380 
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)2381     private native void gattServerAddServiceNative (int server_if,
2382             int service_type, int service_id_inst_id,
2383             long service_id_uuid_lsb, long service_id_uuid_msb,
2384             int num_handles);
2385 
gattServerAddIncludedServiceNative(int server_if, int svc_handle, int included_svc_handle)2386     private native void gattServerAddIncludedServiceNative (int server_if,
2387             int svc_handle, int included_svc_handle);
2388 
gattServerAddCharacteristicNative(int server_if, int svc_handle, long char_uuid_lsb, long char_uuid_msb, int properties, int permissions)2389     private native void gattServerAddCharacteristicNative (int server_if,
2390             int svc_handle, long char_uuid_lsb, long char_uuid_msb,
2391             int properties, int permissions);
2392 
gattServerAddDescriptorNative(int server_if, int svc_handle, long desc_uuid_lsb, long desc_uuid_msb, int permissions)2393     private native void gattServerAddDescriptorNative (int server_if,
2394             int svc_handle, long desc_uuid_lsb, long desc_uuid_msb,
2395             int permissions);
2396 
gattServerStartServiceNative(int server_if, int svc_handle, int transport )2397     private native void gattServerStartServiceNative (int server_if,
2398             int svc_handle, int transport );
2399 
gattServerStopServiceNative(int server_if, int svc_handle)2400     private native void gattServerStopServiceNative (int server_if,
2401                                                      int svc_handle);
2402 
gattServerDeleteServiceNative(int server_if, int svc_handle)2403     private native void gattServerDeleteServiceNative (int server_if,
2404                                                        int svc_handle);
2405 
gattServerSendIndicationNative(int server_if, int attr_handle, int conn_id, byte[] val)2406     private native void gattServerSendIndicationNative (int server_if,
2407             int attr_handle, int conn_id, byte[] val);
2408 
gattServerSendNotificationNative(int server_if, int attr_handle, int conn_id, byte[] val)2409     private native void gattServerSendNotificationNative (int server_if,
2410             int attr_handle, int conn_id, byte[] val);
2411 
gattServerSendResponseNative(int server_if, int conn_id, int trans_id, int status, int handle, int offset, byte[] val, int auth_req)2412     private native void gattServerSendResponseNative (int server_if,
2413             int conn_id, int trans_id, int status, int handle, int offset,
2414             byte[] val, int auth_req);
2415 }
2416