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