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