16d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang/* 26d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Copyright (C) 2014 The Android Open Source Project 36d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 46d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Licensed under the Apache License, Version 2.0 (the "License"); 56d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * you may not use this file except in compliance with the License. 66d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * You may obtain a copy of the License at 76d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 86d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * http://www.apache.org/licenses/LICENSE-2.0 96d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 106d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Unless required by applicable law or agreed to in writing, software 116d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * distributed under the License is distributed on an "AS IS" BASIS, 126d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * See the License for the specific language governing permissions and 146d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * limitations under the License. 156d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 166d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 176d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangpackage android.bluetooth.le; 186d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 196d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.bluetooth.BluetoothAdapter; 209e377194e35c0fb9ac5771f5658c095ed97e0838Jakub Pawlowskiimport android.bluetooth.BluetoothDevice; 210e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wangimport android.bluetooth.BluetoothUuid; 226d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.bluetooth.IBluetoothGatt; 239fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wangimport android.bluetooth.IBluetoothManager; 246d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.os.Handler; 256d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.os.Looper; 266d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.os.ParcelUuid; 276d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.os.RemoteException; 286d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport android.util.Log; 296d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 305f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowskiimport java.util.Collections; 316d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport java.util.HashMap; 326d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangimport java.util.Map; 336d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 346d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang/** 35af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * This class provides a way to perform Bluetooth LE advertise operations, such as starting and 36af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * stopping advertising. An advertiser can broadcast up to 31 bytes of advertisement data 37af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * represented by {@link AdvertiseData}. 386d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * <p> 396d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * To get an instance of {@link BluetoothLeAdvertiser}, call the 406d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * {@link BluetoothAdapter#getBluetoothLeAdvertiser()} method. 416d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * <p> 42af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * <b>Note:</b> Most of the methods here require {@link android.Manifest.permission#BLUETOOTH_ADMIN} 436d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * permission. 446d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 45af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * @see AdvertiseData 466d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 476d81118032b92caa0f5cfebe11af02a98f819d5eWei Wangpublic final class BluetoothLeAdvertiser { 486d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 496d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private static final String TAG = "BluetoothLeAdvertiser"; 506d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 51f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski private static final int MAX_ADVERTISING_DATA_BYTES = 1650; 52f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski private static final int MAX_LEGACY_ADVERTISING_DATA_BYTES = 31; 530e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang // Each fields need one byte for field length and another byte for field type. 540e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang private static final int OVERHEAD_BYTES_PER_FIELD = 2; 550e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang // Flags field will be set by system. 560e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang private static final int FLAGS_FIELD_BYTES = 3; 570e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang private static final int MANUFACTURER_SPECIFIC_DATA_LENGTH = 2; 580e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang 599fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang private final IBluetoothManager mBluetoothManager; 606d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang private final Handler mHandler; 618e5270fdf5639461d67e9a898a85520abac6053dPrerepa Viswanadham private BluetoothAdapter mBluetoothAdapter; 625f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski private final Map<AdvertiseCallback, AdvertisingSetCallback> 635f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski mLegacyAdvertisers = new HashMap<>(); 64a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski private final Map<AdvertisingSetCallback, IAdvertisingSetCallback> 655f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski mCallbackWrappers = Collections.synchronizedMap(new HashMap<>()); 665f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski private final Map<Integer, AdvertisingSet> 675f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski mAdvertisingSets = Collections.synchronizedMap(new HashMap<>()); 686d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 696d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 706d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Use BluetoothAdapter.getLeAdvertiser() instead. 71685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * 72685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management 736d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @hide 746d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 759fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang public BluetoothLeAdvertiser(IBluetoothManager bluetoothManager) { 769fb1791e1a6859bfb14006a6d101cdecc88f3f95Wei Wang mBluetoothManager = bluetoothManager; 778e5270fdf5639461d67e9a898a85520abac6053dPrerepa Viswanadham mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 786d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mHandler = new Handler(Looper.getMainLooper()); 796d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 806d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 816d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 82685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * Start Bluetooth LE Advertising. On success, the {@code advertiseData} will be broadcasted. 83685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * Returns immediately, the operation status is delivered through {@code callback}. 846d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * <p> 856d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. 866d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 876d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @param settings Settings for Bluetooth LE advertising. 886d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @param advertiseData Advertisement data to be broadcasted. 896d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @param callback Callback for advertising status. 906d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 916d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public void startAdvertising(AdvertiseSettings settings, 92af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang AdvertiseData advertiseData, final AdvertiseCallback callback) { 936d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang startAdvertising(settings, advertiseData, null, callback); 946d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 956d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 966d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 97af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * Start Bluetooth LE Advertising. The {@code advertiseData} will be broadcasted if the 98685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * operation succeeds. The {@code scanResponse} is returned when a scanning device sends an 99685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * active scan request. This method returns immediately, the operation status is delivered 100685c1758902a42a7beb030d8bbaed3f7ce6f6135Wei Wang * through {@code callback}. 1016d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * <p> 1026d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 1036d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 1046d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @param settings Settings for Bluetooth LE advertising. 1056d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @param advertiseData Advertisement data to be advertised in advertisement packet. 1066d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @param scanResponse Scan response associated with the advertisement data. 1076d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * @param callback Callback for advertising status. 1086d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 1096d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public void startAdvertising(AdvertiseSettings settings, 110af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang AdvertiseData advertiseData, AdvertiseData scanResponse, 1116d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang final AdvertiseCallback callback) { 1125f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski synchronized (mLegacyAdvertisers) { 113833559d9f3f0bd6ddb1cf9c1571975751830e045Wei Wang BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); 1149a974be631a3ff2e7e754f79167eb024ee55925eWei Wang if (callback == null) { 1159a974be631a3ff2e7e754f79167eb024ee55925eWei Wang throw new IllegalArgumentException("callback cannot be null"); 1169a974be631a3ff2e7e754f79167eb024ee55925eWei Wang } 11729230ceab9ea7b6913f0a898411b213f199e18c2Tom Turney boolean isConnectable = settings.isConnectable(); 1182992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES 1192992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He || totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) { 1209a974be631a3ff2e7e754f79167eb024ee55925eWei Wang postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE); 1219a974be631a3ff2e7e754f79167eb024ee55925eWei Wang return; 1226d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 1235f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski if (mLegacyAdvertisers.containsKey(callback)) { 1249a974be631a3ff2e7e754f79167eb024ee55925eWei Wang postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED); 1259a974be631a3ff2e7e754f79167eb024ee55925eWei Wang return; 1269a974be631a3ff2e7e754f79167eb024ee55925eWei Wang } 1279a974be631a3ff2e7e754f79167eb024ee55925eWei Wang 1285f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski AdvertisingSetParameters.Builder parameters = new AdvertisingSetParameters.Builder(); 1295f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski parameters.setLegacyMode(true); 1305f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski parameters.setConnectable(isConnectable); 131d12b5688f06b0f3428730262cf208713442f6f5bJakub Pawlowski parameters.setScannable(true); // legacy advertisements we support are always scannable 1325f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_POWER) { 1335f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski parameters.setInterval(1600); // 1s 1345f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_BALANCED) { 1355f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski parameters.setInterval(400); // 250ms 1365f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) { 1375f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski parameters.setInterval(160); // 100ms 1385f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski } 1395f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski 1405f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW) { 1415f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski parameters.setTxPowerLevel(-21); 1425f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_LOW) { 1435f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski parameters.setTxPowerLevel(-15); 1445f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM) { 1455f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski parameters.setTxPowerLevel(-7); 1465f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) { 1475f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski parameters.setTxPowerLevel(1); 1489a974be631a3ff2e7e754f79167eb024ee55925eWei Wang } 1495f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski 1505a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski int duration = 0; 1515a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski int timeoutMillis = settings.getTimeout(); 1525a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski if (timeoutMillis > 0) { 153a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He duration = (timeoutMillis < 10) ? 1 : timeoutMillis / 10; 1545a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski } 1555a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski 1565f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski AdvertisingSetCallback wrapped = wrapOldCallback(callback, settings); 1575f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski mLegacyAdvertisers.put(callback, wrapped); 1585f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski startAdvertisingSet(parameters.build(), advertiseData, scanResponse, null, null, 159a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He duration, 0, wrapped); 1606d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 1616d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 1626d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 1635f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski AdvertisingSetCallback wrapOldCallback(AdvertiseCallback callback, AdvertiseSettings settings) { 1645f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski return new AdvertisingSetCallback() { 165bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski @Override 166bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, 167a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He int status) { 1685f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) { 1695f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski postStartFailure(callback, status); 1705f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski return; 1715f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski } 1725f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski 1735f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski postStartSuccess(callback, settings); 1745f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski } 1755f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski 1765f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski /* Legacy advertiser is disabled on timeout */ 177bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski @Override 178bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enabled, 179a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He int status) { 1802992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He if (enabled) { 1812992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He Log.e(TAG, "Legacy advertiser should be only disabled on timeout," 1822992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He + " but was enabled!"); 1835f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski return; 1845f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski } 1855f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski 1865f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski stopAdvertising(callback); 1875f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski } 1885f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski 1895f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski }; 1905f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski } 1915f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski 1926d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang /** 1936d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Stop Bluetooth LE advertising. The {@code callback} must be the same one use in 1946d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * {@link BluetoothLeAdvertiser#startAdvertising}. 1956d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * <p> 1966d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. 1976d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang * 198af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang * @param callback {@link AdvertiseCallback} identifies the advertising instance to stop. 1996d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang */ 2006d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public void stopAdvertising(final AdvertiseCallback callback) { 2015f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski synchronized (mLegacyAdvertisers) { 2029a974be631a3ff2e7e754f79167eb024ee55925eWei Wang if (callback == null) { 2039a974be631a3ff2e7e754f79167eb024ee55925eWei Wang throw new IllegalArgumentException("callback cannot be null"); 2046d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2055f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski AdvertisingSetCallback wrapper = mLegacyAdvertisers.get(callback); 2069a974be631a3ff2e7e754f79167eb024ee55925eWei Wang if (wrapper == null) return; 2075f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski 2085f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski stopAdvertisingSet(wrapper); 2092489b415ff8ec87a4c89f4b16e8d7b2901cd6b3dJakub Pawlowski 2102489b415ff8ec87a4c89f4b16e8d7b2901cd6b3dJakub Pawlowski mLegacyAdvertisers.remove(callback); 2116d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2126d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 2136d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang 214ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang /** 215f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * Creates a new advertising set. If operation succeed, device will start advertising. This 216f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * method returns immediately, the operation status is delivered through 217f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * {@code callback.onAdvertisingSetStarted()}. 218f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * <p> 219a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * 220f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @param parameters advertising set parameters. 221a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link 222a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable, 223a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * three bytes will be added for flags. 2245a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski * @param scanResponse Scan response associated with the advertisement data. Size must not 225a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. 226f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will 227a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * not be started. 228a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @param periodicData Periodic advertising data. Size must not exceed {@link 229a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. 230f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @param callback Callback for advertising set. 231f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable 232a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising 233a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * feature is made when it's not supported by the controller. 234f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski */ 235a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void startAdvertisingSet(AdvertisingSetParameters parameters, 236a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He AdvertiseData advertiseData, AdvertiseData scanResponse, 237a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He PeriodicAdvertisingParameters periodicParameters, 238a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He AdvertiseData periodicData, AdvertisingSetCallback callback) { 239a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, 240a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He periodicData, 0, 0, callback, new Handler(Looper.getMainLooper())); 241a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 242a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 243a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski /** 244f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * Creates a new advertising set. If operation succeed, device will start advertising. This 245f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * method returns immediately, the operation status is delivered through 246f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * {@code callback.onAdvertisingSetStarted()}. 247f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * <p> 248a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * 249f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @param parameters advertising set parameters. 250a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link 251a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable, 252a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * three bytes will be added for flags. 2535a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski * @param scanResponse Scan response associated with the advertisement data. Size must not 254a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. 255f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will 256a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * not be started. 257a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @param periodicData Periodic advertising data. Size must not exceed {@link 258a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. 259f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @param callback Callback for advertising set. 260f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @param handler thread upon which the callbacks will be invoked. 261f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable 262a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising 263a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * feature is made when it's not supported by the controller. 264f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski */ 265a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void startAdvertisingSet(AdvertisingSetParameters parameters, 266a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He AdvertiseData advertiseData, AdvertiseData scanResponse, 267a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He PeriodicAdvertisingParameters periodicParameters, 268a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He AdvertiseData periodicData, AdvertisingSetCallback callback, 269a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He Handler handler) { 270adbf2eef2fda68a5c3acc78a67e5dda00d8a14d7Jakub Pawlowski startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, 271a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He periodicData, 0, 0, callback, handler); 272adbf2eef2fda68a5c3acc78a67e5dda00d8a14d7Jakub Pawlowski } 273adbf2eef2fda68a5c3acc78a67e5dda00d8a14d7Jakub Pawlowski 274adbf2eef2fda68a5c3acc78a67e5dda00d8a14d7Jakub Pawlowski /** 275f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * Creates a new advertising set. If operation succeed, device will start advertising. This 276f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * method returns immediately, the operation status is delivered through 277f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * {@code callback.onAdvertisingSetStarted()}. 278f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * <p> 279a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * 280f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @param parameters advertising set parameters. 281a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link 282a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable, 283a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * three bytes will be added for flags. 2845a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski * @param scanResponse Scan response associated with the advertisement data. Size must not 285a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. 286f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @param periodicParameters periodic advertisng parameters. If null, periodic advertising will 287a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * not be started. 288a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @param periodicData Periodic advertising data. Size must not exceed {@link 289a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. 290a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535 291a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * (655,350 ms). 0 means advertising should continue until stopped. 2925a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the 293a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * controller shall attempt to send prior to terminating the extended advertising, even if the 294a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * duration has not expired. Valid range is from 1 to 255. 0 means no maximum. 295f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @param callback Callback for advertising set. 296f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable 297a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising 298a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * feature is made when it's not supported by the controller. 299f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski */ 300adbf2eef2fda68a5c3acc78a67e5dda00d8a14d7Jakub Pawlowski public void startAdvertisingSet(AdvertisingSetParameters parameters, 301a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He AdvertiseData advertiseData, AdvertiseData scanResponse, 302a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He PeriodicAdvertisingParameters periodicParameters, 303a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He AdvertiseData periodicData, int duration, 304a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He int maxExtendedAdvertisingEvents, 305a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He AdvertisingSetCallback callback) { 306adbf2eef2fda68a5c3acc78a67e5dda00d8a14d7Jakub Pawlowski startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, 307a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He periodicData, duration, maxExtendedAdvertisingEvents, callback, 308a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He new Handler(Looper.getMainLooper())); 309adbf2eef2fda68a5c3acc78a67e5dda00d8a14d7Jakub Pawlowski } 310adbf2eef2fda68a5c3acc78a67e5dda00d8a14d7Jakub Pawlowski 311adbf2eef2fda68a5c3acc78a67e5dda00d8a14d7Jakub Pawlowski /** 312f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * Creates a new advertising set. If operation succeed, device will start advertising. This 313f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * method returns immediately, the operation status is delivered through 314f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * {@code callback.onAdvertisingSetStarted()}. 315f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * <p> 316a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * 3175a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski * @param parameters Advertising set parameters. 318a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @param advertiseData Advertisement data to be broadcasted. Size must not exceed {@link 319a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the advertisement is connectable, 320a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * three bytes will be added for flags. 3215a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski * @param scanResponse Scan response associated with the advertisement data. Size must not 322a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength} 3235a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski * @param periodicParameters Periodic advertisng parameters. If null, periodic advertising will 324a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * not be started. 325a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @param periodicData Periodic advertising data. Size must not exceed {@link 326a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * BluetoothAdapter#getLeMaximumAdvertisingDataLength} 327a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * @param duration advertising duration, in 10ms unit. Valid range is from 1 (10ms) to 65535 328a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * (655,350 ms). 0 means advertising should continue until stopped. 3295a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski * @param maxExtendedAdvertisingEvents maximum number of extended advertising events the 330a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * controller shall attempt to send prior to terminating the extended advertising, even if the 331a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * duration has not expired. Valid range is from 1 to 255. 0 means no maximum. 332f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski * @param callback Callback for advertising set. 3335a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski * @param handler Thread upon which the callbacks will be invoked. 3345a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski * @throws IllegalArgumentException When any of the data parameter exceed the maximum allowable 335a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * size, or unsupported advertising PHY is selected, or when attempt to use Periodic Advertising 336a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * feature is made when it's not supported by the controller, or when 337a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * maxExtendedAdvertisingEvents is used on a controller that doesn't support the LE Extended 338a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He * Advertising 339f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski */ 340adbf2eef2fda68a5c3acc78a67e5dda00d8a14d7Jakub Pawlowski public void startAdvertisingSet(AdvertisingSetParameters parameters, 341a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He AdvertiseData advertiseData, AdvertiseData scanResponse, 342a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He PeriodicAdvertisingParameters periodicParameters, 343a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He AdvertiseData periodicData, int duration, 344a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He int maxExtendedAdvertisingEvents, AdvertisingSetCallback callback, 345a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He Handler handler) { 346a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); 347a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski if (callback == null) { 348a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He throw new IllegalArgumentException("callback cannot be null"); 349a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 350a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 351f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski boolean isConnectable = parameters.isConnectable(); 352f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski if (parameters.isLegacy()) { 353f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES) { 354f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski throw new IllegalArgumentException("Legacy advertising data too big"); 355f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski } 356f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski 357f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski if (totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) { 358f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski throw new IllegalArgumentException("Legacy scan response data too big"); 359f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski } 360f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski } else { 361f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski boolean supportCodedPhy = mBluetoothAdapter.isLeCodedPhySupported(); 362f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski boolean support2MPhy = mBluetoothAdapter.isLe2MPhySupported(); 363f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski int pphy = parameters.getPrimaryPhy(); 364f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski int sphy = parameters.getSecondaryPhy(); 3659e377194e35c0fb9ac5771f5658c095ed97e0838Jakub Pawlowski if (pphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy) { 366f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski throw new IllegalArgumentException("Unsupported primary PHY selected"); 367f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski } 368f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski 3699e377194e35c0fb9ac5771f5658c095ed97e0838Jakub Pawlowski if ((sphy == BluetoothDevice.PHY_LE_CODED && !supportCodedPhy) 370a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He || (sphy == BluetoothDevice.PHY_LE_2M && !support2MPhy)) { 371f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski throw new IllegalArgumentException("Unsupported secondary PHY selected"); 372f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski } 373f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski 374f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski int maxData = mBluetoothAdapter.getLeMaximumAdvertisingDataLength(); 375f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski if (totalBytes(advertiseData, isConnectable) > maxData) { 376f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski throw new IllegalArgumentException("Advertising data too big"); 377f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski } 378f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski 379f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski if (totalBytes(scanResponse, false) > maxData) { 380f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski throw new IllegalArgumentException("Scan response data too big"); 381f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski } 382f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski 383f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski if (totalBytes(periodicData, false) > maxData) { 384f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski throw new IllegalArgumentException("Periodic advertising data too big"); 385f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski } 386f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski 387f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski boolean supportPeriodic = mBluetoothAdapter.isLePeriodicAdvertisingSupported(); 388e6c453d828fec3df82708d2b0c3bb00bd0a0dbf8Jakub Pawlowski if (periodicParameters != null && !supportPeriodic) { 389f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski throw new IllegalArgumentException( 390a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He "Controller does not support LE Periodic Advertising"); 391f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski } 392f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski } 393f4ed33f5fa6ffa3bda6faff773a3fb90b16a760cJakub Pawlowski 3945a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski if (maxExtendedAdvertisingEvents < 0 || maxExtendedAdvertisingEvents > 255) { 3955a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski throw new IllegalArgumentException( 396a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He "maxExtendedAdvertisingEvents out of range: " + maxExtendedAdvertisingEvents); 3975a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski } 3985a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski 3992992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He if (maxExtendedAdvertisingEvents != 0 4002992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He && !mBluetoothAdapter.isLePeriodicAdvertisingSupported()) { 4015a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski throw new IllegalArgumentException( 4022992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He "Can't use maxExtendedAdvertisingEvents with controller that don't support " 4032992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He + "LE Extended Advertising"); 4045a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski } 4055a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski 4065a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski if (duration < 0 || duration > 65535) { 4075a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski throw new IllegalArgumentException("duration out of range: " + duration); 4085a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski } 4095a355610fe6ac0460f7130375de97b4d7bae7ba4Jakub Pawlowski 410a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski IBluetoothGatt gatt; 411a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski try { 412a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He gatt = mBluetoothManager.getBluetoothGatt(); 413a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } catch (RemoteException e) { 414a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He Log.e(TAG, "Failed to get Bluetooth gatt - ", e); 415a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He postStartSetFailure(handler, callback, 416a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); 417a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He return; 418a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 419a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 420a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski IAdvertisingSetCallback wrapped = wrap(callback, handler); 4215f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski if (mCallbackWrappers.putIfAbsent(callback, wrapped) != null) { 4225f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski throw new IllegalArgumentException( 423a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He "callback instance already associated with advertising"); 4245f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski } 425a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 426a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski try { 427a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski gatt.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, 428a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He periodicData, duration, maxExtendedAdvertisingEvents, wrapped); 429a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } catch (RemoteException e) { 430a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He Log.e(TAG, "Failed to start advertising set - ", e); 431a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He postStartSetFailure(handler, callback, 432a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR); 433a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He return; 434a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 435a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 436a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 437a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski /** 438a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski * Used to dispose of a {@link AdvertisingSet} object, obtained with {@link 439a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski * BluetoothLeAdvertiser#startAdvertisingSet}. 440a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski */ 441a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void stopAdvertisingSet(AdvertisingSetCallback callback) { 442a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski if (callback == null) { 443a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He throw new IllegalArgumentException("callback cannot be null"); 444a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 445a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 4465f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski IAdvertisingSetCallback wrapped = mCallbackWrappers.remove(callback); 447a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski if (wrapped == null) { 4485f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski return; 449a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 450a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 451a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski IBluetoothGatt gatt; 452a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski try { 453a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski gatt = mBluetoothManager.getBluetoothGatt(); 454a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski gatt.stopAdvertisingSet(wrapped); 455a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He } catch (RemoteException e) { 456a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski Log.e(TAG, "Failed to stop advertising - ", e); 457a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He } 458a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 459a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 460a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski /** 461a480f7fe28ef059b82491f52dcc69934322ee5e2Jakub Pawlowski * Cleans up advertisers. Should be called when bluetooth is down. 462ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang * 463ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang * @hide 464ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang */ 465ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang public void cleanup() { 4665f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski mLegacyAdvertisers.clear(); 4675f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski mCallbackWrappers.clear(); 4685f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski mAdvertisingSets.clear(); 469ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang } 470ee80922c6a1228886589dcd4598a1cadf0bd1ff8Wei Wang 471e77adabeafa16f9b401a6ad67405205bd96f2219Prerepa Viswanadham // Compute the size of advertisement data or scan resp 472e77adabeafa16f9b401a6ad67405205bd96f2219Prerepa Viswanadham private int totalBytes(AdvertiseData data, boolean isFlagsIncluded) { 4739a974be631a3ff2e7e754f79167eb024ee55925eWei Wang if (data == null) return 0; 47429230ceab9ea7b6913f0a898411b213f199e18c2Tom Turney // Flags field is omitted if the advertising is not connectable. 475e77adabeafa16f9b401a6ad67405205bd96f2219Prerepa Viswanadham int size = (isFlagsIncluded) ? FLAGS_FIELD_BYTES : 0; 4760e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang if (data.getServiceUuids() != null) { 4770e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang int num16BitUuids = 0; 4780e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang int num32BitUuids = 0; 4790e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang int num128BitUuids = 0; 4800e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang for (ParcelUuid uuid : data.getServiceUuids()) { 4810e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang if (BluetoothUuid.is16BitUuid(uuid)) { 4820e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang ++num16BitUuids; 4830e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } else if (BluetoothUuid.is32BitUuid(uuid)) { 4840e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang ++num32BitUuids; 4850e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } else { 4860e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang ++num128BitUuids; 4870e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } 4880e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } 4890e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang // 16 bit service uuids are grouped into one field when doing advertising. 4900e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang if (num16BitUuids != 0) { 4912992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He size += OVERHEAD_BYTES_PER_FIELD + num16BitUuids * BluetoothUuid.UUID_BYTES_16_BIT; 4920e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } 4930e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang // 32 bit service uuids are grouped into one field when doing advertising. 4940e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang if (num32BitUuids != 0) { 4952992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He size += OVERHEAD_BYTES_PER_FIELD + num32BitUuids * BluetoothUuid.UUID_BYTES_32_BIT; 4960e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } 4970e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang // 128 bit service uuids are grouped into one field when doing advertising. 4980e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang if (num128BitUuids != 0) { 4992992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He size += OVERHEAD_BYTES_PER_FIELD 5002992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT; 5010e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } 5020e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } 5036bf513d32db7fbc157681bd642e12a201cf20a89Wei Wang for (ParcelUuid uuid : data.getServiceData().keySet()) { 50472e9e9f81504559ca18b71358203b1b39d9f0581Jakub Pawlowski int uuidLen = BluetoothUuid.uuidToBytes(uuid).length; 50572e9e9f81504559ca18b71358203b1b39d9f0581Jakub Pawlowski size += OVERHEAD_BYTES_PER_FIELD + uuidLen 5066bf513d32db7fbc157681bd642e12a201cf20a89Wei Wang + byteLength(data.getServiceData().get(uuid)); 5070e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } 5086bf513d32db7fbc157681bd642e12a201cf20a89Wei Wang for (int i = 0; i < data.getManufacturerSpecificData().size(); ++i) { 5092992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH 5102992cd084cd5cfd9ef253c37ef269d6c75e7e144Jack He + byteLength(data.getManufacturerSpecificData().valueAt(i)); 5110e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } 5120e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang if (data.getIncludeTxPowerLevel()) { 5130e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte. 5140e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } 5150e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang if (data.getIncludeDeviceName() && mBluetoothAdapter.getName() != null) { 5160e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang size += OVERHEAD_BYTES_PER_FIELD + mBluetoothAdapter.getName().length(); 5170e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } 5180e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang return size; 5190e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } 5200e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang 5210e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang private int byteLength(byte[] array) { 5220e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang return array == null ? 0 : array.length; 5230e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang } 5240e81ca25432b3606eba841206b7a4a6ed74bd54bWei Wang 525a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski IAdvertisingSetCallback wrap(AdvertisingSetCallback callback, Handler handler) { 526a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski return new IAdvertisingSetCallback.Stub() { 527bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski @Override 5286a55da90184fcc6e8f4bb9ebb01662b4925f6094Jakub Pawlowski public void onAdvertisingSetStarted(int advertiserId, int txPower, int status) { 529a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski handler.post(new Runnable() { 530a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski @Override 531a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void run() { 532a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) { 5336a55da90184fcc6e8f4bb9ebb01662b4925f6094Jakub Pawlowski callback.onAdvertisingSetStarted(null, 0, status); 5345f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski mCallbackWrappers.remove(callback); 535a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski return; 536a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 537a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 538a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski AdvertisingSet advertisingSet = 539a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He new AdvertisingSet(advertiserId, mBluetoothManager); 5405f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski mAdvertisingSets.put(advertiserId, advertisingSet); 5416a55da90184fcc6e8f4bb9ebb01662b4925f6094Jakub Pawlowski callback.onAdvertisingSetStarted(advertisingSet, txPower, status); 542a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 543a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski }); 544a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 545a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 546bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski @Override 5474bc4a441007e0a9ef6ccd1816c831ffd2dfa4c18Jakub Pawlowski public void onOwnAddressRead(int advertiserId, int addressType, String address) { 5484bc4a441007e0a9ef6ccd1816c831ffd2dfa4c18Jakub Pawlowski handler.post(new Runnable() { 5494bc4a441007e0a9ef6ccd1816c831ffd2dfa4c18Jakub Pawlowski @Override 5504bc4a441007e0a9ef6ccd1816c831ffd2dfa4c18Jakub Pawlowski public void run() { 5514bc4a441007e0a9ef6ccd1816c831ffd2dfa4c18Jakub Pawlowski AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId); 5524bc4a441007e0a9ef6ccd1816c831ffd2dfa4c18Jakub Pawlowski callback.onOwnAddressRead(advertisingSet, addressType, address); 5534bc4a441007e0a9ef6ccd1816c831ffd2dfa4c18Jakub Pawlowski } 5544bc4a441007e0a9ef6ccd1816c831ffd2dfa4c18Jakub Pawlowski }); 5554bc4a441007e0a9ef6ccd1816c831ffd2dfa4c18Jakub Pawlowski } 5564bc4a441007e0a9ef6ccd1816c831ffd2dfa4c18Jakub Pawlowski 5574bc4a441007e0a9ef6ccd1816c831ffd2dfa4c18Jakub Pawlowski @Override 558a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void onAdvertisingSetStopped(int advertiserId) { 559a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski handler.post(new Runnable() { 560a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski @Override 561a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void run() { 5625f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId); 563a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski callback.onAdvertisingSetStopped(advertisingSet); 5645f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski mAdvertisingSets.remove(advertiserId); 5655f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski mCallbackWrappers.remove(callback); 566a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 567a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski }); 568a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 569a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 570bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski @Override 571a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void onAdvertisingEnabled(int advertiserId, boolean enabled, int status) { 572a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski handler.post(new Runnable() { 573a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski @Override 574a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void run() { 5755f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId); 576a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski callback.onAdvertisingEnabled(advertisingSet, enabled, status); 577a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 578a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski }); 579a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 580a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 581bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski @Override 582a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void onAdvertisingDataSet(int advertiserId, int status) { 583a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski handler.post(new Runnable() { 584a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski @Override 585a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void run() { 5865f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId); 587a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski callback.onAdvertisingDataSet(advertisingSet, status); 588a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 589a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski }); 590a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 591a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 592bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski @Override 593a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void onScanResponseDataSet(int advertiserId, int status) { 594a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski handler.post(new Runnable() { 595a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski @Override 596a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void run() { 5975f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId); 598a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski callback.onScanResponseDataSet(advertisingSet, status); 599a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 600a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski }); 601a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 602a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 603bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski @Override 6046a55da90184fcc6e8f4bb9ebb01662b4925f6094Jakub Pawlowski public void onAdvertisingParametersUpdated(int advertiserId, int txPower, int status) { 605a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski handler.post(new Runnable() { 606a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski @Override 607a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void run() { 6085f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId); 6096a55da90184fcc6e8f4bb9ebb01662b4925f6094Jakub Pawlowski callback.onAdvertisingParametersUpdated(advertisingSet, txPower, status); 610a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 611a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski }); 612a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 613a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 614bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski @Override 615a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void onPeriodicAdvertisingParametersUpdated(int advertiserId, int status) { 616a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski handler.post(new Runnable() { 617a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski @Override 618a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void run() { 6195f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId); 620a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski callback.onPeriodicAdvertisingParametersUpdated(advertisingSet, status); 621a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 622a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski }); 623a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 624a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 625bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski @Override 626a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void onPeriodicAdvertisingDataSet(int advertiserId, int status) { 627a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski handler.post(new Runnable() { 628a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski @Override 629a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void run() { 6305f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId); 631a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski callback.onPeriodicAdvertisingDataSet(advertisingSet, status); 632a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 633a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski }); 634a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 635a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 636bcf671b7ebec19c89c18cadbf6187786c121f29dJakub Pawlowski @Override 6377998be9e44f7797a96fb0a2568b95581ebccc1d0Jakub Pawlowski public void onPeriodicAdvertisingEnabled(int advertiserId, boolean enable, int status) { 638a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski handler.post(new Runnable() { 639a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski @Override 640a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski public void run() { 6415f00f173fb2da2622803029e69ff85f932e9020bJakub Pawlowski AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId); 6427998be9e44f7797a96fb0a2568b95581ebccc1d0Jakub Pawlowski callback.onPeriodicAdvertisingEnabled(advertisingSet, enable, status); 643a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 644a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski }); 645a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 646a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski }; 647a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski } 648a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9Jakub Pawlowski 649f7bd6b26c73b7ea0bbfd00b75c23895eca281affJakub Pawlowski private void postStartSetFailure(Handler handler, final AdvertisingSetCallback callback, 650a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He final int error) { 651f7bd6b26c73b7ea0bbfd00b75c23895eca281affJakub Pawlowski handler.post(new Runnable() { 652a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He @Override 653a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He public void run() { 654a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He callback.onAdvertisingSetStarted(null, 0, error); 655a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He } 656a355e5efaf45a534ee6437aa4bae7d30f18c0ec2Jack He }); 657f7bd6b26c73b7ea0bbfd00b75c23895eca281affJakub Pawlowski } 658f7bd6b26c73b7ea0bbfd00b75c23895eca281affJakub Pawlowski 6599a974be631a3ff2e7e754f79167eb024ee55925eWei Wang private void postStartFailure(final AdvertiseCallback callback, final int error) { 6606d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang mHandler.post(new Runnable() { 6619a974be631a3ff2e7e754f79167eb024ee55925eWei Wang @Override 6626d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang public void run() { 663af74e66e29a518157cb78fcef4b4fc532b7f60b0Wei Wang callback.onStartFailure(error); 6646d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 6656d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang }); 6666d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang } 6679a974be631a3ff2e7e754f79167eb024ee55925eWei Wang 6689a974be631a3ff2e7e754f79167eb024ee55925eWei Wang private void postStartSuccess(final AdvertiseCallback callback, 6699a974be631a3ff2e7e754f79167eb024ee55925eWei Wang final AdvertiseSettings settings) { 6709a974be631a3ff2e7e754f79167eb024ee55925eWei Wang mHandler.post(new Runnable() { 6719a974be631a3ff2e7e754f79167eb024ee55925eWei Wang 6729a974be631a3ff2e7e754f79167eb024ee55925eWei Wang @Override 6739a974be631a3ff2e7e754f79167eb024ee55925eWei Wang public void run() { 6749a974be631a3ff2e7e754f79167eb024ee55925eWei Wang callback.onStartSuccess(settings); 6759a974be631a3ff2e7e754f79167eb024ee55925eWei Wang } 6769a974be631a3ff2e7e754f79167eb024ee55925eWei Wang }); 6779a974be631a3ff2e7e754f79167eb024ee55925eWei Wang } 6786d81118032b92caa0f5cfebe11af02a98f819d5eWei Wang} 679