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