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