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