Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 685c1758 authored by Wei Wang's avatar Wei Wang
Browse files

More API modification of BLE APIs (1/2).

Changed include:

1) Add serviceDataUuid to filter so it matches sanRecord and
AdvertiseData.
2) Add raw bytes to ScanRecord and make ScanResult take a ScanRecord
instead of raw bytes.
3) Change from setServiceUuid(List) to addServiceUuid(ParcelUuid).
4) Added include device name
5) Removed service not registered and added ADVERTISE_DATA_TOO_LARGE.
6) Fixed a few comments.

Change-Id: Ibbe07183b1293835c4a84728d1cd2d61e5d627d3
parent 3d63a9c7
Loading
Loading
Loading
Loading
+11 −16
Original line number Diff line number Diff line
@@ -6499,14 +6499,15 @@ package android.bluetooth.le {
    method public void onStartFailure(int);
    method public void onStartSuccess(android.bluetooth.le.AdvertiseSettings);
    field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
    field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1
    field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5
    field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4
    field public static final int ADVERTISE_FAILED_SERVICE_UNKNOWN = 1; // 0x1
    field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2
  }
  public final class AdvertiseData implements android.os.Parcelable {
    method public int describeContents();
    method public boolean getIncludeDeviceName();
    method public boolean getIncludeTxPowerLevel();
    method public int getManufacturerId();
    method public byte[] getManufacturerSpecificData();
@@ -6514,16 +6515,16 @@ package android.bluetooth.le {
    method public android.os.ParcelUuid getServiceDataUuid();
    method public java.util.List<android.os.ParcelUuid> getServiceUuids();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public static final class AdvertiseData.Builder {
    ctor public AdvertiseData.Builder();
    method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid);
    method public android.bluetooth.le.AdvertiseData build();
    method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean);
    method public android.bluetooth.le.AdvertiseData.Builder setIncludeTxPowerLevel(boolean);
    method public android.bluetooth.le.AdvertiseData.Builder setManufacturerData(int, byte[]);
    method public android.bluetooth.le.AdvertiseData.Builder setServiceData(android.os.ParcelUuid, byte[]);
    method public android.bluetooth.le.AdvertiseData.Builder setServiceUuids(java.util.List<android.os.ParcelUuid>);
  }
  public final class AdvertiseSettings implements android.os.Parcelable {
@@ -6540,7 +6541,6 @@ package android.bluetooth.le {
    field public static final int ADVERTISE_TX_POWER_LOW = 1; // 0x1
    field public static final int ADVERTISE_TX_POWER_MEDIUM = 2; // 0x2
    field public static final int ADVERTISE_TX_POWER_ULTRA_LOW = 0; // 0x0
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public static final class AdvertiseSettings.Builder {
@@ -6583,15 +6583,12 @@ package android.bluetooth.le {
    method public byte[] getManufacturerData();
    method public byte[] getManufacturerDataMask();
    method public int getManufacturerId();
    method public int getMaxRssi();
    method public int getMinRssi();
    method public byte[] getServiceData();
    method public byte[] getServiceDataMask();
    method public android.os.ParcelUuid getServiceUuid();
    method public android.os.ParcelUuid getServiceUuidMask();
    method public boolean matches(android.bluetooth.le.ScanResult);
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public static final class ScanFilter.Builder {
@@ -6601,15 +6598,15 @@ package android.bluetooth.le {
    method public android.bluetooth.le.ScanFilter.Builder setDeviceName(java.lang.String);
    method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[]);
    method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[], byte[]);
    method public android.bluetooth.le.ScanFilter.Builder setRssiRange(int, int);
    method public android.bluetooth.le.ScanFilter.Builder setServiceData(byte[]);
    method public android.bluetooth.le.ScanFilter.Builder setServiceData(byte[], byte[]);
    method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[]);
    method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[], byte[]);
    method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid);
    method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid);
  }
  public final class ScanRecord {
    method public int getAdvertiseFlags();
    method public byte[] getBytes();
    method public java.lang.String getDeviceName();
    method public int getManufacturerId();
    method public byte[] getManufacturerSpecificData();
@@ -6617,30 +6614,28 @@ package android.bluetooth.le {
    method public android.os.ParcelUuid getServiceDataUuid();
    method public java.util.List<android.os.ParcelUuid> getServiceUuids();
    method public int getTxPowerLevel();
    method public static android.bluetooth.le.ScanRecord parseFromBytes(byte[]);
  }
  public final class ScanResult implements android.os.Parcelable {
    ctor public ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long);
    method public int describeContents();
    method public android.bluetooth.BluetoothDevice getDevice();
    method public int getRssi();
    method public byte[] getScanRecord();
    method public android.bluetooth.le.ScanRecord getScanRecord();
    method public long getTimestampNanos();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public final class ScanSettings implements android.os.Parcelable {
    method public int describeContents();
    method public int getCallbackType();
    method public long getReportDelaySeconds();
    method public long getReportDelayMillis();
    method public int getScanMode();
    method public int getScanResultType();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int CALLBACK_TYPE_ALL_MATCHES = 1; // 0x1
    field public static final int CALLBACK_TYPE_FIRST_MATCH = 2; // 0x2
    field public static final int CALLBACK_TYPE_MATCH_LOST = 4; // 0x4
    field public static final android.os.Parcelable.Creator CREATOR;
    field public static final int SCAN_MODE_BALANCED = 1; // 0x1
    field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
    field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
@@ -6651,7 +6646,7 @@ package android.bluetooth.le {
    ctor public ScanSettings.Builder();
    method public android.bluetooth.le.ScanSettings build();
    method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int);
    method public android.bluetooth.le.ScanSettings.Builder setReportDelaySeconds(long);
    method public android.bluetooth.le.ScanSettings.Builder setReportDelayMillis(long);
    method public android.bluetooth.le.ScanSettings.Builder setScanMode(int);
  }
+5 −5
Original line number Diff line number Diff line
@@ -23,15 +23,15 @@ public abstract class AdvertiseCallback {

    /**
     * The requested operation was successful.
     *
     * @hide
     */
    public static final int ADVERTISE_SUCCESS = 0;

    /**
     * Failed to start advertising as the advertisement data contains services that are not
     * added to the local Bluetooth GATT server.
     * Failed to start advertising as the advertise data to be broadcasted is larger than 31 bytes.
     */
    public static final int ADVERTISE_FAILED_SERVICE_UNKNOWN = 1;
    public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1;

    /**
     * Failed to start advertising because no advertising instance is available.
@@ -53,7 +53,6 @@ public abstract class AdvertiseCallback {
     */
    public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5;


    /**
     * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertising} indicating
     * that the advertising has been started successfully.
@@ -67,7 +66,8 @@ public abstract class AdvertiseCallback {
    /**
     * Callback when advertising could not be started.
     *
     * @param errorCode Error code (see ADVERTISE_FAILED_* constants) for
     * @param errorCode Error code (see ADVERTISE_FAILED_* constants) for advertising start
     *            failures.
     */
    public void onStartFailure(int errorCode) {
    }
+48 −30
Original line number Diff line number Diff line
@@ -27,10 +27,10 @@ import java.util.Arrays;
import java.util.List;

/**
 * Advertisement data packet container for Bluetooth LE advertising. This represents the data to be
 * Advertise data packet container for Bluetooth LE advertising. This represents the data to be
 * advertised as well as the scan response data for active scans.
 *
 * <p>Use {@link AdvertiseData.Builder} to create an instance of {@link AdvertiseData} to be
 * <p>
 * Use {@link AdvertiseData.Builder} to create an instance of {@link AdvertiseData} to be
 * advertised.
 *
 * @see BluetoothLeAdvertiser
@@ -50,18 +50,21 @@ public final class AdvertiseData implements Parcelable {
    @Nullable
    private final byte[] mServiceData;

    private boolean mIncludeTxPowerLevel;
    private final boolean mIncludeTxPowerLevel;
    private final boolean mIncludeDeviceName;

    private AdvertiseData(List<ParcelUuid> serviceUuids,
            ParcelUuid serviceDataUuid, byte[] serviceData,
            int manufacturerId,
            byte[] manufacturerSpecificData, boolean includeTxPowerLevel) {
            byte[] manufacturerSpecificData, boolean includeTxPowerLevel,
            boolean includeDeviceName) {
        mServiceUuids = serviceUuids;
        mManufacturerId = manufacturerId;
        mManufacturerSpecificData = manufacturerSpecificData;
        mServiceDataUuid = serviceDataUuid;
        mServiceData = serviceData;
        mIncludeTxPowerLevel = includeTxPowerLevel;
        mIncludeDeviceName = includeDeviceName;
    }

    /**
@@ -109,13 +112,20 @@ public final class AdvertiseData implements Parcelable {
        return mIncludeTxPowerLevel;
    }

    /**
     * Whether the device name will be included in the advertisement packet.
     */
    public boolean getIncludeDeviceName() {
        return mIncludeDeviceName;
    }

    @Override
    public String toString() {
        return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerId="
                + mManufacturerId + ", mManufacturerSpecificData="
                + Arrays.toString(mManufacturerSpecificData) + ", mServiceDataUuid="
                + mServiceDataUuid + ", mServiceData=" + Arrays.toString(mServiceData)
                + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + "]";
                + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" + "]";
    }

    @Override
@@ -153,8 +163,12 @@ public final class AdvertiseData implements Parcelable {
            }
        }
        dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0));
        dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0));
    }

    /**
     * @hide
     */
    public static final Parcelable.Creator<AdvertiseData> CREATOR =
            new Creator<AdvertiseData>() {
            @Override
@@ -168,7 +182,9 @@ public final class AdvertiseData implements Parcelable {
                    if (in.readInt() > 0) {
                        List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
                        in.readList(uuids, ParcelUuid.class.getClassLoader());
                        builder.setServiceUuids(uuids);
                        for (ParcelUuid uuid : uuids) {
                            builder.addServiceUuid(uuid);
                        }
                    }
                    int manufacturerId = in.readInt();
                    int manufacturerDataLength = in.readInt();
@@ -188,6 +204,7 @@ public final class AdvertiseData implements Parcelable {
                        }
                    }
                    builder.setIncludeTxPowerLevel(in.readByte() == 1);
                    builder.setIncludeDeviceName(in.readByte() == 1);
                    return builder.build();
                }
            };
@@ -203,8 +220,7 @@ public final class AdvertiseData implements Parcelable {
        private static final int FLAGS_FIELD_BYTES = 3;

        @Nullable
        private List<ParcelUuid> mServiceUuids;
        private boolean mIncludeTxPowerLevel;
        private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>();
        private int mManufacturerId;
        @Nullable
        private byte[] mManufacturerSpecificData;
@@ -212,27 +228,25 @@ public final class AdvertiseData implements Parcelable {
        private ParcelUuid mServiceDataUuid;
        @Nullable
        private byte[] mServiceData;
        private boolean mIncludeTxPowerLevel;
        private boolean mIncludeDeviceName;

        /**
         * Set the service UUIDs.
         * Add a service UUID to advertise data.
         *
         * <p><b>Note:</b> The corresponding Bluetooth Gatt services need to already
         * be added on the device (using {@link android.bluetooth.BluetoothGattServer#addService}) prior
         * to advertising them.
         *
         * @param serviceUuids Service UUIDs to be advertised.
         * @param serviceUuid A service UUID to be advertised.
         * @throws IllegalArgumentException If the {@code serviceUuids} are null.
         */
        public Builder setServiceUuids(List<ParcelUuid> serviceUuids) {
            if (serviceUuids == null) {
        public Builder addServiceUuid(ParcelUuid serviceUuid) {
            if (serviceUuid == null) {
                throw new IllegalArgumentException("serivceUuids are null");
            }
            mServiceUuids = serviceUuids;
            mServiceUuids.add(serviceUuid);
            return this;
        }

        /**
         * Add service data to advertisement.
         * Add service data to advertise data.
         *
         * @param serviceDataUuid 16-bit UUID of the service the data is associated with
         * @param serviceData Service data
@@ -251,10 +265,10 @@ public final class AdvertiseData implements Parcelable {

        /**
         * Set manufacturer specific data.
         *
         * <p>Please refer to the Bluetooth Assigned Numbers document provided by the
         * <a href="https://www.bluetooth.org">Bluetooth SIG</a> for a list of existing
         * company identifiers.
         * <p>
         * Please refer to the Bluetooth Assigned Numbers document provided by the <a
         * href="https://www.bluetooth.org">Bluetooth SIG</a> for a list of existing company
         * identifiers.
         *
         * @param manufacturerId Manufacturer ID assigned by Bluetooth SIG.
         * @param manufacturerSpecificData Manufacturer specific data
@@ -275,27 +289,31 @@ public final class AdvertiseData implements Parcelable {
        }

        /**
         * Whether the transmission power level should be included in the advertising packet.
         * Whether the transmission power level should be included in the advertise packet. Tx power
         * level field takes 3 bytes in advertise packet.
         */
        public Builder setIncludeTxPowerLevel(boolean includeTxPowerLevel) {
            mIncludeTxPowerLevel = includeTxPowerLevel;
            return this;
        }

        /**
         * Set whether the device name should be included in advertise packet.
         */
        public Builder setIncludeDeviceName(boolean includeDeviceName) {
            mIncludeDeviceName = includeDeviceName;
            return this;
        }

        /**
         * Build the {@link AdvertiseData}.
         *
         * @throws IllegalArgumentException If the data size is larger than 31 bytes.
         */
        public AdvertiseData build() {
            if (totalBytes() > MAX_ADVERTISING_DATA_BYTES) {
                throw new IllegalArgumentException(
                        "advertisement data size is larger than 31 bytes");
            }
            return new AdvertiseData(mServiceUuids,
                    mServiceDataUuid,
                    mServiceData, mManufacturerId, mManufacturerSpecificData,
                    mIncludeTxPowerLevel);
                    mIncludeTxPowerLevel, mIncludeDeviceName);
        }

        // Compute the size of the advertisement data.
+3 −0
Original line number Diff line number Diff line
@@ -139,6 +139,9 @@ public final class AdvertiseSettings implements Parcelable {
        dest.writeInt(mAdvertiseTimeoutSeconds);
    }

    /**
     * @hide
     */
    public static final Parcelable.Creator<AdvertiseSettings> CREATOR =
            new Creator<AdvertiseSettings>() {
            @Override
+27 −23
Original line number Diff line number Diff line
@@ -57,6 +57,8 @@ public final class BluetoothLeAdvertiser {

    /**
     * Use BluetoothAdapter.getLeAdvertiser() instead.
     *
     * @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management
     * @hide
     */
    public BluetoothLeAdvertiser(IBluetoothManager bluetoothManager) {
@@ -66,9 +68,8 @@ public final class BluetoothLeAdvertiser {
    }

    /**
     * Start Bluetooth LE Advertising. On success, the {@code advertiseData} will be
     * broadcasted. Returns immediately, the operation status is delivered through
     * {@code callback}.
     * Start Bluetooth LE Advertising. On success, the {@code advertiseData} will be broadcasted.
     * Returns immediately, the operation status is delivered through {@code callback}.
     * <p>
     * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
     *
@@ -83,9 +84,9 @@ public final class BluetoothLeAdvertiser {

    /**
     * Start Bluetooth LE Advertising. The {@code advertiseData} will be broadcasted if the
     * operation succeeds. The {@code scanResponse} is returned when a scanning device sends
     * an active scan request. This method returns immediately, the operation status is
     * delivered through {@code callback}.
     * operation succeeds. The {@code scanResponse} is returned when a scanning device sends an
     * active scan request. This method returns immediately, the operation status is delivered
     * through {@code callback}.
     * <p>
     * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
     *
@@ -142,11 +143,13 @@ public final class BluetoothLeAdvertiser {
            throw new IllegalArgumentException("callback cannot be null");
        }
        AdvertiseCallbackWrapper wrapper = mLeAdvertisers.get(callback);
        if (wrapper == null) return;
        if (wrapper == null)
            return;

        try {
            IBluetoothGatt gatt = mBluetoothManager.getBluetoothGatt();
            if (gatt != null) gatt.stopMultiAdvertising(wrapper.mLeHandle);
            if (gatt != null)
                gatt.stopMultiAdvertising(wrapper.mClientIf);

            if (wrapper.advertiseStopped()) {
                mLeAdvertisers.remove(callback);
@@ -167,10 +170,10 @@ public final class BluetoothLeAdvertiser {
        private final AdvertiseSettings mSettings;
        private final IBluetoothGatt mBluetoothGatt;

        // mLeHandle 0: not registered
        // mClientIf 0: not registered
        // -1: scan stopped
        // >0: registered and scan started
        private int mLeHandle;
        private int mClientIf;
        private boolean isAdvertising = false;

        public AdvertiseCallbackWrapper(AdvertiseCallback advertiseCallback,
@@ -182,13 +185,13 @@ public final class BluetoothLeAdvertiser {
            mScanResponse = scanResponse;
            mSettings = settings;
            mBluetoothGatt = bluetoothGatt;
            mLeHandle = 0;
            mClientIf = 0;
        }

        public boolean advertiseStarted() {
            boolean started = false;
            synchronized (this) {
                if (mLeHandle == -1) {
                if (mClientIf == -1) {
                    return false;
                }
                try {
@@ -196,7 +199,7 @@ public final class BluetoothLeAdvertiser {
                } catch (InterruptedException e) {
                    Log.e(TAG, "Callback reg wait interrupted: ", e);
                }
                started = (mLeHandle > 0 && isAdvertising);
                started = (mClientIf > 0 && isAdvertising);
            }
            return started;
        }
@@ -220,18 +223,18 @@ public final class BluetoothLeAdvertiser {
            Log.d(TAG, "onClientRegistered() - status=" + status + " clientIf=" + clientIf);
            synchronized (this) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    mLeHandle = clientIf;
                    mClientIf = clientIf;
                    try {
                        mBluetoothGatt.startMultiAdvertising(mLeHandle, mAdvertisement,
                        mBluetoothGatt.startMultiAdvertising(mClientIf, mAdvertisement,
                                mScanResponse, mSettings);
                    } catch (RemoteException e) {
                        Log.e(TAG, "fail to start le advertise: " + e);
                        mLeHandle = -1;
                        mClientIf = -1;
                        notifyAll();
                    }
                } else {
                    // registration failed
                    mLeHandle = -1;
                    mClientIf = -1;
                    notifyAll();
                }
            }
@@ -342,8 +345,8 @@ public final class BluetoothLeAdvertiser {
                    isAdvertising = !isAdvertising;
                    if (!isAdvertising) {
                        try {
                            mBluetoothGatt.unregisterClient(mLeHandle);
                            mLeHandle = -1;
                            mBluetoothGatt.unregisterClient(mClientIf);
                            mClientIf = -1;
                        } catch (RemoteException e) {
                            Log.e(TAG, "remote exception when unregistering", e);
                        }
@@ -351,7 +354,8 @@ public final class BluetoothLeAdvertiser {
                        mAdvertiseCallback.onStartSuccess(null);
                    }
                } else {
                    if (!isAdvertising) mAdvertiseCallback.onStartFailure(status);
                    if (!isAdvertising)
                        mAdvertiseCallback.onStartFailure(status);
                }
                notifyAll();
            }
Loading