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