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