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