Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2016 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 package com.googlecode.android_scripting.facade.bluetooth;
     18 
     19 import java.util.ArrayList;
     20 import java.util.HashMap;
     21 import java.util.List;
     22 import java.util.UUID;
     23 import java.util.concurrent.Callable;
     24 
     25 import android.app.Service;
     26 import android.bluetooth.BluetoothAdapter;
     27 import android.bluetooth.BluetoothDevice;
     28 import android.bluetooth.BluetoothGatt;
     29 import android.bluetooth.BluetoothGattServer;
     30 import android.bluetooth.BluetoothManager;
     31 import android.bluetooth.BluetoothGattCharacteristic;
     32 import android.bluetooth.BluetoothGattServerCallback;
     33 import android.bluetooth.BluetoothGattDescriptor;
     34 import android.bluetooth.BluetoothGattService;
     35 import android.bluetooth.BluetoothProfile;
     36 import android.content.Context;
     37 import android.os.Bundle;
     38 
     39 import com.googlecode.android_scripting.ConvertUtils;
     40 import com.googlecode.android_scripting.Log;
     41 import com.googlecode.android_scripting.MainThread;
     42 import com.googlecode.android_scripting.facade.EventFacade;
     43 import com.googlecode.android_scripting.facade.FacadeManager;
     44 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
     45 import com.googlecode.android_scripting.rpc.Rpc;
     46 import com.googlecode.android_scripting.rpc.RpcParameter;
     47 
     48 public class GattServerFacade extends RpcReceiver {
     49   private final EventFacade mEventFacade;
     50   private BluetoothAdapter mBluetoothAdapter;
     51   private BluetoothManager mBluetoothManager;
     52   private final Service mService;
     53   private final Context mContext;
     54   private final HashMap<Integer, BluetoothGattCharacteristic> mCharacteristicList;
     55   private final HashMap<Integer, BluetoothGattDescriptor> mDescriptorList;
     56   private final HashMap<Integer, BluetoothGattServer> mBluetoothGattServerList;
     57   private final HashMap<Integer, myBluetoothGattServerCallback> mBluetoothGattServerCallbackList;
     58   private final HashMap<Integer, BluetoothGattService> mGattServiceList;
     59   private final HashMap<Integer, List<BluetoothGattService>> mBluetoothGattDiscoveredServicesList;
     60   private final HashMap<Integer, List<BluetoothDevice>> mGattServerDiscoveredDevicesList;
     61   private static int CharacteristicCount;
     62   private static int DescriptorCount;
     63   private static int GattServerCallbackCount;
     64   private static int GattServerCount;
     65   private static int GattServiceCount;
     66 
     67   public GattServerFacade(FacadeManager manager) {
     68     super(manager);
     69     mService = manager.getService();
     70     mContext = mService.getApplicationContext();
     71     mBluetoothAdapter = MainThread.run(mService, new Callable<BluetoothAdapter>() {
     72       @Override
     73       public BluetoothAdapter call() throws Exception {
     74         return BluetoothAdapter.getDefaultAdapter();
     75       }
     76     });
     77     mBluetoothManager = (BluetoothManager) mContext.getSystemService(Service.BLUETOOTH_SERVICE);
     78     mEventFacade = manager.getReceiver(EventFacade.class);
     79     mCharacteristicList = new HashMap<Integer, BluetoothGattCharacteristic>();
     80     mDescriptorList = new HashMap<Integer, BluetoothGattDescriptor>();
     81     mBluetoothGattServerList = new HashMap<Integer, BluetoothGattServer>();
     82     mBluetoothGattServerCallbackList = new HashMap<Integer, myBluetoothGattServerCallback>();
     83     mGattServiceList = new HashMap<Integer, BluetoothGattService>();
     84     mBluetoothGattDiscoveredServicesList = new HashMap<Integer, List<BluetoothGattService>>();
     85     mGattServerDiscoveredDevicesList = new HashMap<Integer, List<BluetoothDevice>>();
     86   }
     87 
     88   /**
     89    * Open a new Gatt server.
     90    *
     91    * @param index the bluetooth gatt server callback to open on
     92    * @return the index of the newly opened gatt server
     93    * @throws Exception
     94    */
     95   @Rpc(description = "Open new gatt server")
     96   public int gattServerOpenGattServer(@RpcParameter(name = "index") Integer index)
     97       throws Exception {
     98     if (mBluetoothGattServerCallbackList.get(index) != null) {
     99       BluetoothGattServer mGattServer =
    100           mBluetoothManager.openGattServer(mContext, mBluetoothGattServerCallbackList.get(index));
    101       GattServerCount += 1;
    102       int in = GattServerCount;
    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    * @param serviceIndex the service to add to the bluetooth gatt server
    136    * @throws Exception
    137    */
    138   @Rpc(description = "Clear services from bluetooth gatt server")
    139   public void gattServerClearServices(@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, @RpcParameter(name = "offset") Integer offset,
    182       @RpcParameter(name = "value") byte[] value) throws Exception {
    183 
    184     BluetoothGattServer gattServer = mBluetoothGattServerList.get(gattServerIndex);
    185     if (gattServer == null)
    186       throw new Exception("Invalid gattServerIndex: " + Integer.toString(gattServerIndex));
    187     List<BluetoothDevice> connectedDevices = mGattServerDiscoveredDevicesList.get(gattServerIndex);
    188     if (connectedDevices == null)
    189       throw new Exception(
    190           "Connected device list empty for gattServerIndex:" + Integer.toString(gattServerIndex));
    191     BluetoothDevice bluetoothDevice = connectedDevices.get(bluetoothDeviceIndex);
    192     if (bluetoothDevice == null)
    193       throw new Exception(
    194           "Invalid bluetoothDeviceIndex: " + Integer.toString(bluetoothDeviceIndex));
    195     gattServer.sendResponse(bluetoothDevice, requestId, status, offset, value);
    196   }
    197 
    198   /**
    199    * Notify that characteristic was changed
    200    *
    201    * @param gattServerIndex the gatt server index
    202    * @param bluetoothDeviceIndex the remotely connected bluetooth device
    203    * @param characteristicIndex characteristic index
    204    * @param confirm shall we expect confirmation
    205    * @throws Exception
    206    */
    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     List<BluetoothDevice> connectedDevices = mGattServerDiscoveredDevicesList.get(gattServerIndex);
    218     if (connectedDevices == null)
    219       throw new Exception(
    220           "Connected device list empty for gattServerIndex:" + Integer.toString(gattServerIndex));
    221     BluetoothDevice bluetoothDevice = connectedDevices.get(bluetoothDeviceIndex);
    222     if (bluetoothDevice == null)
    223       throw new Exception(
    224           "Invalid bluetoothDeviceIndex: " + Integer.toString(bluetoothDeviceIndex));
    225 
    226     BluetoothGattCharacteristic bluetoothCharacteristic = mCharacteristicList.get(characteristicIndex);
    227     if (bluetoothCharacteristic == null)
    228       throw new Exception(
    229           "Invalid characteristicIndex: " + Integer.toString(characteristicIndex));
    230 
    231     gattServer.notifyCharacteristicChanged(bluetoothDevice, bluetoothCharacteristic, confirm);
    232   }
    233 
    234   /**
    235    * Create a new bluetooth gatt service
    236    *
    237    * @param uuid the UUID that characterises the service
    238    * @param serviceType the service type
    239    * @return The index of the new bluetooth gatt service
    240    */
    241   @Rpc(description = "Create new bluetooth gatt service")
    242   public int gattServerCreateService(@RpcParameter(name = "uuid") String uuid,
    243       @RpcParameter(name = "serviceType") Integer serviceType) {
    244     GattServiceCount += 1;
    245     int index = GattServiceCount;
    246     mGattServiceList.put(index, new BluetoothGattService(UUID.fromString(uuid), serviceType));
    247     return index;
    248   }
    249 
    250   /**
    251    * Add a characteristic to a bluetooth gatt service
    252    *
    253    * @param index the bluetooth gatt service index
    254    * @param serviceUuid the service Uuid to get
    255    * @param characteristicIndex the character index to use
    256    * @throws Exception
    257    */
    258   @Rpc(description = "Add a characteristic to a bluetooth gatt service")
    259   public void gattServiceAddCharacteristic(@RpcParameter(name = "index") Integer index,
    260       @RpcParameter(name = "serviceUuid") String serviceUuid,
    261       @RpcParameter(name = "characteristicIndex") Integer characteristicIndex) throws Exception {
    262     if (mBluetoothGattServerList.get(index) != null
    263         && mBluetoothGattServerList.get(index).getService(UUID.fromString(serviceUuid)) != null
    264         && mCharacteristicList.get(characteristicIndex) != null) {
    265       mBluetoothGattServerList.get(index).getService(UUID.fromString(serviceUuid))
    266           .addCharacteristic(mCharacteristicList.get(characteristicIndex));
    267     } else {
    268       if (mBluetoothGattServerList.get(index) == null) {
    269         throw new Exception("Invalid index input:" + index);
    270       } else if (mCharacteristicList.get(characteristicIndex) == null) {
    271         throw new Exception("Invalid characteristicIndex input:" + characteristicIndex);
    272       } else {
    273         throw new Exception("Invalid serviceUuid input:" + serviceUuid);
    274       }
    275     }
    276   }
    277 
    278   /**
    279    * Add a characteristic to a bluetooth gatt service
    280    *
    281    * @param index the bluetooth gatt service to add a characteristic to
    282    * @param characteristicIndex the characteristic to add
    283    * @throws Exception
    284    */
    285   @Rpc(description = "Add a characteristic to a bluetooth gatt service")
    286   public void gattServerAddCharacteristicToService(@RpcParameter(name = "index") Integer index,
    287       @RpcParameter(name = "characteristicIndex") Integer characteristicIndex
    288 
    289   ) throws Exception {
    290     if (mGattServiceList.get(index) != null) {
    291       if (mCharacteristicList.get(characteristicIndex) != null) {
    292         mGattServiceList.get(index).addCharacteristic(mCharacteristicList.get(characteristicIndex));
    293       } else {
    294         throw new Exception("Invalid index input:" + index);
    295       }
    296     } else {
    297       throw new Exception("Invalid index input:" + index);
    298     }
    299   }
    300 
    301   /**
    302    * Close a bluetooth gatt
    303    *
    304    * @param index the bluetooth gatt index to close
    305    * @throws Exception
    306    */
    307   @Rpc(description = "Close a bluetooth gatt")
    308   public void gattServerClose(@RpcParameter(name = "index") Integer index) throws Exception {
    309     if (mBluetoothGattServerList.get(index) != null) {
    310       mBluetoothGattServerList.get(index).close();
    311     } else {
    312       throw new Exception("Invalid index input:" + index);
    313     }
    314   }
    315 
    316   /**
    317    * Get a list of Bluetooth Devices connnected to the bluetooth gatt
    318    *
    319    * @param index the bluetooth gatt index
    320    * @return List of BluetoothDevice Objects
    321    * @throws Exception
    322    */
    323   @Rpc(description = "Get a list of Bluetooth Devices connnected to the bluetooth gatt")
    324   public List<BluetoothDevice> gattGetConnectedDevices(@RpcParameter(name = "index") Integer index)
    325       throws Exception {
    326     if (mBluetoothGattServerList.get(index) != null) {
    327       return mBluetoothGattServerList.get(index).getConnectedDevices();
    328     } else {
    329       throw new Exception("Invalid index input:" + index);
    330     }
    331   }
    332 
    333   /**
    334    * Get the service from an input UUID
    335    *
    336    * @param index the bluetooth gatt index
    337    * @return BluetoothGattService related to the bluetooth gatt
    338    * @throws Exception
    339    */
    340   @Rpc(description = "Get the service from an input UUID")
    341   public ArrayList<String> gattGetServiceUuidList(@RpcParameter(name = "index") Integer index)
    342       throws Exception {
    343     if (mBluetoothGattServerList.get(index) != null) {
    344       ArrayList<String> serviceUuidList = new ArrayList<String>();
    345       for (BluetoothGattService service : mBluetoothGattServerList.get(index).getServices()) {
    346         serviceUuidList.add(service.getUuid().toString());
    347       }
    348       return serviceUuidList;
    349     } else {
    350       throw new Exception("Invalid index input:" + index);
    351     }
    352   }
    353 
    354   /**
    355    * Get the service from an input UUID
    356    *
    357    * @param index the bluetooth gatt index
    358    * @param uuid the String uuid that matches the service
    359    * @return BluetoothGattService related to the bluetooth gatt
    360    * @throws Exception
    361    */
    362   @Rpc(description = "Get the service from an input UUID")
    363   public BluetoothGattService gattGetService(@RpcParameter(name = "index") Integer index,
    364       @RpcParameter(name = "uuid") String uuid) throws Exception {
    365     if (mBluetoothGattServerList.get(index) != null) {
    366       return mBluetoothGattServerList.get(index).getService(UUID.fromString(uuid));
    367     } else {
    368       throw new Exception("Invalid index input:" + index);
    369     }
    370   }
    371 
    372   /**
    373    * Add a descriptor to a bluetooth gatt characteristic
    374    *
    375    * @param index the bluetooth gatt characteristic to add a descriptor to
    376    * @param descriptorIndex the descritor index to add to the characteristic
    377    * @throws Exception
    378    */
    379   @Rpc(description = "add descriptor to blutooth gatt characteristic")
    380   public void gattServerCharacteristicAddDescriptor(@RpcParameter(name = "index") Integer index,
    381       @RpcParameter(name = "descriptorIndex") Integer descriptorIndex) throws Exception {
    382     if (mCharacteristicList.get(index) != null) {
    383       if (mDescriptorList.get(descriptorIndex) != null) {
    384         mCharacteristicList.get(index).addDescriptor(mDescriptorList.get(descriptorIndex));
    385       } else {
    386         throw new Exception("Invalid descriptorIndex input:" + descriptorIndex);
    387       }
    388     } else {
    389       throw new Exception("Invalid index input:" + index);
    390     }
    391   }
    392 
    393   /**
    394    * Create a new Characteristic object
    395    *
    396    * @param characteristicUuid uuid The UUID for this characteristic
    397    * @param property Properties of this characteristic
    398    * @param permission permissions Permissions for this characteristic
    399    * @return
    400    */
    401   @Rpc(description = "Create a new Characteristic object")
    402   public int gattServerCreateBluetoothGattCharacteristic(
    403       @RpcParameter(name = "characteristicUuid") String characteristicUuid,
    404       @RpcParameter(name = "property") Integer property,
    405       @RpcParameter(name = "permission") Integer permission) {
    406     CharacteristicCount += 1;
    407     int index = CharacteristicCount;
    408     BluetoothGattCharacteristic characteristic =
    409         new BluetoothGattCharacteristic(UUID.fromString(characteristicUuid), property, permission);
    410     mCharacteristicList.put(index, characteristic);
    411     return index;
    412   }
    413 
    414   /**
    415    * Set value to a bluetooth gatt characteristic
    416    *
    417    * @param index the bluetooth gatt characteristic
    418    * @param value value
    419    * @throws Exception
    420    */
    421   @Rpc(description = "add descriptor to blutooth gatt characteristic")
    422   public void gattServerCharacteristicSetValue(@RpcParameter(name = "index") Integer index,
    423       @RpcParameter(name = "value") byte[] value) throws Exception {
    424     if (mCharacteristicList.get(index) != null) {
    425       mCharacteristicList.get(index).setValue(value);
    426     } else {
    427       throw new Exception("Invalid index input:" + index);
    428     }
    429   }
    430 
    431   /**
    432    * Create a new GattCallback object
    433    *
    434    * @return the index of the callback object
    435    */
    436   @Rpc(description = "Create a new GattCallback object")
    437   public Integer gattServerCreateGattServerCallback() {
    438     GattServerCallbackCount += 1;
    439     int index = GattServerCallbackCount;
    440     mBluetoothGattServerCallbackList.put(index, new myBluetoothGattServerCallback(index));
    441     return index;
    442   }
    443 
    444   /**
    445    * Create a new Descriptor object
    446    *
    447    * @param descriptorUuid the UUID for this descriptor
    448    * @param permissions Permissions for this descriptor
    449    * @return the index of the Descriptor object
    450    */
    451   @Rpc(description = "Create a new Descriptor object")
    452   public int gattServerCreateBluetoothGattDescriptor(
    453       @RpcParameter(name = "descriptorUuid") String descriptorUuid,
    454       @RpcParameter(name = "permissions") Integer permissions) {
    455     DescriptorCount += 1;
    456     int index = DescriptorCount;
    457     BluetoothGattDescriptor descriptor =
    458         new BluetoothGattDescriptor(UUID.fromString(descriptorUuid), permissions);
    459     mDescriptorList.put(index, descriptor);
    460     return index;
    461   }
    462 
    463   private class myBluetoothGattServerCallback extends BluetoothGattServerCallback {
    464     private final Bundle mResults;
    465     private final int index;
    466     private final String mEventType;
    467 
    468     public myBluetoothGattServerCallback(int idx) {
    469       mResults = new Bundle();
    470       mEventType = "GattServer";
    471       index = idx;
    472     }
    473 
    474     @Override
    475     public void onServiceAdded(int status, BluetoothGattService service) {
    476       Log.d("gatt_server change onServiceAdded " + mEventType + " " + index);
    477       mResults.putString("serviceUuid", service.getUuid().toString());
    478       mResults.putInt("instanceId", service.getInstanceId());
    479       mEventFacade.postEvent(mEventType + index + "onServiceAdded", mResults.clone());
    480       mResults.clear();
    481     }
    482 
    483     @Override
    484     public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset,
    485         BluetoothGattCharacteristic characteristic) {
    486       Log.d("gatt_server change onCharacteristicReadRequest " + mEventType + " " + index);
    487       mResults.putInt("requestId", requestId);
    488       mResults.putInt("offset", offset);
    489       mResults.putInt("instanceId", characteristic.getInstanceId());
    490       mResults.putInt("properties", characteristic.getProperties());
    491       mResults.putString("uuid", characteristic.getUuid().toString());
    492       mResults.putInt("permissions", characteristic.getPermissions());
    493       mEventFacade.postEvent(mEventType + index + "onCharacteristicReadRequest", mResults.clone());
    494       mResults.clear();
    495     }
    496 
    497     @Override
    498     public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
    499         BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded,
    500         int offset, byte[] value) {
    501       Log.d("gatt_server change onCharacteristicWriteRequest " + mEventType + " " + index);
    502       mResults.putInt("requestId", requestId);
    503       mResults.putInt("offset", offset);
    504       mResults.putParcelable("BluetoothDevice", device);
    505       mResults.putBoolean("preparedWrite", preparedWrite);
    506       mResults.putBoolean("responseNeeded", responseNeeded);
    507       mResults.putByteArray("value", value);
    508       mResults.putInt("instanceId", characteristic.getInstanceId());
    509       mResults.putInt("properties", characteristic.getProperties());
    510       mResults.putString("uuid", characteristic.getUuid().toString());
    511       mResults.putInt("permissions", characteristic.getPermissions());
    512       mEventFacade.postEvent(mEventType + index + "onCharacteristicWriteRequest", mResults.clone());
    513       mResults.clear();
    514 
    515     }
    516 
    517     @Override
    518     public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset,
    519         BluetoothGattDescriptor descriptor) {
    520       Log.d("gatt_server change onDescriptorReadRequest " + mEventType + " " + index);
    521       mResults.putInt("requestId", requestId);
    522       mResults.putInt("offset", offset);
    523       mResults.putParcelable("BluetoothDevice", device);
    524       mResults.putInt("instanceId", descriptor.getInstanceId());
    525       mResults.putInt("permissions", descriptor.getPermissions());
    526       mResults.putString("uuid", descriptor.getUuid().toString());
    527       mEventFacade.postEvent(mEventType + index + "onDescriptorReadRequest", mResults.clone());
    528       mResults.clear();
    529     }
    530 
    531     @Override
    532     public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
    533         BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded,
    534         int offset, byte[] value) {
    535       Log.d("gatt_server change onDescriptorWriteRequest " + mEventType + " " + index);
    536       mResults.putInt("requestId", requestId);
    537       mResults.putInt("offset", offset);
    538       mResults.putParcelable("BluetoothDevice", device);
    539       mResults.putBoolean("preparedWrite", preparedWrite);
    540       mResults.putBoolean("responseNeeded", responseNeeded);
    541       mResults.putByteArray("value", value);
    542       mResults.putInt("instanceId", descriptor.getInstanceId());
    543       mResults.putInt("permissions", descriptor.getPermissions());
    544       mResults.putString("uuid", descriptor.getUuid().toString());
    545       mEventFacade.postEvent(mEventType + index + "onDescriptorWriteRequest", mResults.clone());
    546       mResults.clear();
    547     }
    548 
    549     @Override
    550     public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
    551       Log.d("gatt_server change onExecuteWrite " + mEventType + " " + index);
    552       mResults.putParcelable("BluetoothDevice", device);
    553       mResults.putInt("requestId", requestId);
    554       mResults.putBoolean("execute", execute);
    555       mEventFacade.postEvent(mEventType + index + "onExecuteWrite", mResults.clone());
    556       mResults.clear();
    557     }
    558 
    559     @Override
    560     public void onNotificationSent(BluetoothDevice device, int status) {
    561       Log.d("gatt_server change onNotificationSent " + mEventType + " " + index);
    562       mResults.putParcelable("BluetoothDevice", device);
    563       mResults.putInt("status", status);
    564       mEventFacade.postEvent(mEventType + index + "onNotificationSent", mResults.clone());
    565       mResults.clear();
    566     }
    567 
    568     @Override
    569     public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
    570       Log.d("gatt_server change onConnectionStateChange " + mEventType + " " + index);
    571       if (newState == BluetoothProfile.STATE_CONNECTED) {
    572         Log.d("State Connected to mac address " + device.getAddress() + " status " + status);
    573       } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
    574         Log.d("State Disconnected from mac address " + device.getAddress() + " status " + status);
    575       }
    576       mResults.putParcelable("BluetoothDevice", device);
    577       mResults.putInt("status", status);
    578       mResults.putInt("newState", newState);
    579       mEventFacade.postEvent(mEventType + index + "onConnectionStateChange", mResults.clone());
    580       mResults.clear();
    581     }
    582 
    583     @Override
    584     public void onMtuChanged(BluetoothDevice device, int mtu) {
    585       Log.d("gatt_server change onMtuChanged " + mEventType + " " + index);
    586       mResults.putParcelable("BluetoothDevice", device);
    587       mResults.putInt("mtu", mtu);
    588       mEventFacade.postEvent(mEventType + index + "onMtuChanged", mResults.clone());
    589       mResults.clear();
    590     }
    591   }
    592 
    593   @Override
    594   public void shutdown() {
    595     if (!mBluetoothGattServerList.isEmpty()) {
    596       if (mBluetoothGattServerList.values() != null) {
    597         for (BluetoothGattServer mBluetoothGattServer : mBluetoothGattServerList.values()) {
    598           mBluetoothGattServer.close();
    599         }
    600       }
    601     }
    602   }
    603 }
    604