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