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