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