Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.googlecode.android_scripting.facade.bluetooth;
     18 
     19 import 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 
     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")
     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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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")
    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 
    544         public MyAdvertiseCallback(int idx) {
    545             index = idx;
    546             mEventType = "BleAdvertise";
    547             mResults = new Bundle();
    548         }
    549 
    550         @Override
    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
    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
    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