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
17package com.googlecode.android_scripting.facade.bluetooth;
18
19import java.util.ArrayList;
20import java.util.HashMap;
21import java.util.List;
22import java.util.UUID;
23import java.util.concurrent.Callable;
24
25import android.app.Service;
26import android.bluetooth.BluetoothAdapter;
27import android.bluetooth.BluetoothDevice;
28import android.bluetooth.BluetoothGatt;
29import android.bluetooth.BluetoothGattServer;
30import android.bluetooth.BluetoothManager;
31import android.bluetooth.BluetoothGattCharacteristic;
32import android.bluetooth.BluetoothGattServerCallback;
33import android.bluetooth.BluetoothGattDescriptor;
34import android.bluetooth.BluetoothGattService;
35import android.bluetooth.BluetoothProfile;
36import android.content.Context;
37import android.os.Bundle;
38
39import com.googlecode.android_scripting.ConvertUtils;
40import com.googlecode.android_scripting.Log;
41import com.googlecode.android_scripting.MainThread;
42import com.googlecode.android_scripting.facade.EventFacade;
43import com.googlecode.android_scripting.facade.FacadeManager;
44import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
45import com.googlecode.android_scripting.rpc.Rpc;
46import com.googlecode.android_scripting.rpc.RpcParameter;
47
48public 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