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