aboutsummaryrefslogtreecommitdiff
path: root/Common/src/com/googlecode/android_scripting/facade/bluetooth/BluetoothLeAdvertiseFacade.java
blob: 521c517a061f97ae9bbe4fd28217df7bf5ffad49 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.googlecode.android_scripting.facade.bluetooth;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseData.Builder;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.os.Bundle;
import android.os.ParcelUuid;

import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.MainThread;
import com.googlecode.android_scripting.facade.EventFacade;
import com.googlecode.android_scripting.facade.FacadeManager;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcParameter;

import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Callable;

/**
 * BluetoothLe Advertise functions.
 */

public class BluetoothLeAdvertiseFacade extends RpcReceiver {

    private final EventFacade mEventFacade;
    private BluetoothAdapter mBluetoothAdapter;
    private static int BleAdvertiseCallbackCount;
    private static int BleAdvertiseSettingsCount;
    private static int BleAdvertiseDataCount;
    private final HashMap<Integer, MyAdvertiseCallback> mAdvertiseCallbackList;
    private final BluetoothLeAdvertiser mAdvertise;
    private final Service mService;
    private Builder mAdvertiseDataBuilder;
    private android.bluetooth.le.AdvertiseSettings.Builder mAdvertiseSettingsBuilder;
    private final HashMap<Integer, AdvertiseData> mAdvertiseDataList;
    private final HashMap<Integer, AdvertiseSettings> mAdvertiseSettingsList;

    public BluetoothLeAdvertiseFacade(FacadeManager manager) {
        super(manager);
        mService = manager.getService();
        mBluetoothAdapter = MainThread.run(mService,
                new Callable<BluetoothAdapter>() {
                    @Override
                    public BluetoothAdapter call() throws Exception {
                        return BluetoothAdapter.getDefaultAdapter();
                    }
                });
        mEventFacade = manager.getReceiver(EventFacade.class);
        mAdvertiseCallbackList = new HashMap<Integer, MyAdvertiseCallback>();
        mAdvertise = mBluetoothAdapter.getBluetoothLeAdvertiser();
        mAdvertiseDataList = new HashMap<Integer, AdvertiseData>();
        mAdvertiseSettingsList = new HashMap<Integer, AdvertiseSettings>();
        mAdvertiseDataBuilder = new Builder();
        mAdvertiseSettingsBuilder = new android.bluetooth.le.AdvertiseSettings.Builder();
    }

    /**
     * Constructs a MyAdvertiseCallback obj and returns its index
     *
     * @return MyAdvertiseCallback.index
     */
    @Rpc(description = "Generate a new myAdvertisement Object")
    public Integer bleGenBleAdvertiseCallback() {
        BleAdvertiseCallbackCount += 1;
        int index = BleAdvertiseCallbackCount;
        MyAdvertiseCallback mCallback = new MyAdvertiseCallback(index);
        mAdvertiseCallbackList.put(mCallback.index,
                mCallback);
        return mCallback.index;
    }

    /**
     * Constructs a AdvertiseData obj and returns its index
     *
     * @return index
     */
    @Rpc(description = "Constructs a new Builder obj for AdvertiseData and returns its index")
    public Integer bleBuildAdvertiseData() {
        BleAdvertiseDataCount += 1;
        int index = BleAdvertiseDataCount;
        mAdvertiseDataList.put(index,
                mAdvertiseDataBuilder.build());
        mAdvertiseDataBuilder = new Builder();
        return index;
    }

    /**
     * Constructs a Advertise Settings obj and returns its index
     *
     * @return index
     */
    @Rpc(description = "Constructs a new Builder obj for AdvertiseData and returns its index")
    public Integer bleBuildAdvertiseSettings() {
        BleAdvertiseSettingsCount += 1;
        int index = BleAdvertiseSettingsCount;
        mAdvertiseSettingsList.put(index,
                mAdvertiseSettingsBuilder.build());
        mAdvertiseSettingsBuilder = new android.bluetooth.le.AdvertiseSettings.Builder();
        return index;
    }

    /**
     * Stops a ble advertisement
     *
     * @param index the id of the advertisement to stop advertising on
     * @throws Exception
     */
    @Rpc(description = "Stops an ongoing ble advertisement")
    public void bleStopBleAdvertising(
            @RpcParameter(name = "index")
            Integer index) throws Exception {
        if (mAdvertiseCallbackList.get(index) != null) {
            Log.d("bluetooth_le mAdvertise " + index);
            mAdvertise.stopAdvertising(mAdvertiseCallbackList
                    .get(index));
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));
        }
    }

    /**
     * Starts ble advertising
     *
     * @param callbackIndex The advertisementCallback index
     * @param dataIndex the AdvertiseData index
     * @param settingsIndex the advertisementsettings index
     * @throws Exception
     */
    @Rpc(description = "Starts ble advertisement")
    public void bleStartBleAdvertising(
            @RpcParameter(name = "callbackIndex")
            Integer callbackIndex,
            @RpcParameter(name = "dataIndex")
            Integer dataIndex,
            @RpcParameter(name = "settingsIndex")
            Integer settingsIndex
            ) throws Exception {
        AdvertiseData mData = new AdvertiseData.Builder().build();
        AdvertiseSettings mSettings = new AdvertiseSettings.Builder().build();
        if (mAdvertiseDataList.get(dataIndex) != null) {
            mData = mAdvertiseDataList.get(dataIndex);
        } else {
            throw new Exception("Invalid dataIndex input:" + Integer.toString(dataIndex));
        }
        if (mAdvertiseSettingsList.get(settingsIndex) != null) {
            mSettings = mAdvertiseSettingsList.get(settingsIndex);
        } else {
            throw new Exception("Invalid settingsIndex input:" + Integer.toString(settingsIndex));
        }
        if (mAdvertiseCallbackList.get(callbackIndex) != null) {
            Log.d("bluetooth_le starting a background advertisement on callback index: "
                    + Integer.toString(callbackIndex));
            mAdvertise
                    .startAdvertising(mSettings, mData, mAdvertiseCallbackList.get(callbackIndex));
        } else {
            throw new Exception("Invalid callbackIndex input" + Integer.toString(callbackIndex));
        }
    }

    /**
     * Starts ble advertising with a scanResponse. ScanResponses are created in the same way
     * AdvertiseData is created since they share the same object type.
     *
     * @param callbackIndex The advertisementCallback index
     * @param dataIndex the AdvertiseData index
     * @param settingsIndex the advertisementsettings index
     * @param scanResponseIndex the scanResponse index
     * @throws Exception
     */
    @Rpc(description = "Starts ble advertisement")
    public void bleStartBleAdvertisingWithScanResponse(
            @RpcParameter(name = "callbackIndex")
            Integer callbackIndex,
            @RpcParameter(name = "dataIndex")
            Integer dataIndex,
            @RpcParameter(name = "settingsIndex")
            Integer settingsIndex,
            @RpcParameter(name = "scanResponseIndex")
            Integer scanResponseIndex
            ) throws Exception {
        AdvertiseData mData = new AdvertiseData.Builder().build();
        AdvertiseSettings mSettings = new AdvertiseSettings.Builder().build();
        AdvertiseData mScanResponse = new AdvertiseData.Builder().build();

        if (mAdvertiseDataList.get(dataIndex) != null) {
            mData = mAdvertiseDataList.get(dataIndex);
        } else {
            throw new Exception("Invalid dataIndex input:" + Integer.toString(dataIndex));
        }
        if (mAdvertiseSettingsList.get(settingsIndex) != null) {
            mSettings = mAdvertiseSettingsList.get(settingsIndex);
        } else {
            throw new Exception("Invalid settingsIndex input:" + Integer.toString(settingsIndex));
        }
        if (mAdvertiseDataList.get(scanResponseIndex) != null) {
            mScanResponse = mAdvertiseDataList.get(scanResponseIndex);
        } else {
            throw new Exception("Invalid scanResponseIndex input:"
                    + Integer.toString(settingsIndex));
        }
        if (mAdvertiseCallbackList.get(callbackIndex) != null) {
            Log.d("bluetooth_le starting a background advertise on callback index: "
                    + Integer.toString(callbackIndex));
            mAdvertise
                    .startAdvertising(mSettings, mData, mScanResponse,
                            mAdvertiseCallbackList.get(callbackIndex));
        } else {
            throw new Exception("Invalid callbackIndex input" + Integer.toString(callbackIndex));
        }
    }

    /**
     * Get ble advertisement settings mode
     *
     * @param index the advertise settings object to use
     * @return the mode of the advertise settings object
     * @throws Exception
     */
    @Rpc(description = "Get ble advertisement settings mode")
    public int bleGetAdvertiseSettingsMode(
            @RpcParameter(name = "index")
            Integer index) throws Exception {
        if (mAdvertiseSettingsList.get(index) != null) {
            AdvertiseSettings mSettings = mAdvertiseSettingsList.get(index);
            return mSettings.getMode();
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));
        }
    }

    /**
     * Get ble advertisement settings tx power level
     *
     * @param index the advertise settings object to use
     * @return the tx power level of the advertise settings object
     * @throws Exception
     */
    @Rpc(description = "Get ble advertisement settings tx power level")
    public int bleGetAdvertiseSettingsTxPowerLevel(
            @RpcParameter(name = "index")
            Integer index) throws Exception {
        if (mAdvertiseSettingsList.get(index) != null) {
            AdvertiseSettings mSettings = mAdvertiseSettingsList.get(index);
            return mSettings.getTxPowerLevel();
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));
        }
    }

    /**
     * Get ble advertisement settings isConnectable value
     *
     * @param index the advertise settings object to use
     * @return the boolean value whether the advertisement will indicate
     * connectable.
     * @throws Exception
     */
    @Rpc(description = "Get ble advertisement settings isConnectable value")
    public boolean bleGetAdvertiseSettingsIsConnectable(
            @RpcParameter(name = "index")
            Integer index) throws Exception {
        if (mAdvertiseSettingsList.get(index) != null) {
            AdvertiseSettings mSettings = mAdvertiseSettingsList.get(index);
            return mSettings.isConnectable();
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));
        }
    }

    /**
     * Get ble advertisement data include tx power level
     *
     * @param index the advertise data object to use
     * @return True if include tx power level, false otherwise
     * @throws Exception
     */
    @Rpc(description = "Get ble advertisement data include tx power level")
    public Boolean bleGetAdvertiseDataIncludeTxPowerLevel(
            @RpcParameter(name = "index")
            Integer index) throws Exception {
        if (mAdvertiseDataList.get(index) != null) {
            AdvertiseData mData = mAdvertiseDataList.get(index);
            return mData.getIncludeTxPowerLevel();
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));
        }
    }

    /**
     * Get ble advertisement data manufacturer specific data
     *
     * @param index the advertise data object to use
     * @param manufacturerId the id that corresponds to the manufacturer specific data.
     * @return the corresponding manufacturer specific data to the manufacturer id.
     * @throws Exception
     */
    @Rpc(description = "Get ble advertisement data manufacturer specific data")
    public byte[] bleGetAdvertiseDataManufacturerSpecificData(
            @RpcParameter(name = "index")
            Integer index,
            @RpcParameter(name = "manufacturerId")
            Integer manufacturerId) throws Exception {
        if (mAdvertiseDataList.get(index) != null) {
            AdvertiseData mData = mAdvertiseDataList.get(index);
            if (mData.getManufacturerSpecificData() != null) {
                return mData.getManufacturerSpecificData().get(manufacturerId);
            } else {
                throw new Exception("Invalid manufacturerId input:" + Integer.toString(manufacturerId));
            }
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));

        }
    }

    /**
     * Get ble advertisement data include device name
     *
     * @param index the advertise data object to use
     * @return the advertisement data's include device name
     * @throws Exception
     */
    @Rpc(description = "Get ble advertisement include device name")
    public Boolean bleGetAdvertiseDataIncludeDeviceName(
            @RpcParameter(name = "index")
            Integer index) throws Exception {
        if (mAdvertiseDataList.get(index) != null) {
            AdvertiseData mData = mAdvertiseDataList.get(index);
            return mData.getIncludeDeviceName();
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));
        }
    }

    /**
     * Get ble advertisement Service Data
     *
     * @param index the advertise data object to use
     * @param serviceUuid the uuid corresponding to the service data.
     * @return the advertisement data's service data
     * @throws Exception
     */
    @Rpc(description = "Get ble advertisement Service Data")
    public byte[] bleGetAdvertiseDataServiceData(
            @RpcParameter(name = "index")
            Integer index,
            @RpcParameter(name = "serviceUuid")
            String serviceUuid) throws Exception {
        ParcelUuid uuidKey = ParcelUuid.fromString(serviceUuid);
        if (mAdvertiseDataList.get(index) != null) {
            AdvertiseData mData = mAdvertiseDataList.get(index);
            if (mData.getServiceData().containsKey(uuidKey)) {
                return mData.getServiceData().get(uuidKey);
            } else {
                throw new Exception("Invalid serviceUuid input:" + serviceUuid);
            }
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));
        }
    }

    /**
     * Get ble advertisement Service Uuids
     *
     * @param index the advertise data object to use
     * @return the advertisement data's Service Uuids
     * @throws Exception
     */
    @Rpc(description = "Get ble advertisement Service Uuids")
    public List<ParcelUuid> bleGetAdvertiseDataServiceUuids(
            @RpcParameter(name = "index")
            Integer index) throws Exception {
        if (mAdvertiseDataList.get(index) != null) {
            AdvertiseData mData = mAdvertiseDataList.get(index);
            return mData.getServiceUuids();
        } else {
            throw new Exception("Invalid index input:" + Integer.toString(index));
        }
    }

    /**
     * Set ble advertisement data service uuids
     *
     * @param uuidList
     * @throws Exception
     */
    @Rpc(description = "Set ble advertisement data service uuids")
    public void bleSetAdvertiseDataSetServiceUuids(
            @RpcParameter(name = "uuidList")
            String[] uuidList
            ) {
        for (String uuid : uuidList) {
            mAdvertiseDataBuilder.addServiceUuid(ParcelUuid.fromString(uuid));
        }
    }

    /**
     * Set ble advertise data service uuids
     *
     * @param serviceDataUuid
     * @param serviceData
     * @throws Exception
     */
    @Rpc(description = "Set ble advertise data service uuids")
    public void bleAddAdvertiseDataServiceData(
            @RpcParameter(name = "serviceDataUuid")
            String serviceDataUuid,
            @RpcParameter(name = "serviceData")
            byte[] serviceData
            ) {
        mAdvertiseDataBuilder.addServiceData(
                ParcelUuid.fromString(serviceDataUuid),
                serviceData);
    }

    /**
     * Set ble advertise data manufacturer id
     *
     * @param manufacturerId the manufacturer id to set
     * @param manufacturerSpecificData the manufacturer specific data to set
     * @throws Exception
     */
    @Rpc(description = "Set ble advertise data manufacturerId")
    public void bleAddAdvertiseDataManufacturerId(
            @RpcParameter(name = "manufacturerId")
            Integer manufacturerId,
            @RpcParameter(name = "manufacturerSpecificData")
            byte[] manufacturerSpecificData
            ) {
        mAdvertiseDataBuilder.addManufacturerData(manufacturerId,
                manufacturerSpecificData);
    }

    /**
     * Set ble advertise settings advertise mode
     *
     * @param advertiseMode
     * @throws Exception
     */
    @Rpc(description = "Set ble advertise settings advertise mode")
    public void bleSetAdvertiseSettingsAdvertiseMode(
            @RpcParameter(name = "advertiseMode")
            Integer advertiseMode
            ) {
        mAdvertiseSettingsBuilder.setAdvertiseMode(advertiseMode);
    }

    /**
     * Set ble advertise settings tx power level
     *
     * @param txPowerLevel the tx power level to set
     * @throws Exception
     */
    @Rpc(description = "Set ble advertise settings tx power level")
    public void bleSetAdvertiseSettingsTxPowerLevel(
            @RpcParameter(name = "txPowerLevel")
            Integer txPowerLevel
            ) {
        mAdvertiseSettingsBuilder.setTxPowerLevel(txPowerLevel);
    }

    /**
     * Set ble advertise settings the isConnectable value
     *
     * @param type the isConnectable value
     * @throws Exception
     */
    @Rpc(description = "Set ble advertise settings isConnectable value")
    public void bleSetAdvertiseSettingsIsConnectable(
            @RpcParameter(name = "value")
            Boolean value
            ) {
        mAdvertiseSettingsBuilder.setConnectable(value);
    }

    /**
     * Set ble advertisement data include tx power level
     *
     * @param includeTxPowerLevel boolean whether to include the tx power level or not in the
     *            advertisement
     */
    @Rpc(description = "Set ble advertisement data include tx power level")
    public void bleSetAdvertiseDataIncludeTxPowerLevel(
            @RpcParameter(name = "includeTxPowerLevel")
            Boolean includeTxPowerLevel
            ) {
        mAdvertiseDataBuilder.setIncludeTxPowerLevel(includeTxPowerLevel);
    }

    /**
     * Set ble advertisement settings set timeout
     *
     * @param timeoutSeconds Limit advertising to a given amount of time.
     */
    @Rpc(description = "Set ble advertisement data include tx power level")
    public void bleSetAdvertiseSettingsTimeout(
            @RpcParameter(name = "timeoutSeconds")
            Integer timeoutSeconds
            ) {
        mAdvertiseSettingsBuilder.setTimeout(timeoutSeconds);
    }

    /**
     * Set ble advertisement data include device name
     *
     * @param includeDeviceName boolean whether to include device name or not in the
     *            advertisement
     */
    @Rpc(description = "Set ble advertisement data include device name")
    public void bleSetAdvertiseDataIncludeDeviceName(
            @RpcParameter(name = "includeDeviceName")
            Boolean includeDeviceName
            ) {
        mAdvertiseDataBuilder.setIncludeDeviceName(includeDeviceName);
    }

    private class MyAdvertiseCallback extends AdvertiseCallback {
        public Integer index;
        private final Bundle mResults;
        String mEventType;

        public MyAdvertiseCallback(int idx) {
            index = idx;
            mEventType = "BleAdvertise";
            mResults = new Bundle();
        }

        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            Log.d("bluetooth_le_advertisement onSuccess " + mEventType + " "
                    + index);
            mResults.putString("Type", "onSuccess");
            mResults.putParcelable("SettingsInEffect", settingsInEffect);
            mEventFacade.postEvent(mEventType + index + "onSuccess", mResults.clone());
            mResults.clear();
        }

        @Override
        public void onStartFailure(int errorCode) {
            String errorString = "UNKNOWN_ERROR_CODE";
            if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED) {
                errorString = "ADVERTISE_FAILED_ALREADY_STARTED";
            } else if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE) {
                errorString = "ADVERTISE_FAILED_DATA_TOO_LARGE";
            } else if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED) {
                errorString = "ADVERTISE_FAILED_FEATURE_UNSUPPORTED";
            } else if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR) {
                errorString = "ADVERTISE_FAILED_INTERNAL_ERROR";
            } else if (errorCode == AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS) {
                errorString = "ADVERTISE_FAILED_TOO_MANY_ADVERTISERS";
            }
            Log.d("bluetooth_le_advertisement onFailure " + mEventType + " "
                    + index + " error " + errorString);
            mResults.putString("Type", "onFailure");
            mResults.putInt("ErrorCode", errorCode);
            mResults.putString("Error", errorString);
            mEventFacade.postEvent(mEventType + index + "onFailure",
                    mResults.clone());
            mResults.clear();
        }
    }

    /**
     * Clear all advertise settings
     *
     * @param None
     */
    @Rpc(description = "Clear all advertise settings")
    public void bleAdvertiseClearAll() {
        Log.d("bleAdvertiseClearAll: called");
        if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
            for (MyAdvertiseCallback mAdvertise : mAdvertiseCallbackList
                .values()) {
                if (mAdvertise != null) {
                    try{
                        mBluetoothAdapter.getBluetoothLeAdvertiser()
                            .stopAdvertising(mAdvertise);
                    } catch (NullPointerException e) {
                        Log.e("Failed to stop ble advertising.", e);
                    }
                }
            }
        }
        mAdvertiseCallbackList.clear();
        mAdvertiseSettingsList.clear();
        mAdvertiseDataList.clear();
    }

    @Override
    public void shutdown() {
        bleAdvertiseClearAll();
    }
}