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