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