Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2017 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.googlecode.android_scripting.facade.bluetooth;
     18 
     19 import android.app.Service;
     20 import android.bluetooth.BluetoothAdapter;
     21 import android.bluetooth.BluetoothDevice;
     22 import android.bluetooth.BluetoothGattCharacteristic;
     23 import android.bluetooth.BluetoothGattDescriptor;
     24 import android.bluetooth.BluetoothGattServer;
     25 import android.bluetooth.BluetoothGattServerCallback;
     26 import android.bluetooth.BluetoothGattService;
     27 import android.bluetooth.BluetoothManager;
     28 import android.bluetooth.BluetoothProfile;
     29 import android.content.Context;
     30 import android.os.Bundle;
     31 
     32 import com.googlecode.android_scripting.Log;
     33 import com.googlecode.android_scripting.MainThread;
     34 import com.googlecode.android_scripting.facade.EventFacade;
     35 import com.googlecode.android_scripting.facade.FacadeManager;
     36 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
     37 import com.googlecode.android_scripting.rpc.Rpc;
     38 import com.googlecode.android_scripting.rpc.RpcParameter;
     39 
     40 import java.lang.reflect.*;
     41 import java.util.ArrayList;
     42 import java.util.HashMap;
     43 import java.util.List;
     44 import java.util.UUID;
     45 import java.util.concurrent.Callable;
     46 
     47 public class GattServerFacade extends RpcReceiver {
     48     private final EventFacade mEventFacade;
     49     private BluetoothAdapter mBluetoothAdapter;
     50     private BluetoothManager mBluetoothManager;
     51     private final Service mService;
     52     private final Context mContext;
     53     private final HashMap<Integer, BluetoothGattCharacteristic> mCharacteristicList;
     54     private final HashMap<Integer, BluetoothGattDescriptor> mDescriptorList;
     55     private final HashMap<Integer, BluetoothGattServer> mBluetoothGattServerList;
     56     private final HashMap<Integer, BtGattServerCallback> mBluetoothGattServerCallbackList;
     57     private final HashMap<Integer, BluetoothGattService> mGattServiceList;
     58     private final HashMap<Integer, List<BluetoothGattService>> mBluetoothGattDiscoveredServicesList;
     59     private final HashMap<Integer, List<BluetoothDevice>> mGattServerDiscoveredDevicesList;
     60     private static int sCharacteristicCount;
     61     private static int sDescriptorCount;
     62     private static int sGattServerCallbackCount;
     63     private static int sGattServerCount;
     64     private static int sGattServiceCount;
     65 
     66     public GattServerFacade(FacadeManager manager) {
     67         super(manager);
     68         mService = manager.getService();
     69         mContext = mService.getApplicationContext();
     70         mBluetoothAdapter = MainThread.run(mService, new Callable<BluetoothAdapter>() {
     71             @Override
     72             public BluetoothAdapter call() throws Exception {
     73                 return BluetoothAdapter.getDefaultAdapter();
     74             }
     75         });
     76         mBluetoothManager = (BluetoothManager) mContext.getSystemService(Service.BLUETOOTH_SERVICE);
     77         mEventFacade = manager.getReceiver(EventFacade.class);
     78         mCharacteristicList = new HashMap<Integer, BluetoothGattCharacteristic>();
     79         mDescriptorList = new HashMap<Integer, BluetoothGattDescriptor>();
     80         mBluetoothGattServerList = new HashMap<Integer, BluetoothGattServer>();
     81         mBluetoothGattServerCallbackList = new HashMap<Integer, BtGattServerCallback>();
     82         mGattServiceList = new HashMap<Integer, BluetoothGattService>();
     83         mBluetoothGattDiscoveredServicesList = new HashMap<Integer, List<BluetoothGattService>>();
     84         mGattServerDiscoveredDevicesList = new HashMap<Integer, List<BluetoothDevice>>();
     85     }
     86 
     87     /**
     88      * Open a new Gatt server.
     89      *
     90      * @param index the bluetooth gatt server callback to open on
     91      * @return the index of the newly opened gatt server
     92      * @throws Exception
     93      */
     94     @Rpc(description = "Open new gatt server")
     95     public int gattServerOpenGattServer(@RpcParameter(name = "index") Integer index)
     96             throws Exception {
     97         if (mBluetoothGattServerCallbackList.get(index) != null) {
     98             BluetoothGattServer mGattServer =
     99                     mBluetoothManager.openGattServer(mContext, mBluetoothGattServerCallbackList.get(
    100                         index));
    101             sGattServerCount += 1;
    102             int in = sGattServerCount;
    103             mBluetoothGattServerList.put(in, mGattServer);
    104             return in;
    105         } else {
    106             throw new Exception("Invalid index input:" + Integer.toString(index));
    107         }
    108     }
    109 
    110     /**
    111      * Add a service to a bluetooth gatt server
    112      *
    113      * @param index the bluetooth gatt server to add a service to
    114      * @param serviceIndex the service to add to the bluetooth gatt server
    115      * @throws Exception
    116      */
    117     @Rpc(description = "Add service to bluetooth gatt server")
    118     public void gattServerAddService(@RpcParameter(name = "index") Integer index,
    119             @RpcParameter(name = "serviceIndex") Integer serviceIndex) throws Exception {
    120         if (mBluetoothGattServerList.get(index) != null) {
    121             if (mGattServiceList.get(serviceIndex) != null) {
    122                 mBluetoothGattServerList.get(index).addService(mGattServiceList.get(serviceIndex));
    123             } else {
    124                 throw new Exception("Invalid serviceIndex input:" + Integer.toString(serviceIndex));
    125             }
    126         } else {
    127             throw new Exception("Invalid index input:" + Integer.toString(index));
    128         }
    129     }
    130 
    131     /**
    132      * Add a service to a bluetooth gatt server
    133      *
    134      * @param index the bluetooth gatt server to add a service to
    135      * @throws Exception
    136      */
    137     @Rpc(description = "Clear services from bluetooth gatt server")
    138     public void gattServerClearServices(
    139             @RpcParameter(name = "index") Integer index) throws Exception {
    140         if (mBluetoothGattServerList.get(index) != null) {
    141             mBluetoothGattServerList.get(index).clearServices();
    142         } else {
    143             throw new Exception("Invalid index input:" + Integer.toString(index));
    144         }
    145     }
    146 
    147     /**
    148      * Get connected devices of the gatt server
    149      *
    150      * @param gattServerIndex the gatt server index
    151      * @throws Exception
    152      */
    153     @Rpc(description = "Return a list of connected gatt devices.")
    154     public List<BluetoothDevice> gattServerGetConnectedDevices(
    155             @RpcParameter(name = "gattServerIndex") Integer gattServerIndex) throws Exception {
    156         if (mBluetoothGattServerList.get(gattServerIndex) == null) {
    157             throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex));
    158         }
    159         List<BluetoothDevice> connectedDevices =
    160                 mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER);
    161         mGattServerDiscoveredDevicesList.put(gattServerIndex, connectedDevices);
    162         return connectedDevices;
    163     }
    164 
    165     /**
    166      * Get connected devices of the gatt server
    167      *
    168      * @param gattServerIndex the gatt server index
    169      * @param bluetoothDeviceIndex the remotely connected bluetooth device
    170      * @param requestId the ID of the request that was received with the callback
    171      * @param status the status of the request to be sent to the remote devices
    172      * @param offset value offset for partial read/write response
    173      * @param value the value of the attribute that was read/written
    174      * @throws Exception
    175      */
    176     @Rpc(description = "Send a response after a write.")
    177     public void gattServerSendResponse(
    178             @RpcParameter(name = "gattServerIndex") Integer gattServerIndex,
    179             @RpcParameter(name = "bluetoothDeviceIndex") Integer bluetoothDeviceIndex,
    180             @RpcParameter(name = "requestId") Integer requestId,
    181             @RpcParameter(name = "status") Integer status,
    182             @RpcParameter(name = "offset") Integer offset,
    183             @RpcParameter(name = "value") byte[] value) throws Exception {
    184 
    185         BluetoothGattServer gattServer = mBluetoothGattServerList.get(gattServerIndex);
    186         if (gattServer == null) {
    187             throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex));
    188         }
    189         List<BluetoothDevice> connectedDevices =
    190                 mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER);
    191         BluetoothDevice bluetoothDevice = connectedDevices.get(bluetoothDeviceIndex);
    192         gattServer.sendResponse(bluetoothDevice, requestId, status, offset, value);
    193     }
    194 
    195     /**
    196      * Notify that characteristic was changed
    197      *
    198      * @deprecated Use {@link #gattServerNotifyCharacteristicChangedByInstanceId(
    199      *  gattServerIndex, bluetoothDeviceIndex, instanceId, confirm)} instead.
    200      * @param gattServerIndex the gatt server index
    201      * @param bluetoothDeviceIndex the remotely connected bluetooth device
    202      * @param characteristicIndex characteristic index
    203      * @param confirm shall we expect confirmation
    204      * @throws Exception
    205      */
    206     @Deprecated
    207     @Rpc(description = "Notify that characteristic was changed.")
    208     public void gattServerNotifyCharacteristicChanged(
    209             @RpcParameter(name = "gattServerIndex") Integer gattServerIndex,
    210             @RpcParameter(name = "bluetoothDeviceIndex") Integer bluetoothDeviceIndex,
    211             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex,
    212             @RpcParameter(name = "confirm") Boolean confirm) throws Exception {
    213 
    214         BluetoothGattServer gattServer = mBluetoothGattServerList.get(gattServerIndex);
    215         if (gattServer == null) {
    216             throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex));
    217         }
    218         List<BluetoothDevice> connectedDevices =
    219                 mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER);
    220         if (connectedDevices == null) {
    221             throw new Exception(
    222                     "Connected device list empty for gattServerIndex:" + Integer.toString(
    223                         gattServerIndex));
    224         }
    225         BluetoothDevice bluetoothDevice = connectedDevices.get(bluetoothDeviceIndex);
    226         if (bluetoothDevice == null) {
    227             throw new Exception(
    228                     "Invalid bluetoothDeviceIndex: " + Integer.toString(bluetoothDeviceIndex));
    229         }
    230 
    231         BluetoothGattCharacteristic bluetoothCharacteristic = mCharacteristicList.get(
    232                 characteristicIndex);
    233         if (bluetoothCharacteristic == null) {
    234             throw new Exception(
    235                     "Invalid characteristicIndex: " + Integer.toString(characteristicIndex));
    236         }
    237 
    238         gattServer.notifyCharacteristicChanged(bluetoothDevice, bluetoothCharacteristic, confirm);
    239     }
    240 
    241     /**
    242      * Notify that characteristic was changed
    243      *
    244      * @param gattServerIndex the gatt server index
    245      * @param bluetoothDeviceIndex the remotely connected bluetooth device
    246      * @param characteristicIndex characteristic index
    247      * @param confirm shall we expect confirmation
    248      * @throws Exception
    249      */
    250     @Rpc(description = "Notify that characteristic was changed by Instance Id.")
    251     public void gattServerNotifyCharacteristicChangedByInstanceId(
    252             @RpcParameter(name = "gattServerIndex") Integer gattServerIndex,
    253             @RpcParameter(name = "bluetoothDeviceIndex") Integer bluetoothDeviceIndex,
    254             @RpcParameter(name = "instanceId") Integer instanceId,
    255             @RpcParameter(name = "confirm") Boolean confirm) throws Exception {
    256 
    257         BluetoothGattServer gattServer = mBluetoothGattServerList.get(gattServerIndex);
    258         if (gattServer == null) {
    259             throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex));
    260         }
    261         List<BluetoothDevice> connectedDevices =
    262                 mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER);
    263         if (connectedDevices == null) {
    264             throw new Exception(
    265                     "Connected device list empty for gattServerIndex:" + Integer.toString(
    266                         gattServerIndex));
    267         }
    268         BluetoothDevice bluetoothDevice = connectedDevices.get(bluetoothDeviceIndex);
    269         if (bluetoothDevice == null) {
    270             throw new Exception(
    271                     "Invalid bluetoothDeviceIndex: " + Integer.toString(bluetoothDeviceIndex));
    272         }
    273 
    274         for (BluetoothGattCharacteristic mGattChar : mCharacteristicList.values()) {
    275             if (mGattChar.getInstanceId() == instanceId) {
    276                         Log.i("Found Characteristic to get value. instanceId: "
    277                         + Integer.toString(instanceId)
    278                         + " UUID: " + mGattChar.getUuid().toString());
    279                 gattServer.notifyCharacteristicChanged(bluetoothDevice, mGattChar, confirm);
    280             }
    281         }
    282     }
    283 
    284     /**
    285      * Create a new bluetooth gatt service
    286      *
    287      * @param uuid the UUID that characterises the service
    288      * @param serviceType the service type
    289      * @return The index of the new bluetooth gatt service
    290      */
    291     @Rpc(description = "Create new bluetooth gatt service")
    292     public int gattServerCreateService(@RpcParameter(name = "uuid") String uuid,
    293             @RpcParameter(name = "serviceType") Integer serviceType) {
    294         sGattServiceCount += 1;
    295         int index = sGattServiceCount;
    296         mGattServiceList.put(index, new BluetoothGattService(UUID.fromString(uuid), serviceType));
    297         return index;
    298     }
    299 
    300     /**
    301      * Add a characteristic to a bluetooth gatt service
    302      *
    303      * @param index the bluetooth gatt service index
    304      * @param serviceUuid the service Uuid to get
    305      * @param characteristicIndex the character index to use
    306      * @throws Exception
    307      */
    308     @Rpc(description = "Add a characteristic to a bluetooth gatt service")
    309     public void gattServiceAddCharacteristic(
    310             @RpcParameter(name = "index") Integer index,
    311             @RpcParameter(name = "serviceUuid") String serviceUuid,
    312             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex)
    313             throws Exception {
    314         if (mBluetoothGattServerList.get(index) != null
    315                 && mBluetoothGattServerList.get(index).getService(
    316                     UUID.fromString(serviceUuid)) != null
    317                 && mCharacteristicList.get(characteristicIndex) != null) {
    318             mBluetoothGattServerList.get(index).getService(UUID.fromString(serviceUuid))
    319                     .addCharacteristic(mCharacteristicList.get(characteristicIndex));
    320         } else {
    321             if (mBluetoothGattServerList.get(index) == null) {
    322                 throw new Exception("Invalid index input:" + index);
    323             } else if (mCharacteristicList.get(characteristicIndex) == null) {
    324                 throw new Exception("Invalid characteristicIndex input:" + characteristicIndex);
    325             } else {
    326                 throw new Exception("Invalid serviceUuid input:" + serviceUuid);
    327             }
    328         }
    329     }
    330 
    331     /**
    332      * Add a characteristic to a bluetooth gatt service
    333      *
    334      * @param index the bluetooth gatt service to add a characteristic to
    335      * @param characteristicIndex the characteristic to add
    336      * @throws Exception
    337      */
    338     @Rpc(description = "Add a characteristic to a bluetooth gatt service")
    339     public void gattServerAddCharacteristicToService(@RpcParameter(name = "index") Integer index,
    340             @RpcParameter(name = "characteristicIndex") Integer characteristicIndex
    341 
    342     ) throws Exception {
    343         if (mGattServiceList.get(index) != null) {
    344             if (mCharacteristicList.get(characteristicIndex) != null) {
    345                 mGattServiceList.get(index).addCharacteristic(mCharacteristicList.get(
    346                         characteristicIndex));
    347             } else {
    348                 throw new Exception("Invalid index input:" + index);
    349             }
    350         } else {
    351             throw new Exception("Invalid index input:" + index);
    352         }
    353     }
    354 
    355     /**
    356      * Close a bluetooth gatt
    357      *
    358      * @param index the bluetooth gatt index to close
    359      * @throws Exception
    360      */
    361     @Rpc(description = "Close a bluetooth gatt")
    362     public void gattServerClose(@RpcParameter(name = "index") Integer index) throws Exception {
    363         if (mBluetoothGattServerList.get(index) != null) {
    364             mBluetoothGattServerList.get(index).close();
    365         } else {
    366             throw new Exception("Invalid index input:" + index);
    367         }
    368     }
    369 
    370     /**
    371      * Get a list of Bluetooth Devices connnected to the bluetooth gatt
    372      *
    373      * @param index the bluetooth gatt index
    374      * @return List of BluetoothDevice Objects
    375      * @throws Exception
    376      */
    377     @Rpc(description = "Get a list of Bluetooth Devices connnected to the bluetooth gatt")
    378     public List<BluetoothDevice> gattGetConnectedDevices(
    379             @RpcParameter(name = "index") Integer index)
    380             throws Exception {
    381         if (mBluetoothGattServerList.get(index) != null) {
    382             return mBluetoothGattServerList.get(index).getConnectedDevices();
    383         } else {
    384             throw new Exception("Invalid index input:" + index);
    385         }
    386     }
    387 
    388     /**
    389      * Read the current transmitter PHY and receiver PHY of the connection.
    390      *
    391      * @param gattServerIndex the bluetooth gatt index
    392      * @throws Exception
    393      */
    394     @Rpc(description = "Read PHY")
    395     public void gattServerReadPhy(
    396             @RpcParameter(name = "gattServerIndex") Integer gattServerIndex,
    397             @RpcParameter(name = "bluetoothDeviceIndex") Integer bluetoothDeviceIndex)
    398                 throws Exception {
    399         BluetoothGattServer gattServer = mBluetoothGattServerList.get(gattServerIndex);
    400         if (gattServer == null) {
    401             throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex));
    402         }
    403         List<BluetoothDevice> connectedDevices = mGattServerDiscoveredDevicesList.get(
    404                 gattServerIndex);
    405         if (connectedDevices == null) {
    406             throw new Exception(
    407                     "Connected device list empty for gattServerIndex:" + Integer.toString(
    408                         gattServerIndex));
    409         }
    410         BluetoothDevice bluetoothDevice = connectedDevices.get(bluetoothDeviceIndex);
    411         if (bluetoothDevice == null) {
    412             throw new Exception(
    413                     "Invalid bluetoothDeviceIndex: " + Integer.toString(bluetoothDeviceIndex));
    414         }
    415 
    416         if (mBluetoothGattServerList.get(gattServerIndex) != null) {
    417             mBluetoothGattServerList.get(gattServerIndex).readPhy(bluetoothDevice);
    418         } else {
    419             throw new Exception("Invalid index input:" + gattServerIndex);
    420         }
    421     }
    422 
    423     /**
    424      * Set the preferred connection PHY.
    425      *
    426      * @param gattServerIndex the bluetooth gatt index
    427      * @throws Exception
    428      */
    429     @Rpc(description = "Set the preferred connection PHY")
    430     public void gattServerSetPreferredPhy(
    431             @RpcParameter(name = "gattServerIndex") Integer gattServerIndex,
    432             @RpcParameter(name = "bluetoothDeviceIndex") Integer bluetoothDeviceIndex,
    433             @RpcParameter(name = "txPhy") Integer txPhy,
    434             @RpcParameter(name = "rxPhy") Integer rxPhy,
    435             @RpcParameter(name = "txPhy") Integer phyOptions) throws Exception {
    436         BluetoothGattServer gattServer = mBluetoothGattServerList.get(gattServerIndex);
    437         if (gattServer == null) {
    438             throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex));
    439         }
    440         List<BluetoothDevice> connectedDevices = mGattServerDiscoveredDevicesList.get(
    441                 gattServerIndex);
    442         if (connectedDevices == null) {
    443             throw new Exception(
    444                     "Connected device list empty for gattServerIndex:" + Integer.toString(
    445                         gattServerIndex));
    446         }
    447         BluetoothDevice bluetoothDevice = connectedDevices.get(bluetoothDeviceIndex);
    448         if (bluetoothDevice == null) {
    449             throw new Exception(
    450                     "Invalid bluetoothDeviceIndex: " + Integer.toString(bluetoothDeviceIndex));
    451         }
    452 
    453         if (mBluetoothGattServerList.get(gattServerIndex) != null) {
    454             mBluetoothGattServerList.get(gattServerIndex)
    455                 .setPreferredPhy(bluetoothDevice, txPhy, rxPhy, phyOptions);
    456         } else {
    457             throw new Exception("Invalid index input:" + gattServerIndex);
    458         }
    459     }
    460 
    461     /**
    462      * Get GATT Server UUID by characteristic index
    463      *
    464      * @param charIndex of the characteristic
    465      * @return String Uuid
    466      * @throws Exception
    467      */
    468     @Rpc(description = "Get UUID of the input characteristic")
    469     public String gattServerGetCharacteristicUuid(
    470             @RpcParameter(name = "charIndex") Integer charIndex)
    471             throws Exception {
    472         BluetoothGattCharacteristic gattChar = mCharacteristicList.get(charIndex);
    473         if (gattChar == null) {
    474             throw new Exception("Invalid index input: " + charIndex);
    475         }
    476         return gattChar.getUuid().toString();
    477     }
    478 
    479     /**
    480      * Get GATT Server UUID by characteristic index
    481      *
    482      * @param charIndex of the characteristic
    483      * @return Integer instanceId
    484      * @throws Exception
    485      */
    486     @Rpc(description = "Get instanceId of the input characteristic")
    487     public Integer gattServerGetCharacteristicInstanceId(
    488             @RpcParameter(name = "charIndex") Integer charIndex)
    489             throws Exception {
    490         BluetoothGattCharacteristic gattChar = mCharacteristicList.get(charIndex);
    491         if (gattChar == null) {
    492             throw new Exception("Invalid index input: " + charIndex);
    493         }
    494         return gattChar.getInstanceId();
    495     }
    496 
    497     /**
    498      * Get the service from an input UUID
    499      *
    500      * @param index the bluetooth gatt index
    501      * @return BluetoothGattService related to the bluetooth gatt
    502      * @throws Exception
    503      */
    504     @Rpc(description = "Get the service from an input UUID")
    505     public ArrayList<String> gattGetServiceUuidList(@RpcParameter(name = "index") Integer index)
    506             throws Exception {
    507         if (mBluetoothGattServerList.get(index) != null) {
    508             ArrayList<String> serviceUuidList = new ArrayList<String>();
    509             for (BluetoothGattService service : mBluetoothGattServerList.get(index).getServices()) {
    510                 serviceUuidList.add(service.getUuid().toString());
    511             }
    512             return serviceUuidList;
    513         } else {
    514             throw new Exception("Invalid index input:" + index);
    515         }
    516     }
    517 
    518     /**
    519      * Get the service from an input UUID
    520      *
    521      * @param index the bluetooth gatt index
    522      * @param uuid the String uuid that matches the service
    523      * @return BluetoothGattService related to the bluetooth gatt
    524      * @throws Exception
    525      */
    526     @Rpc(description = "Get the service from an input UUID")
    527     public BluetoothGattService gattGetService(@RpcParameter(name = "index") Integer index,
    528             @RpcParameter(name = "uuid") String uuid) throws Exception {
    529         if (mBluetoothGattServerList.get(index) != null) {
    530             return mBluetoothGattServerList.get(index).getService(UUID.fromString(uuid));
    531         } else {
    532             throw new Exception("Invalid index input:" + index);
    533         }
    534     }
    535 
    536     /**
    537      * Add a descriptor to a bluetooth gatt characteristic
    538      *
    539      * @param index the bluetooth gatt characteristic to add a descriptor to
    540      * @param descriptorIndex the descritor index to add to the characteristic
    541      * @throws Exception
    542      */
    543     @Rpc(description = "add descriptor to blutooth gatt characteristic")
    544     public void gattServerCharacteristicAddDescriptor(@RpcParameter(name = "index") Integer index,
    545             @RpcParameter(name = "descriptorIndex") Integer descriptorIndex) throws Exception {
    546         if (mCharacteristicList.get(index) != null) {
    547             if (mDescriptorList.get(descriptorIndex) != null) {
    548                 mCharacteristicList.get(index).addDescriptor(mDescriptorList.get(descriptorIndex));
    549             } else {
    550                 throw new Exception("Invalid descriptorIndex input:" + descriptorIndex);
    551             }
    552         } else {
    553             throw new Exception("Invalid index input:" + index);
    554         }
    555     }
    556 
    557     /**
    558      * Create a new Characteristic object
    559      *
    560      * @param characteristicUuid uuid The UUID for this characteristic
    561      * @param property Properties of this characteristic
    562      * @param permission permissions Permissions for this characteristic
    563      * @return
    564      */
    565     @Rpc(description = "Create a new Characteristic object")
    566     public int gattServerCreateBluetoothGattCharacteristic(
    567             @RpcParameter(name = "characteristicUuid") String characteristicUuid,
    568             @RpcParameter(name = "property") Integer property,
    569             @RpcParameter(name = "permission") Integer permission) {
    570         sCharacteristicCount += 1;
    571         int index = sCharacteristicCount;
    572         BluetoothGattCharacteristic characteristic =
    573                 new BluetoothGattCharacteristic(
    574                     UUID.fromString(characteristicUuid), property, permission);
    575         mCharacteristicList.put(index, characteristic);
    576         return index;
    577     }
    578 
    579     /**
    580      * Set value to a bluetooth gatt characteristic
    581      *
    582      * @deprecated Use {@link #gattServerCharacteristicSetValueByInstanceId(
    583      * instanceId, value)} instead.
    584      * @param index the bluetooth gatt characteristic
    585      * @param value value
    586      * @throws Exception
    587      */
    588     @Deprecated
    589     @Rpc(description = "Set byte value to a Characteristic")
    590     public void gattServerCharacteristicSetValue(@RpcParameter(name = "index") Integer index,
    591             @RpcParameter(name = "value") byte[] value) throws Exception {
    592         if (mCharacteristicList.get(index) != null) {
    593             mCharacteristicList.get(index).setValue(value);
    594             } else {
    595             throw new Exception("Invalid index input:" + index);
    596         }
    597     }
    598 
    599     /**
    600      * Set value to a bluetooth gatt characteristic by instance id
    601      *
    602      * @param index the bluetooth gatt characteristic by instance id
    603      * @param value value
    604      * @throws Exception
    605      */
    606     @Rpc(description = "Set byte value to a Characteristic by instance id")
    607     public boolean gattServerCharacteristicSetValueByInstanceId(
    608             @RpcParameter(name = "instanceId") Integer instanceId,
    609             @RpcParameter(name = "value") byte[] value) throws Exception {
    610         for (BluetoothGattCharacteristic mGattChar : mCharacteristicList.values()) {
    611             //test this to be sure
    612             if (mGattChar.getInstanceId() == instanceId) {
    613                 return mGattChar.setValue(value);
    614             }
    615         }
    616         throw new Exception("Cannot find instance ID:" + instanceId);
    617     }
    618 
    619     /**
    620      * Set value to a bluetooth gatt characteristic
    621      *
    622      * @param index the bluetooth gatt characteristic
    623      * @param value value
    624      * @throws Exception
    625      */
    626     @Rpc(description = "Set Characteristic Byte Value")
    627     public boolean gattServerCharacteristicSetByteValue(@RpcParameter(name = "index") Integer index,
    628             @RpcParameter(name = "value") byte[] value) throws Exception {
    629         if (mCharacteristicList.get(index) != null) {
    630             return mCharacteristicList.get(index).setValue(value);
    631         } else {
    632             throw new Exception("Invalid index input:" + index);
    633         }
    634     }
    635 
    636     /**
    637      * Set value to a bluetooth gatt descriptor
    638      *
    639      * @param index the bluetooth gatt descriptor
    640      * @param value byte[] value to set
    641      * @throws Exception
    642      */
    643     @Rpc(description = "Set Characteristic Byte Value")
    644     public boolean gattServerDescriptorSetByteValue(
    645             @RpcParameter(name = "index") Integer index,
    646             @RpcParameter(name = "value") byte[] value) throws Exception {
    647         if (mDescriptorList.get(index) != null) {
    648             return mDescriptorList.get(index).setValue(value);
    649         } else {
    650             throw new Exception("Invalid index input:" + index);
    651         }
    652     }
    653 
    654     /**
    655      * Get Read value by instance ID
    656      *
    657      * @param instanceId of the Characteristic of the Descriptor to get the value of
    658      * @throws Exception
    659      */
    660     @Rpc(description = "Returns the read value of a matching instanceId")
    661     public byte[] gattServerGetReadValueByInstanceId(
    662             @RpcParameter(name = "instanceId") Integer instanceId)
    663             throws Exception {
    664         for (BluetoothGattCharacteristic mGattChar : mCharacteristicList.values()) {
    665             if (mGattChar.getInstanceId() == instanceId) {
    666                         Log.i("Found Characteristic to get value. instanceId: "
    667                         + Integer.toString(instanceId)
    668                         + " UUID: " + mGattChar.getUuid().toString());
    669                 return mGattChar.getValue();
    670             }
    671             List<BluetoothGattDescriptor> descList = mGattChar.getDescriptors();
    672             for (BluetoothGattDescriptor mGattDesc : descList) {
    673                 if (mGattDesc.getInstanceId() == instanceId) {
    674                     Log.i("Found Descriptor to get value. instanceId: "
    675                         + Integer.toString(instanceId)
    676                         + " UUID: " + mGattDesc.getUuid().toString());
    677                     return mGattDesc.getValue();
    678                 }
    679             }
    680         }
    681         throw new Exception("Cannot find instance ID:" + instanceId);
    682     }
    683 
    684     /**
    685      * Set value by instance ID
    686      *
    687      * @param instanceId of the Characteristic of the Descriptor to get the value of
    688      * @value value set bytearray value
    689      * @throws Exception
    690      */
    691     @Rpc(description = "Sets the value of a Characteristic or Descriptor by instance id")
    692     public boolean gattServerSetByteArrayValueByInstanceId(
    693             @RpcParameter(name = "instanceId") Integer instanceId,
    694             @RpcParameter(name = "value") byte[] value)
    695             throws Exception {
    696         for (BluetoothGattCharacteristic mGattChar : mCharacteristicList.values()) {
    697             if (mGattChar.getInstanceId() == instanceId) {
    698                         Log.i("Found Characteristic to get value. instanceId: "
    699                         + Integer.toString(instanceId)
    700                         + " UUID: " + mGattChar.getUuid().toString());
    701                 return mGattChar.setValue(value);
    702             }
    703             List<BluetoothGattDescriptor> descList = mGattChar.getDescriptors();
    704             for (BluetoothGattDescriptor mGattDesc : descList) {
    705                 if (mGattDesc.getInstanceId() == instanceId) {
    706                     Log.i("Found Descriptor to set value. instanceId: "
    707                         + Integer.toString(instanceId)
    708                         + " UUID: " + mGattDesc.getUuid().toString());
    709                     return mGattDesc.setValue(value);
    710                 }
    711             }
    712         }
    713         throw new Exception("Cannot find instance ID:" + instanceId);
    714     }
    715 
    716     /**
    717      * Set BluetoothGattService instance ID to input value
    718      *
    719      * @param index the bluetooth gatt service
    720      * @param instanceId instanceId
    721      * @throws Exception
    722      */
    723     @Rpc(description = "GATT Server Set Instance ID of Service")
    724     public void gattServerServiceSetInstanceId(
    725             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
    726             @RpcParameter(name = "instanceId") Integer instanceId) throws Exception {
    727         if (mGattServiceList.get(serviceIndex) == null) {
    728             throw new Exception("Invalid serviceIndex input:" + Integer.toString(serviceIndex));
    729         }
    730         Class bluetoothGattServiceClass = Class.forName("android.bluetooth.BluetoothGattService");
    731         Method setInstanceIdMethod = bluetoothGattServiceClass.getMethod(
    732             "setInstanceId", int.class);
    733         setInstanceIdMethod.invoke(mGattServiceList.get(serviceIndex), instanceId);
    734     }
    735 
    736     /**
    737      * GATT Server set the number of handles to reserve for this service
    738      *
    739      * @param index the bluetooth gatt service
    740      * @param numHandles number of handles to reserve
    741      * @throws Exception
    742      */
    743     @Rpc(description = "GATT Server Set the number of handles to reserve for this service")
    744     public void gattServerServiceSetHandlesToReserve(
    745             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
    746             @RpcParameter(name = "numHandles") Integer numHandles) throws Exception {
    747         if (mGattServiceList.get(serviceIndex) == null) {
    748             throw new Exception("Invalid serviceIndex input:" + Integer.toString(serviceIndex));
    749         }
    750         Class bluetoothGattServiceClass = Class.forName("android.bluetooth.BluetoothGattService");
    751         Method setHandlesMethod = bluetoothGattServiceClass.getMethod(
    752             "setHandles", int.class);
    753         setHandlesMethod.invoke(mGattServiceList.get(serviceIndex), numHandles);
    754     }
    755 
    756     /**
    757      * GATT Server set service advertise perferred value
    758      *
    759      * @param index the bluetooth gatt service
    760      * @param isPreferred if advertisement is preferred or not
    761      * @throws Exception
    762      */
    763     @Rpc(description = "GATT Server Set the number of handles to reserve for this service")
    764     public void gattServerServiceIsAdvertisePreferred(
    765             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
    766             @RpcParameter(name = "isPreferred") Boolean isPreferred) throws Exception {
    767         if (mGattServiceList.get(serviceIndex) == null) {
    768             throw new Exception("Invalid serviceIndex input:" + Integer.toString(serviceIndex));
    769         }
    770         Class bluetoothGattServiceClass = Class.forName("android.bluetooth.BluetoothGattService");
    771         Method setAdvertisePreferredMethod = bluetoothGattServiceClass.getMethod(
    772             "setAdvertisePrefereed", boolean.class);
    773         setAdvertisePreferredMethod.invoke(mGattServiceList.get(serviceIndex), isPreferred);
    774     }
    775 
    776     /**
    777      * GATT Service add included service.
    778      *
    779      * @param index the bluetooth gatt service
    780      * @param serviceIncludedIndex index of the service to be included
    781      * @throws Exception
    782      */
    783     @Rpc(description = "Gatt Server add included service")
    784     public void gattServerServiceaddIncludedService(
    785             @RpcParameter(name = "serviceIndex") Integer serviceIndex,
    786             @RpcParameter(name = "serviceIncludedIndex") Integer serviceIncludedIndex)
    787             throws Exception {
    788         if (mGattServiceList.get(serviceIndex) == null) {
    789             throw new Exception("Invalid serviceIndex input:" + Integer.toString(serviceIndex));
    790         }
    791         if (mGattServiceList.get(serviceIncludedIndex) == null) {
    792             throw new Exception("Invalid serviceIncludedIndex input:" + Integer.toString(
    793                 serviceIncludedIndex));
    794         }
    795         Class bluetoothGattServiceClass = Class.forName("android.bluetooth.BluetoothGattService");
    796         Method addIncludedServiceMethod = bluetoothGattServiceClass.getMethod(
    797             "addIncludedService", BluetoothGattService.class);
    798         addIncludedServiceMethod.invoke(
    799             mGattServiceList.get(serviceIndex), mGattServiceList.get(serviceIncludedIndex));
    800     }
    801 
    802     /**
    803      * Set value to a bluetooth gatt characteristic
    804      *
    805      * @param index the bluetooth gatt characteristic
    806      * @param value value
    807      * @throws Exception
    808      */
    809     @Rpc(description = "add descriptor to blutooth gatt characteristic")
    810     public boolean gattServerCharacteristicSetStringValue(
    811             @RpcParameter(name = "index") Integer index,
    812             @RpcParameter(name = "value") String value) throws Exception {
    813         if (mCharacteristicList.get(index) != null) {
    814             return mCharacteristicList.get(index).setValue(value);
    815         } else {
    816             throw new Exception("Invalid index input:" + index);
    817         }
    818     }
    819 
    820     /**
    821      * Set value to a bluetooth gatt characteristic
    822      *
    823      * @param index the bluetooth gatt characteristic
    824      * @param value value
    825      * @throws Exception
    826      */
    827     @Rpc(description = "add descriptor to blutooth gatt characteristic")
    828     public boolean gattServerCharacteristicSetIntValue(@RpcParameter(name = "index") Integer index,
    829             @RpcParameter(name = "value") Integer value,
    830             @RpcParameter(name = "type") Integer type,
    831             @RpcParameter(name = "offset") Integer offset)
    832             throws Exception {
    833         if (mCharacteristicList.get(index) != null) {
    834             return mCharacteristicList.get(index).setValue(value, type, offset);
    835         } else {
    836             throw new Exception("Invalid index input:" + index);
    837         }
    838     }
    839 
    840     /**
    841      * Set the instance id of the Bluetooth Gatt Characteristic
    842      *
    843      * @param index the bluetooth gatt characteristic
    844      * @param instanceId the instanceId to set
    845      * @throws Exception
    846      */
    847     @Rpc(description = "Set Caracteristic Instance id")
    848     public void gattServerCharacteristicSetInstanceId(@RpcParameter(name = "index") Integer index,
    849             @RpcParameter(name = "instanceId") Integer instanceId)
    850             throws Exception {
    851         if (mCharacteristicList.get(index) != null) {
    852             mCharacteristicList.get(index).setInstanceId(instanceId);
    853         } else {
    854             throw new Exception("Invalid index input:" + index);
    855         }
    856     }
    857 
    858     /**
    859      * Set the instance id of the Bluetooth Gatt Descriptor
    860      *
    861      * @param index the bluetooth gatt descriptor
    862      * @param instanceId the instanceId to set
    863      * @throws Exception
    864      */
    865     @Rpc(description = "Set Descriptor Instance Id")
    866     public void gattServerDescriptorSetInstanceId(@RpcParameter(name = "index") Integer index,
    867             @RpcParameter(name = "instanceId") Integer instanceId)
    868             throws Exception {
    869         if (mDescriptorList.get(index) != null) {
    870             Class bluetoothGattDescriptorClass = Class.forName(
    871                 "android.bluetooth.BluetoothGattDescriptor");
    872             Method setInstanceIdMethod = bluetoothGattDescriptorClass.getMethod(
    873                 "setInstanceId", int.class);
    874             setInstanceIdMethod.invoke(
    875                 mDescriptorList.get(index), instanceId);
    876         } else {
    877             throw new Exception("Invalid index input:" + index);
    878         }
    879     }
    880 
    881     /**
    882      * Get the instance id of the Bluetooth Gatt Characteristic
    883      *
    884      * @param index the bluetooth gatt characteristic
    885      * @throws Exception
    886      * @return the instance id of the characteristic
    887      */
    888     @Rpc(description = "add descriptor to blutooth gatt characteristic")
    889     public int gattServerCharacteristicGetInstanceId(
    890             @RpcParameter(name = "index") Integer index)
    891             throws Exception {
    892         if (mCharacteristicList.get(index) != null) {
    893             return mCharacteristicList.get(index).getInstanceId();
    894         } else {
    895             throw new Exception("Invalid index input:" + index);
    896         }
    897     }
    898 
    899     /**
    900      * Create a new GattCallback object
    901      *
    902      * @return the index of the callback object
    903      */
    904     @Rpc(description = "Create a new GattCallback object")
    905     public Integer gattServerCreateGattServerCallback() {
    906         sGattServerCallbackCount += 1;
    907         int index = sGattServerCallbackCount;
    908         mBluetoothGattServerCallbackList.put(index, new BtGattServerCallback(index));
    909         return index;
    910     }
    911 
    912     /**
    913      * Create a new Descriptor object
    914      *
    915      * @param descriptorUuid the UUID for this descriptor
    916      * @param permissions Permissions for this descriptor
    917      * @return the index of the Descriptor object
    918      */
    919     @Rpc(description = "Create a new Descriptor object")
    920     public int gattServerCreateBluetoothGattDescriptor(
    921             @RpcParameter(name = "descriptorUuid") String descriptorUuid,
    922             @RpcParameter(name = "permissions") Integer permissions) {
    923         sDescriptorCount += 1;
    924         int index = sDescriptorCount;
    925         BluetoothGattDescriptor descriptor =
    926                 new BluetoothGattDescriptor(UUID.fromString(descriptorUuid), permissions);
    927         mDescriptorList.put(index, descriptor);
    928         return index;
    929     }
    930 
    931     private class BtGattServerCallback extends BluetoothGattServerCallback {
    932         private final Bundle mResults;
    933         private final int mIndex;
    934         private final String mEventType;
    935 
    936         BtGattServerCallback(int idx) {
    937             mResults = new Bundle();
    938             mEventType = "GattServer";
    939             mIndex = idx;
    940         }
    941 
    942         @Override
    943         public void onServiceAdded(int status, BluetoothGattService service) {
    944             Log.d("gatt_server change onServiceAdded " + mEventType + " " + mIndex);
    945             mResults.putString("serviceUuid", service.getUuid().toString());
    946             mResults.putInt("instanceId", service.getInstanceId());
    947             mEventFacade.postEvent(mEventType + mIndex + "onServiceAdded", mResults.clone());
    948             mResults.clear();
    949         }
    950 
    951         @Override
    952         public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset,
    953                 BluetoothGattCharacteristic characteristic) {
    954             Log.d("gatt_server change onCharacteristicReadRequest " + mEventType + " " + mIndex);
    955             mResults.putInt("requestId", requestId);
    956             mResults.putInt("offset", offset);
    957             mResults.putInt("instanceId", characteristic.getInstanceId());
    958             mResults.putInt("properties", characteristic.getProperties());
    959             mResults.putString("uuid", characteristic.getUuid().toString());
    960             mResults.putInt("permissions", characteristic.getPermissions());
    961             mEventFacade.postEvent(
    962                     mEventType + mIndex + "onCharacteristicReadRequest", mResults.clone());
    963             mResults.clear();
    964         }
    965 
    966         @Override
    967         public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
    968                 BluetoothGattCharacteristic characteristic, boolean preparedWrite,
    969                 boolean responseNeeded, int offset, byte[] value) {
    970             Log.d("gatt_server change onCharacteristicWriteRequest " + mEventType + " " + mIndex);
    971             mResults.putInt("requestId", requestId);
    972             mResults.putInt("offset", offset);
    973             mResults.putParcelable("BluetoothDevice", device);
    974             mResults.putBoolean("preparedWrite", preparedWrite);
    975             mResults.putBoolean("responseNeeded", responseNeeded);
    976             mResults.putByteArray("value", value);
    977             mResults.putInt("instanceId", characteristic.getInstanceId());
    978             mResults.putInt("properties", characteristic.getProperties());
    979             mResults.putString("uuid", characteristic.getUuid().toString());
    980             mResults.putInt("permissions", characteristic.getPermissions());
    981             mEventFacade.postEvent(
    982                     mEventType + mIndex + "onCharacteristicWriteRequest", mResults.clone());
    983             mResults.clear();
    984 
    985         }
    986 
    987         @Override
    988         public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset,
    989                 BluetoothGattDescriptor descriptor) {
    990             Log.d("gatt_server change onDescriptorReadRequest " + mEventType + " " + mIndex);
    991             mResults.putInt("requestId", requestId);
    992             mResults.putInt("offset", offset);
    993             mResults.putParcelable("BluetoothDevice", device);
    994             mResults.putInt("instanceId", descriptor.getInstanceId());
    995             mResults.putInt("permissions", descriptor.getPermissions());
    996             mResults.putString("uuid", descriptor.getUuid().toString());
    997             mEventFacade.postEvent(
    998                     mEventType + mIndex + "onDescriptorReadRequest", mResults.clone());
    999             mResults.clear();
   1000         }
   1001 
   1002         @Override
   1003         public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
   1004                 BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded,
   1005                 int offset, byte[] value) {
   1006             Log.d("gatt_server change onDescriptorWriteRequest " + mEventType + " " + mIndex);
   1007             mResults.putInt("requestId", requestId);
   1008             mResults.putInt("offset", offset);
   1009             mResults.putParcelable("BluetoothDevice", device);
   1010             mResults.putBoolean("preparedWrite", preparedWrite);
   1011             mResults.putBoolean("responseNeeded", responseNeeded);
   1012             mResults.putByteArray("value", value);
   1013             mResults.putInt("instanceId", descriptor.getInstanceId());
   1014             mResults.putInt("permissions", descriptor.getPermissions());
   1015             mResults.putString("uuid", descriptor.getUuid().toString());
   1016             mEventFacade.postEvent(
   1017                     mEventType + mIndex + "onDescriptorWriteRequest", mResults.clone());
   1018             mResults.clear();
   1019         }
   1020 
   1021         @Override
   1022         public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
   1023             Log.d("gatt_server change onExecuteWrite " + mEventType + " " + mIndex);
   1024             mResults.putParcelable("BluetoothDevice", device);
   1025             mResults.putInt("requestId", requestId);
   1026             mResults.putBoolean("execute", execute);
   1027             mEventFacade.postEvent(mEventType + mIndex + "onExecuteWrite", mResults.clone());
   1028             mResults.clear();
   1029         }
   1030 
   1031         @Override
   1032         public void onNotificationSent(BluetoothDevice device, int status) {
   1033             Log.d("gatt_server change onNotificationSent " + mEventType + " " + mIndex);
   1034             mResults.putParcelable("BluetoothDevice", device);
   1035             mResults.putInt("status", status);
   1036             mEventFacade.postEvent(mEventType + mIndex + "onNotificationSent", mResults.clone());
   1037             mResults.clear();
   1038         }
   1039 
   1040         @Override
   1041         public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
   1042             Log.d("gatt_server change onConnectionStateChange " + mEventType + " " + mIndex);
   1043             if (newState == BluetoothProfile.STATE_CONNECTED) {
   1044                 Log.d("State Connected to mac address " + device.getAddress() + " status "
   1045                         + status);
   1046             } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
   1047                 Log.d("State Disconnected from mac address "
   1048                         + device.getAddress() + " status " + status);
   1049             }
   1050             mResults.putParcelable("BluetoothDevice", device);
   1051             mResults.putInt("status", status);
   1052             mResults.putInt("newState", newState);
   1053             mEventFacade.postEvent(
   1054                     mEventType + mIndex + "onConnectionStateChange", mResults.clone());
   1055             mResults.clear();
   1056         }
   1057 
   1058         @Override
   1059         public void onMtuChanged(BluetoothDevice device, int mtu) {
   1060             Log.d("gatt_server change onMtuChanged " + mEventType + " " + mIndex);
   1061             mResults.putParcelable("BluetoothDevice", device);
   1062             mResults.putInt("MTU", mtu);
   1063             mEventFacade.postEvent(mEventType + mIndex + "onMtuChanged", mResults.clone());
   1064             mResults.clear();
   1065         }
   1066 
   1067         @Override
   1068         public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
   1069             Log.d("gatt_server change onPhyRead " + mEventType + " " + mIndex);
   1070             mResults.putParcelable("BluetoothDevice", device);
   1071             mResults.putInt("TxPhy", txPhy);
   1072             mResults.putInt("RxPhy", rxPhy);
   1073             mResults.putInt("Status", status);
   1074             mEventFacade.postEvent(mEventType + mIndex + "onPhyRead", mResults.clone());
   1075             mResults.clear();
   1076         }
   1077 
   1078         @Override
   1079         public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
   1080             Log.d("gatt_server change onPhyUpdate " + mEventType + " " + mIndex);
   1081             mResults.putParcelable("BluetoothDevice", device);
   1082             mResults.putInt("TxPhy", txPhy);
   1083             mResults.putInt("RxPhy", rxPhy);
   1084             mResults.putInt("Status", status);
   1085             mEventFacade.postEvent(mEventType + mIndex + "onPhyUpdate", mResults.clone());
   1086             mResults.clear();
   1087         }
   1088 
   1089         public void onConnectionUpdated(BluetoothDevice device, int interval, int latency,
   1090                                             int timeout, int status) {
   1091             Log.d("gatt_server change onConnecitonUpdated " + mEventType + " " + mIndex
   1092                     + ", interval: " + interval + ", latency: " + latency
   1093                     + ", timeout: " + timeout + ", status: " + status);
   1094 
   1095             mResults.putInt("Status", status);
   1096             mResults.putInt("Interval", interval);
   1097             mResults.putInt("Latency", latency);
   1098             mResults.putInt("Timeout", timeout);
   1099             mEventFacade.postEvent(mEventType + mIndex + "onConnectionUpdated", mResults.clone());
   1100             mResults.clear();
   1101         }
   1102 
   1103     }
   1104 
   1105     @Override
   1106     public void shutdown() {
   1107         if (!mBluetoothGattServerList.isEmpty()) {
   1108             if (mBluetoothGattServerList.values() != null) {
   1109                 for (BluetoothGattServer mBluetoothGattServer : mBluetoothGattServerList.values()) {
   1110                     mBluetoothGattServer.close();
   1111                 }
   1112             }
   1113         }
   1114     }
   1115 }
   1116