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