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