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