• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.HashMap;
20 import java.util.List;
21 import java.util.concurrent.Callable;
22 
23 import android.app.Service;
24 import android.bluetooth.BluetoothAdapter;
25 import android.bluetooth.le.AdvertiseCallback;
26 import android.bluetooth.le.AdvertiseData;
27 import android.bluetooth.le.AdvertiseData.Builder;
28 import android.bluetooth.le.AdvertiseSettings;
29 import android.bluetooth.le.BluetoothLeAdvertiser;
30 import android.os.Bundle;
31 import android.os.ParcelUuid;
32 
33 import com.googlecode.android_scripting.Log;
34 import com.googlecode.android_scripting.MainThread;
35 import com.googlecode.android_scripting.facade.EventFacade;
36 import com.googlecode.android_scripting.facade.FacadeManager;
37 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
38 import com.googlecode.android_scripting.rpc.Rpc;
39 import com.googlecode.android_scripting.rpc.RpcParameter;
40 
41 /**
42  * BluetoothLe Advertise functions.
43  */
44 
45 public class BluetoothLeAdvertiseFacade extends RpcReceiver {
46 
47     private final EventFacade mEventFacade;
48     private BluetoothAdapter mBluetoothAdapter;
49     private static int BleAdvertiseCallbackCount;
50     private static int BleAdvertiseSettingsCount;
51     private static int BleAdvertiseDataCount;
52     private final HashMap<Integer, myAdvertiseCallback> mAdvertiseCallbackList;
53     private final BluetoothLeAdvertiser mAdvertise;
54     private final Service mService;
55     private Builder mAdvertiseDataBuilder;
56     private android.bluetooth.le.AdvertiseSettings.Builder mAdvertiseSettingsBuilder;
57     private final HashMap<Integer, AdvertiseData> mAdvertiseDataList;
58     private final HashMap<Integer, AdvertiseSettings> mAdvertiseSettingsList;
59 
BluetoothLeAdvertiseFacade(FacadeManager manager)60     public BluetoothLeAdvertiseFacade(FacadeManager manager) {
61         super(manager);
62         mService = manager.getService();
63         mBluetoothAdapter = MainThread.run(mService,
64                 new Callable<BluetoothAdapter>() {
65                     @Override
66                     public BluetoothAdapter call() throws Exception {
67                         return BluetoothAdapter.getDefaultAdapter();
68                     }
69                 });
70         mEventFacade = manager.getReceiver(EventFacade.class);
71         mAdvertiseCallbackList = new HashMap<Integer, myAdvertiseCallback>();
72         mAdvertise = mBluetoothAdapter.getBluetoothLeAdvertiser();
73         mAdvertiseDataList = new HashMap<Integer, AdvertiseData>();
74         mAdvertiseSettingsList = new HashMap<Integer, AdvertiseSettings>();
75         mAdvertiseDataBuilder = new Builder();
76         mAdvertiseSettingsBuilder = new android.bluetooth.le.AdvertiseSettings.Builder();
77     }
78 
79     /**
80      * Constructs a myAdvertiseCallback obj and returns its index
81      *
82      * @return myAdvertiseCallback.index
83      */
84     @Rpc(description = "Generate a new myAdvertisement Object")
bleGenBleAdvertiseCallback()85     public Integer bleGenBleAdvertiseCallback() {
86         BleAdvertiseCallbackCount += 1;
87         int index = BleAdvertiseCallbackCount;
88         myAdvertiseCallback mCallback = new myAdvertiseCallback(index);
89         mAdvertiseCallbackList.put(mCallback.index,
90                 mCallback);
91         return mCallback.index;
92     }
93 
94     /**
95      * Constructs a AdvertiseData obj and returns its index
96      *
97      * @return index
98      */
99     @Rpc(description = "Constructs a new Builder obj for AdvertiseData and returns its index")
bleBuildAdvertiseData()100     public Integer bleBuildAdvertiseData() {
101         BleAdvertiseDataCount += 1;
102         int index = BleAdvertiseDataCount;
103         mAdvertiseDataList.put(index,
104                 mAdvertiseDataBuilder.build());
105         mAdvertiseDataBuilder = new Builder();
106         return index;
107     }
108 
109     /**
110      * Constructs a Advertise Settings obj and returns its index
111      *
112      * @return index
113      */
114     @Rpc(description = "Constructs a new Builder obj for AdvertiseData and returns its index")
bleBuildAdvertiseSettings()115     public Integer bleBuildAdvertiseSettings() {
116         BleAdvertiseSettingsCount += 1;
117         int index = BleAdvertiseSettingsCount;
118         mAdvertiseSettingsList.put(index,
119                 mAdvertiseSettingsBuilder.build());
120         mAdvertiseSettingsBuilder = new android.bluetooth.le.AdvertiseSettings.Builder();
121         return index;
122     }
123 
124     /**
125      * Stops a ble advertisement
126      *
127      * @param index the id of the advertisement to stop advertising on
128      * @throws Exception
129      */
130     @Rpc(description = "Stops an ongoing ble advertisement")
bleStopBleAdvertising( @pcParametername = "index") Integer index)131     public void bleStopBleAdvertising(
132             @RpcParameter(name = "index")
133             Integer index) throws Exception {
134         if (mAdvertiseCallbackList.get(index) != null) {
135             Log.d("bluetooth_le mAdvertise " + index);
136             mAdvertise.stopAdvertising(mAdvertiseCallbackList
137                     .get(index));
138         } else {
139             throw new Exception("Invalid index input:" + Integer.toString(index));
140         }
141     }
142 
143     /**
144      * Starts ble advertising
145      *
146      * @param callbackIndex The advertisementCallback index
147      * @param dataIndex the AdvertiseData index
148      * @param settingsIndex the advertisementsettings index
149      * @throws Exception
150      */
151     @Rpc(description = "Starts ble advertisement")
bleStartBleAdvertising( @pcParametername = "callbackIndex") Integer callbackIndex, @RpcParameter(name = "dataIndex") Integer dataIndex, @RpcParameter(name = "settingsIndex") Integer settingsIndex )152     public void bleStartBleAdvertising(
153             @RpcParameter(name = "callbackIndex")
154             Integer callbackIndex,
155             @RpcParameter(name = "dataIndex")
156             Integer dataIndex,
157             @RpcParameter(name = "settingsIndex")
158             Integer settingsIndex
159             ) throws Exception {
160         AdvertiseData mData = new AdvertiseData.Builder().build();
161         AdvertiseSettings mSettings = new AdvertiseSettings.Builder().build();
162         if (mAdvertiseDataList.get(dataIndex) != null) {
163             mData = mAdvertiseDataList.get(dataIndex);
164         } else {
165             throw new Exception("Invalid dataIndex input:" + Integer.toString(dataIndex));
166         }
167         if (mAdvertiseSettingsList.get(settingsIndex) != null) {
168             mSettings = mAdvertiseSettingsList.get(settingsIndex);
169         } else {
170             throw new Exception("Invalid settingsIndex input:" + Integer.toString(settingsIndex));
171         }
172         if (mAdvertiseCallbackList.get(callbackIndex) != null) {
173             Log.d("bluetooth_le starting a background advertisement on callback index: "
174                     + Integer.toString(callbackIndex));
175             mAdvertise
176                     .startAdvertising(mSettings, mData, mAdvertiseCallbackList.get(callbackIndex));
177         } else {
178             throw new Exception("Invalid callbackIndex input" + Integer.toString(callbackIndex));
179         }
180     }
181 
182     /**
183      * Starts ble advertising with a scanResponse. ScanResponses are created in the same way
184      * AdvertiseData is created since they share the same object type.
185      *
186      * @param callbackIndex The advertisementCallback index
187      * @param dataIndex the AdvertiseData index
188      * @param settingsIndex the advertisementsettings index
189      * @param scanResponseIndex the scanResponse index
190      * @throws Exception
191      */
192     @Rpc(description = "Starts ble advertisement")
bleStartBleAdvertisingWithScanResponse( @pcParametername = "callbackIndex") Integer callbackIndex, @RpcParameter(name = "dataIndex") Integer dataIndex, @RpcParameter(name = "settingsIndex") Integer settingsIndex, @RpcParameter(name = "scanResponseIndex") Integer scanResponseIndex )193     public void bleStartBleAdvertisingWithScanResponse(
194             @RpcParameter(name = "callbackIndex")
195             Integer callbackIndex,
196             @RpcParameter(name = "dataIndex")
197             Integer dataIndex,
198             @RpcParameter(name = "settingsIndex")
199             Integer settingsIndex,
200             @RpcParameter(name = "scanResponseIndex")
201             Integer scanResponseIndex
202             ) throws Exception {
203         AdvertiseData mData = new AdvertiseData.Builder().build();
204         AdvertiseSettings mSettings = new AdvertiseSettings.Builder().build();
205         AdvertiseData mScanResponse = new AdvertiseData.Builder().build();
206 
207         if (mAdvertiseDataList.get(dataIndex) != null) {
208             mData = mAdvertiseDataList.get(dataIndex);
209         } else {
210             throw new Exception("Invalid dataIndex input:" + Integer.toString(dataIndex));
211         }
212         if (mAdvertiseSettingsList.get(settingsIndex) != null) {
213             mSettings = mAdvertiseSettingsList.get(settingsIndex);
214         } else {
215             throw new Exception("Invalid settingsIndex input:" + Integer.toString(settingsIndex));
216         }
217         if (mAdvertiseDataList.get(scanResponseIndex) != null) {
218             mScanResponse = mAdvertiseDataList.get(scanResponseIndex);
219         } else {
220             throw new Exception("Invalid scanResponseIndex input:"
221                     + Integer.toString(settingsIndex));
222         }
223         if (mAdvertiseCallbackList.get(callbackIndex) != null) {
224             Log.d("bluetooth_le starting a background advertise on callback index: "
225                     + Integer.toString(callbackIndex));
226             mAdvertise
227                     .startAdvertising(mSettings, mData, mScanResponse,
228                             mAdvertiseCallbackList.get(callbackIndex));
229         } else {
230             throw new Exception("Invalid callbackIndex input" + Integer.toString(callbackIndex));
231         }
232     }
233 
234     /**
235      * Get ble advertisement settings mode
236      *
237      * @param index the advertise settings object to use
238      * @return the mode of the advertise settings object
239      * @throws Exception
240      */
241     @Rpc(description = "Get ble advertisement settings mode")
bleGetAdvertiseSettingsMode( @pcParametername = "index") Integer index)242     public int bleGetAdvertiseSettingsMode(
243             @RpcParameter(name = "index")
244             Integer index) throws Exception {
245         if (mAdvertiseSettingsList.get(index) != null) {
246             AdvertiseSettings mSettings = mAdvertiseSettingsList.get(index);
247             return mSettings.getMode();
248         } else {
249             throw new Exception("Invalid index input:" + Integer.toString(index));
250         }
251     }
252 
253     /**
254      * Get ble advertisement settings tx power level
255      *
256      * @param index the advertise settings object to use
257      * @return the tx power level of the advertise settings object
258      * @throws Exception
259      */
260     @Rpc(description = "Get ble advertisement settings tx power level")
bleGetAdvertiseSettingsTxPowerLevel( @pcParametername = "index") Integer index)261     public int bleGetAdvertiseSettingsTxPowerLevel(
262             @RpcParameter(name = "index")
263             Integer index) throws Exception {
264         if (mAdvertiseSettingsList.get(index) != null) {
265             AdvertiseSettings mSettings = mAdvertiseSettingsList.get(index);
266             return mSettings.getTxPowerLevel();
267         } else {
268             throw new Exception("Invalid index input:" + Integer.toString(index));
269         }
270     }
271 
272     /**
273      * Get ble advertisement settings isConnectable value
274      *
275      * @param index the advertise settings object to use
276      * @return the boolean value whether the advertisement will indicate
277      * connectable.
278      * @throws Exception
279      */
280     @Rpc(description = "Get ble advertisement settings isConnectable value")
bleGetAdvertiseSettingsIsConnectable( @pcParametername = "index") Integer index)281     public boolean bleGetAdvertiseSettingsIsConnectable(
282             @RpcParameter(name = "index")
283             Integer index) throws Exception {
284         if (mAdvertiseSettingsList.get(index) != null) {
285             AdvertiseSettings mSettings = mAdvertiseSettingsList.get(index);
286             return mSettings.isConnectable();
287         } else {
288             throw new Exception("Invalid index input:" + Integer.toString(index));
289         }
290     }
291 
292     /**
293      * Get ble advertisement data include tx power level
294      *
295      * @param index the advertise data object to use
296      * @return True if include tx power level, false otherwise
297      * @throws Exception
298      */
299     @Rpc(description = "Get ble advertisement data include tx power level")
bleGetAdvertiseDataIncludeTxPowerLevel( @pcParametername = "index") Integer index)300     public Boolean bleGetAdvertiseDataIncludeTxPowerLevel(
301             @RpcParameter(name = "index")
302             Integer index) throws Exception {
303         if (mAdvertiseDataList.get(index) != null) {
304             AdvertiseData mData = mAdvertiseDataList.get(index);
305             return mData.getIncludeTxPowerLevel();
306         } else {
307             throw new Exception("Invalid index input:" + Integer.toString(index));
308         }
309     }
310 
311     /**
312      * Get ble advertisement data manufacturer specific data
313      *
314      * @param index the advertise data object to use
315      * @param manufacturerId the id that corresponds to the manufacturer specific data.
316      * @return the corresponding manufacturer specific data to the manufacturer id.
317      * @throws Exception
318      */
319     @Rpc(description = "Get ble advertisement data manufacturer specific data")
bleGetAdvertiseDataManufacturerSpecificData( @pcParametername = "index") Integer index, @RpcParameter(name = "manufacturerId") Integer manufacturerId)320     public byte[] bleGetAdvertiseDataManufacturerSpecificData(
321             @RpcParameter(name = "index")
322             Integer index,
323             @RpcParameter(name = "manufacturerId")
324             Integer manufacturerId) throws Exception {
325         if (mAdvertiseDataList.get(index) != null) {
326             AdvertiseData mData = mAdvertiseDataList.get(index);
327             if (mData.getManufacturerSpecificData() != null) {
328                 return mData.getManufacturerSpecificData().get(manufacturerId);
329             } else {
330                 throw new Exception("Invalid manufacturerId input:" + Integer.toString(manufacturerId));
331             }
332         } else {
333             throw new Exception("Invalid index input:" + Integer.toString(index));
334 
335         }
336     }
337 
338     /**
339      * Get ble advertisement data include device name
340      *
341      * @param index the advertise data object to use
342      * @return the advertisement data's include device name
343      * @throws Exception
344      */
345     @Rpc(description = "Get ble advertisement include device name")
bleGetAdvertiseDataIncludeDeviceName( @pcParametername = "index") Integer index)346     public Boolean bleGetAdvertiseDataIncludeDeviceName(
347             @RpcParameter(name = "index")
348             Integer index) throws Exception {
349         if (mAdvertiseDataList.get(index) != null) {
350             AdvertiseData mData = mAdvertiseDataList.get(index);
351             return mData.getIncludeDeviceName();
352         } else {
353             throw new Exception("Invalid index input:" + Integer.toString(index));
354         }
355     }
356 
357     /**
358      * Get ble advertisement Service Data
359      *
360      * @param index the advertise data object to use
361      * @param serviceUuid the uuid corresponding to the service data.
362      * @return the advertisement data's service data
363      * @throws Exception
364      */
365     @Rpc(description = "Get ble advertisement Service Data")
bleGetAdvertiseDataServiceData( @pcParametername = "index") Integer index, @RpcParameter(name = "serviceUuid") String serviceUuid)366     public byte[] bleGetAdvertiseDataServiceData(
367             @RpcParameter(name = "index")
368             Integer index,
369             @RpcParameter(name = "serviceUuid")
370             String serviceUuid) throws Exception {
371         ParcelUuid uuidKey = ParcelUuid.fromString(serviceUuid);
372         if (mAdvertiseDataList.get(index) != null) {
373             AdvertiseData mData = mAdvertiseDataList.get(index);
374             if (mData.getServiceData().containsKey(uuidKey)) {
375                 return mData.getServiceData().get(uuidKey);
376             } else {
377                 throw new Exception("Invalid serviceUuid input:" + serviceUuid);
378             }
379         } else {
380             throw new Exception("Invalid index input:" + Integer.toString(index));
381         }
382     }
383 
384     /**
385      * Get ble advertisement Service Uuids
386      *
387      * @param index the advertise data object to use
388      * @return the advertisement data's Service Uuids
389      * @throws Exception
390      */
391     @Rpc(description = "Get ble advertisement Service Uuids")
bleGetAdvertiseDataServiceUuids( @pcParametername = "index") Integer index)392     public List<ParcelUuid> bleGetAdvertiseDataServiceUuids(
393             @RpcParameter(name = "index")
394             Integer index) throws Exception {
395         if (mAdvertiseDataList.get(index) != null) {
396             AdvertiseData mData = mAdvertiseDataList.get(index);
397             return mData.getServiceUuids();
398         } else {
399             throw new Exception("Invalid index input:" + Integer.toString(index));
400         }
401     }
402 
403     /**
404      * Set ble advertisement data service uuids
405      *
406      * @param uuidList
407      * @throws Exception
408      */
409     @Rpc(description = "Set ble advertisement data service uuids")
bleSetAdvertiseDataSetServiceUuids( @pcParametername = "uuidList") String[] uuidList )410     public void bleSetAdvertiseDataSetServiceUuids(
411             @RpcParameter(name = "uuidList")
412             String[] uuidList
413             ) {
414         for (String uuid : uuidList) {
415             mAdvertiseDataBuilder.addServiceUuid(ParcelUuid.fromString(uuid));
416         }
417     }
418 
419     /**
420      * Set ble advertise data service uuids
421      *
422      * @param serviceDataUuid
423      * @param serviceData
424      * @throws Exception
425      */
426     @Rpc(description = "Set ble advertise data service uuids")
bleAddAdvertiseDataServiceData( @pcParametername = "serviceDataUuid") String serviceDataUuid, @RpcParameter(name = "serviceData") byte[] serviceData )427     public void bleAddAdvertiseDataServiceData(
428             @RpcParameter(name = "serviceDataUuid")
429             String serviceDataUuid,
430             @RpcParameter(name = "serviceData")
431             byte[] serviceData
432             ) {
433         mAdvertiseDataBuilder.addServiceData(
434                 ParcelUuid.fromString(serviceDataUuid),
435                 serviceData);
436     }
437 
438     /**
439      * Set ble advertise data manufacturer id
440      *
441      * @param manufacturerId the manufacturer id to set
442      * @param manufacturerSpecificData the manufacturer specific data to set
443      * @throws Exception
444      */
445     @Rpc(description = "Set ble advertise data manufacturerId")
bleAddAdvertiseDataManufacturerId( @pcParametername = "manufacturerId") Integer manufacturerId, @RpcParameter(name = "manufacturerSpecificData") byte[] manufacturerSpecificData )446     public void bleAddAdvertiseDataManufacturerId(
447             @RpcParameter(name = "manufacturerId")
448             Integer manufacturerId,
449             @RpcParameter(name = "manufacturerSpecificData")
450             byte[] manufacturerSpecificData
451             ) {
452         mAdvertiseDataBuilder.addManufacturerData(manufacturerId,
453                 manufacturerSpecificData);
454     }
455 
456     /**
457      * Set ble advertise settings advertise mode
458      *
459      * @param advertiseMode
460      * @throws Exception
461      */
462     @Rpc(description = "Set ble advertise settings advertise mode")
bleSetAdvertiseSettingsAdvertiseMode( @pcParametername = "advertiseMode") Integer advertiseMode )463     public void bleSetAdvertiseSettingsAdvertiseMode(
464             @RpcParameter(name = "advertiseMode")
465             Integer advertiseMode
466             ) {
467         mAdvertiseSettingsBuilder.setAdvertiseMode(advertiseMode);
468     }
469 
470     /**
471      * Set ble advertise settings tx power level
472      *
473      * @param txPowerLevel the tx power level to set
474      * @throws Exception
475      */
476     @Rpc(description = "Set ble advertise settings tx power level")
bleSetAdvertiseSettingsTxPowerLevel( @pcParametername = "txPowerLevel") Integer txPowerLevel )477     public void bleSetAdvertiseSettingsTxPowerLevel(
478             @RpcParameter(name = "txPowerLevel")
479             Integer txPowerLevel
480             ) {
481         mAdvertiseSettingsBuilder.setTxPowerLevel(txPowerLevel);
482     }
483 
484     /**
485      * Set ble advertise settings the isConnectable value
486      *
487      * @param type the isConnectable value
488      * @throws Exception
489      */
490     @Rpc(description = "Set ble advertise settings isConnectable value")
bleSetAdvertiseSettingsIsConnectable( @pcParametername = "value") Boolean value )491     public void bleSetAdvertiseSettingsIsConnectable(
492             @RpcParameter(name = "value")
493             Boolean value
494             ) {
495         mAdvertiseSettingsBuilder.setConnectable(value);
496     }
497 
498     /**
499      * Set ble advertisement data include tx power level
500      *
501      * @param includeTxPowerLevel boolean whether to include the tx power level or not in the
502      *            advertisement
503      */
504     @Rpc(description = "Set ble advertisement data include tx power level")
bleSetAdvertiseDataIncludeTxPowerLevel( @pcParametername = "includeTxPowerLevel") Boolean includeTxPowerLevel )505     public void bleSetAdvertiseDataIncludeTxPowerLevel(
506             @RpcParameter(name = "includeTxPowerLevel")
507             Boolean includeTxPowerLevel
508             ) {
509         mAdvertiseDataBuilder.setIncludeTxPowerLevel(includeTxPowerLevel);
510     }
511 
512     /**
513      * Set ble advertisement settings set timeout
514      *
515      * @param timeoutSeconds Limit advertising to a given amount of time.
516      */
517     @Rpc(description = "Set ble advertisement data include tx power level")
bleSetAdvertiseSettingsTimeout( @pcParametername = "timeoutSeconds") Integer timeoutSeconds )518     public void bleSetAdvertiseSettingsTimeout(
519             @RpcParameter(name = "timeoutSeconds")
520             Integer timeoutSeconds
521             ) {
522         mAdvertiseSettingsBuilder.setTimeout(timeoutSeconds);
523     }
524 
525     /**
526      * Set ble advertisement data include device name
527      *
528      * @param includeDeviceName boolean whether to include device name or not in the
529      *            advertisement
530      */
531     @Rpc(description = "Set ble advertisement data include device name")
bleSetAdvertiseDataIncludeDeviceName( @pcParametername = "includeDeviceName") Boolean includeDeviceName )532     public void bleSetAdvertiseDataIncludeDeviceName(
533             @RpcParameter(name = "includeDeviceName")
534             Boolean includeDeviceName
535             ) {
536         mAdvertiseDataBuilder.setIncludeDeviceName(includeDeviceName);
537     }
538 
539     private class myAdvertiseCallback extends AdvertiseCallback {
540         public Integer index;
541         private final Bundle mResults;
542         String mEventType;
543 
myAdvertiseCallback(int idx)544         public myAdvertiseCallback(int idx) {
545             index = idx;
546             mEventType = "BleAdvertise";
547             mResults = new Bundle();
548         }
549 
550         @Override
onStartSuccess(AdvertiseSettings settingsInEffect)551         public void onStartSuccess(AdvertiseSettings settingsInEffect) {
552             Log.d("bluetooth_le_advertisement onSuccess " + mEventType + " "
553                     + index);
554             mResults.putString("Type", "onSuccess");
555             mResults.putParcelable("SettingsInEffect", settingsInEffect);
556             mEventFacade.postEvent(mEventType + index + "onSuccess", mResults.clone());
557             mResults.clear();
558         }
559 
560         @Override
onStartFailure(int errorCode)561         public void onStartFailure(int errorCode) {
562             String errorString = "UNKNOWN_ERROR_CODE";
563             if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED) {
564                 errorString = "ADVERTISE_FAILED_ALREADY_STARTED";
565             } else if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE) {
566                 errorString = "ADVERTISE_FAILED_DATA_TOO_LARGE";
567             } else if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED) {
568                 errorString = "ADVERTISE_FAILED_FEATURE_UNSUPPORTED";
569             } else if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR) {
570                 errorString = "ADVERTISE_FAILED_INTERNAL_ERROR";
571             } else if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS) {
572                 errorString = "ADVERTISE_FAILED_TOO_MANY_ADVERTISERS";
573             }
574             Log.d("bluetooth_le_advertisement onFailure " + mEventType + " "
575                     + index + " error " + errorString);
576             mResults.putString("Type", "onFailure");
577             mResults.putInt("ErrorCode", errorCode);
578             mResults.putString("Error", errorString);
579             mEventFacade.postEvent(mEventType + index + "onFailure",
580                     mResults.clone());
581             mResults.clear();
582         }
583     }
584 
585     @Override
shutdown()586     public void shutdown() {
587         if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
588             for (myAdvertiseCallback mAdvertise : mAdvertiseCallbackList
589                 .values()) {
590                 if (mAdvertise != null) {
591                     try{
592                         mBluetoothAdapter.getBluetoothLeAdvertiser()
593                             .stopAdvertising(mAdvertise);
594                     } catch (NullPointerException e) {
595                         Log.e("Failed to stop ble advertising.", e);
596                     }
597                 }
598             }
599         }
600         mAdvertiseCallbackList.clear();
601         mAdvertiseSettingsList.clear();
602         mAdvertiseDataList.clear();
603     }
604 }
605