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