Merge "Bluetooth 5 periodc scan API (1/2)"

This commit is contained in:
Jakub Pawlowski
2017-03-08 19:03:47 +00:00
committed by Gerrit Code Review
11 changed files with 673 additions and 0 deletions

View File

@@ -131,6 +131,7 @@ LOCAL_SRC_FILES += \
core/java/android/bluetooth/IBluetoothGattCallback.aidl \
core/java/android/bluetooth/IBluetoothGattServerCallback.aidl \
core/java/android/bluetooth/le/IAdvertiserCallback.aidl \
core/java/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl \
core/java/android/bluetooth/le/IScannerCallback.aidl \
core/java/android/content/IClipboard.aidl \
core/java/android/content/IContentService.aidl \

View File

@@ -6695,6 +6695,7 @@ package android.bluetooth {
method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
method public java.lang.String getName();
method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
method public int getProfileConnectionState(int);
method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7490,6 +7491,36 @@ package android.bluetooth.le {
method public void stopScan(android.bluetooth.le.ScanCallback);
}
public abstract class PeriodicAdvertisingCallback {
ctor public PeriodicAdvertisingCallback();
method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
method public void onSyncLost(int);
field public static final int SYNC_NO_RESOURCES = 2; // 0x2
field public static final int SYNC_NO_RESPONSE = 1; // 0x1
}
public final class PeriodicAdvertisingManager {
method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
}
public final class PeriodicAdvertisingReport implements android.os.Parcelable {
ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
method public int describeContents();
method public android.bluetooth.le.ScanRecord getData();
method public int getDataStatus();
method public int getRssi();
method public int getSyncHandle();
method public long getTimestampNanos();
method public int getTxPower();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
field public static final int DATA_COMPLETE = 0; // 0x0
field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
}
public abstract class ScanCallback {
ctor public ScanCallback();
method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);

View File

@@ -6993,6 +6993,7 @@ package android.bluetooth {
method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
method public java.lang.String getName();
method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
method public int getProfileConnectionState(int);
method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7797,6 +7798,36 @@ package android.bluetooth.le {
method public void stopScan(android.bluetooth.le.ScanCallback);
}
public abstract class PeriodicAdvertisingCallback {
ctor public PeriodicAdvertisingCallback();
method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
method public void onSyncLost(int);
field public static final int SYNC_NO_RESOURCES = 2; // 0x2
field public static final int SYNC_NO_RESPONSE = 1; // 0x1
}
public final class PeriodicAdvertisingManager {
method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
}
public final class PeriodicAdvertisingReport implements android.os.Parcelable {
ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
method public int describeContents();
method public android.bluetooth.le.ScanRecord getData();
method public int getDataStatus();
method public int getRssi();
method public int getSyncHandle();
method public long getTimestampNanos();
method public int getTxPower();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
field public static final int DATA_COMPLETE = 0; // 0x0
field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
}
public final class ResultStorageDescriptor implements android.os.Parcelable {
ctor public ResultStorageDescriptor(int, int, int);
method public int describeContents();

View File

@@ -6704,6 +6704,7 @@ package android.bluetooth {
method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
method public java.lang.String getName();
method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
method public int getProfileConnectionState(int);
method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
method public android.bluetooth.BluetoothDevice getRemoteDevice(java.lang.String);
@@ -7499,6 +7500,36 @@ package android.bluetooth.le {
method public void stopScan(android.bluetooth.le.ScanCallback);
}
public abstract class PeriodicAdvertisingCallback {
ctor public PeriodicAdvertisingCallback();
method public void onPeriodicAdvertisingReport(android.bluetooth.le.PeriodicAdvertisingReport);
method public void onSyncEstablished(int, android.bluetooth.BluetoothDevice, int, int, int, int);
method public void onSyncLost(int);
field public static final int SYNC_NO_RESOURCES = 2; // 0x2
field public static final int SYNC_NO_RESPONSE = 1; // 0x1
}
public final class PeriodicAdvertisingManager {
method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback);
method public void registerSync(android.bluetooth.le.ScanResult, int, int, android.bluetooth.le.PeriodicAdvertisingCallback, android.os.Handler);
method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback);
}
public final class PeriodicAdvertisingReport implements android.os.Parcelable {
ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord);
method public int describeContents();
method public android.bluetooth.le.ScanRecord getData();
method public int getDataStatus();
method public int getRssi();
method public int getSyncHandle();
method public long getTimestampNanos();
method public int getTxPower();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingReport> CREATOR;
field public static final int DATA_COMPLETE = 0; // 0x0
field public static final int DATA_INCOMPLETE_TRUNCATED = 2; // 0x2
}
public abstract class ScanCallback {
ctor public ScanCallback();
method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);

View File

@@ -26,6 +26,7 @@ import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.PeriodicAdvertisingManager;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanRecord;
@@ -525,6 +526,7 @@ public final class BluetoothAdapter {
private static BluetoothLeScanner sBluetoothLeScanner;
private static BluetoothLeAdvertiser sBluetoothLeAdvertiser;
private static PeriodicAdvertisingManager sPeriodicAdvertisingManager;
private final IBluetoothManager mManagerService;
private IBluetooth mService;
@@ -629,6 +631,30 @@ public final class BluetoothAdapter {
return sBluetoothLeAdvertiser;
}
/**
* Returns a {@link PeriodicAdvertisingManager} object for Bluetooth LE Periodic Advertising
* operations. Will return null if Bluetooth is turned off or if Bluetooth LE Periodic
* Advertising is not supported on this device.
* <p>
* Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
* supported on this device before calling this method.
*/
public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
if (!getLeAccess())
return null;
if (!isLePeriodicAdvertisingSupported())
return null;
synchronized (mLock) {
if (sPeriodicAdvertisingManager == null) {
sPeriodicAdvertisingManager =
new PeriodicAdvertisingManager(mManagerService);
}
}
return sPeriodicAdvertisingManager;
}
/**
* Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
*/

View File

@@ -21,6 +21,7 @@ import android.bluetooth.BluetoothGattService;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.bluetooth.le.ResultStorageDescriptor;
import android.os.ParcelUuid;
@@ -29,6 +30,7 @@ import android.os.WorkSource;
import android.bluetooth.IBluetoothGattCallback;
import android.bluetooth.IBluetoothGattServerCallback;
import android.bluetooth.le.IAdvertiserCallback;
import android.bluetooth.le.IPeriodicAdvertisingCallback;
import android.bluetooth.le.IScannerCallback;
/**
@@ -53,6 +55,9 @@ interface IBluetoothGatt {
in AdvertiseSettings settings);
void stopMultiAdvertising(in int advertiserId);
void registerSync(in ScanResult scanResult, in int skip, in int timeout, in IPeriodicAdvertisingCallback callback);
void unregisterSync(in IPeriodicAdvertisingCallback callback);
void registerClient(in ParcelUuid appId, in IBluetoothGattCallback callback);
void unregisterClient(in int clientIf);
void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport);

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.bluetooth.le;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.PeriodicAdvertisingReport;
/**
* Callback definitions for interacting with Periodic Advertising
* @hide
*/
oneway interface IPeriodicAdvertisingCallback {
void onSyncEstablished(in int syncHandle, in BluetoothDevice device, in int advertisingSid,
in int skip, in int timeout, in int status);
void onPeriodicAdvertisingReport(in PeriodicAdvertisingReport report);
void onSyncLost(in int syncHandle);
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.bluetooth.le;
import android.bluetooth.BluetoothDevice;
/**
* Bluetooth LE periodic advertising callbacks, used to deliver periodic
* advertising operation status.
*
* @see PeriodicAdvertisingManager#createSync
*/
public abstract class PeriodicAdvertisingCallback {
/**
* The requested operation was successful.
*
* @hide
*/
public static final int SYNC_SUCCESS = 0;
/**
* Sync failed to be established because remote device did not respond.
*/
public static final int SYNC_NO_RESPONSE = 1;
/**
* Sync failed to be established because controller can't support more syncs.
*/
public static final int SYNC_NO_RESOURCES = 2;
/**
* Callback when synchronization was established.
*
* @param syncHandle handle used to identify this synchronization.
* @param device remote device.
* @param advertisingSid synchronized advertising set id.
* @param skip The number of periodic advertising packets that can be skipped
* after a successful receive in force. @see PeriodicAdvertisingManager#createSync
* @param timeout Synchronization timeout for the periodic advertising in force. One
* unit is 10ms. @see PeriodicAdvertisingManager#createSync
* @param timeout
* @param status operation status.
*/
public void onSyncEstablished(int syncHandle, BluetoothDevice device,
int advertisingSid, int skip, int timeout,
int status) {}
/**
* Callback when periodic advertising report is received.
*
* @param report periodic advertising report.
*/
public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) {}
/**
* Callback when periodic advertising synchronization was lost.
*
* @param syncHandle handle used to identify this synchronization.
*/
public void onSyncLost(int syncHandle) {}
}

View File

@@ -0,0 +1,237 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package android.bluetooth.le;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothManager;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
import java.util.IdentityHashMap;
import java.util.Map;
/**
* This class provides methods to perform periodic advertising related
* operations. An application can register for periodic advertisements using
* {@link PeriodicAdvertisingManager#registerSync}.
* <p>
* Use {@link BluetoothAdapter#getPeriodicAdvertisingManager()} to get an
* instance of {@link PeriodicAdvertisingManager}.
* <p>
* <b>Note:</b> Most of the methods here require
* {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
*/
public final class PeriodicAdvertisingManager {
private static final String TAG = "PeriodicAdvertisingManager";
private static final int SKIP_MIN = 0;
private static final int SKIP_MAX = 499;
private static final int TIMEOUT_MIN = 10;
private static final int TIMEOUT_MAX = 16384;
private static final int SYNC_STARTING = -1;
private final IBluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
/* maps callback, to callback wrapper and sync handle */
Map<PeriodicAdvertisingCallback,
IPeriodicAdvertisingCallback /* callbackWrapper */> callbackWrappers;
/**
* Use {@link BluetoothAdapter#getBluetoothLeScanner()} instead.
*
* @param bluetoothManager BluetoothManager that conducts overall Bluetooth Management.
* @hide
*/
public PeriodicAdvertisingManager(IBluetoothManager bluetoothManager) {
mBluetoothManager = bluetoothManager;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
callbackWrappers = new IdentityHashMap<>();
}
/**
* Synchronize with periodic advertising pointed to by the {@code scanResult}.
* The {@code scanResult} used must contain a valid advertisingSid. First
* call to registerSync will use the {@code skip} and {@code timeout} provided.
* Subsequent calls from other apps, trying to sync with same set will reuse
* existing sync, thus {@code skip} and {@code timeout} values will not take
* effect. The values in effect will be returned in
* {@link PeriodicAdvertisingCallback#onSyncEstablished}.
*
* @param scanResult Scan result containing advertisingSid.
* @param skip The number of periodic advertising packets that can be skipped
* after a successful receive. Must be between 0 and 499.
* @param timeout Synchronization timeout for the periodic advertising. One
* unit is 10ms. Must be between 10 (100ms) and 16384 (163.84s).
* @param callback Callback used to deliver all operations status.
* @throws IllegalArgumentException if {@code scanResult} is null or {@code
* skip} is invalid or {@code timeout} is invalid or {@code callback} is null.
*/
public void registerSync(ScanResult scanResult, int skip, int timeout,
PeriodicAdvertisingCallback callback) {
registerSync(scanResult, skip, timeout, callback, null);
}
/**
* Synchronize with periodic advertising pointed to by the {@code scanResult}.
* The {@code scanResult} used must contain a valid advertisingSid. First
* call to registerSync will use the {@code skip} and {@code timeout} provided.
* Subsequent calls from other apps, trying to sync with same set will reuse
* existing sync, thus {@code skip} and {@code timeout} values will not take
* effect. The values in effect will be returned in
* {@link PeriodicAdvertisingCallback#onSyncEstablished}.
*
* @param scanResult Scan result containing advertisingSid.
* @param skip The number of periodic advertising packets that can be skipped
* after a successful receive. Must be between 0 and 499.
* @param timeout Synchronization timeout for the periodic advertising. One
* unit is 10ms. Must be between 10 (100ms) and 16384 (163.84s).
* @param callback Callback used to deliver all operations status.
* @param handler thread upon which the callbacks will be invoked.
* @throws IllegalArgumentException if {@code scanResult} is null or {@code
* skip} is invalid or {@code timeout} is invalid or {@code callback} is null.
*/
public void registerSync(ScanResult scanResult, int skip, int timeout,
PeriodicAdvertisingCallback callback, Handler handler) {
if (callback == null) {
throw new IllegalArgumentException("callback can't be null");
}
if (scanResult == null) {
throw new IllegalArgumentException("scanResult can't be null");
}
if (scanResult.getAdvertisingSid() == ScanResult.SID_NOT_PRESENT) {
throw new IllegalArgumentException("scanResult must contain a valid sid");
}
if (skip < SKIP_MIN || skip > SKIP_MAX) {
throw new IllegalArgumentException(
"timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX);
}
if (timeout < TIMEOUT_MIN || timeout > TIMEOUT_MAX) {
throw new IllegalArgumentException(
"timeout must be between " + TIMEOUT_MIN + " and " + TIMEOUT_MAX);
}
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
} catch (RemoteException e) {
Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
callback.onSyncEstablished(0, scanResult.getDevice(), scanResult.getAdvertisingSid(),
skip, timeout,
PeriodicAdvertisingCallback.SYNC_NO_RESOURCES);
return;
}
if (handler == null)
handler = new Handler(Looper.getMainLooper());
IPeriodicAdvertisingCallback wrapped = wrap(callback, handler);
callbackWrappers.put(callback, wrapped);
try {
gatt.registerSync(scanResult, skip, timeout, wrapped);
} catch (RemoteException e) {
Log.e(TAG, "Failed to register sync - ", e);
return;
}
}
/**
* Cancel pending attempt to create sync, or terminate existing sync.
*
* @param callback Callback used to deliver all operations status.
* @throws IllegalArgumentException if {@code callback} is null, or not a properly
* registered callback.
*/
public void unregisterSync(PeriodicAdvertisingCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback can't be null");
}
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
} catch (RemoteException e) {
Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
return;
}
IPeriodicAdvertisingCallback wrapper = callbackWrappers.remove(callback);
if (wrapper == null) {
throw new IllegalArgumentException("callback was not properly registered");
}
try {
gatt.unregisterSync(wrapper);
} catch (RemoteException e) {
Log.e(TAG, "Failed to cancel sync creation - ", e);
return;
}
}
private IPeriodicAdvertisingCallback wrap(PeriodicAdvertisingCallback callback, Handler handler) {
return new IPeriodicAdvertisingCallback.Stub() {
public void onSyncEstablished(int syncHandle, BluetoothDevice device,
int advertisingSid, int skip, int timeout, int status) {
handler.post(new Runnable() {
@Override
public void run() {
callback.onSyncEstablished(syncHandle, device, advertisingSid, skip, timeout,
status);
if (status != PeriodicAdvertisingCallback.SYNC_SUCCESS) {
// App can still unregister the sync until notified it failed. Remove callback
// after app was notifed.
callbackWrappers.remove(callback);
}
}
});
}
public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) {
handler.post(new Runnable() {
@Override
public void run() {
callback.onPeriodicAdvertisingReport(report);
}
});
}
public void onSyncLost(int syncHandle) {
handler.post(new Runnable() {
@Override
public void run() {
callback.onSyncLost(syncHandle);
// App can still unregister the sync until notified it's lost. Remove callback after
// app was notifed.
callbackWrappers.remove(callback);
}
});
}
};
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.bluetooth.le;
parcelable PeriodicAdvertisingReport;

View File

@@ -0,0 +1,184 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.bluetooth.le;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Objects;
/**
* PeriodicAdvertisingReport for Bluetooth LE synchronized advertising.
*/
public final class PeriodicAdvertisingReport implements Parcelable {
/**
* The data returned is complete
*/
public static final int DATA_COMPLETE = 0;
/**
* The data returned is incomplete. The controller was unsuccessfull to
* receive all chained packets, returning only partial data.
*/
public static final int DATA_INCOMPLETE_TRUNCATED = 2;
private int syncHandle;
private int txPower;
private int rssi;
private int dataStatus;
// periodic advertising data.
@Nullable
private ScanRecord data;
// Device timestamp when the result was last seen.
private long timestampNanos;
/**
* Constructor of periodic advertising result.
*
*/
public PeriodicAdvertisingReport(int syncHandle, int txPower, int rssi,
int dataStatus, ScanRecord data) {
this.syncHandle = syncHandle;
this.txPower = txPower;
this.rssi = rssi;
this.dataStatus = dataStatus;
this.data = data;
}
private PeriodicAdvertisingReport(Parcel in) {
readFromParcel(in);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(syncHandle);
dest.writeLong(txPower);
dest.writeInt(rssi);
dest.writeInt(dataStatus);
if (data != null) {
dest.writeInt(1);
dest.writeByteArray(data.getBytes());
} else {
dest.writeInt(0);
}
}
private void readFromParcel(Parcel in) {
syncHandle = in.readInt();
txPower = in.readInt();
rssi = in.readInt();
dataStatus = in.readInt();
if (in.readInt() == 1) {
data = ScanRecord.parseFromBytes(in.createByteArray());
}
}
@Override
public int describeContents() {
return 0;
}
/**
* Returns the synchronization handle.
*/
public int getSyncHandle() {
return syncHandle;
}
/**
* Returns the transmit power in dBm. The valid range is [-127, 126]. Value
* of 127 means information was not available.
*/
public int getTxPower() {
return txPower;
}
/**
* Returns the received signal strength in dBm. The valid range is [-127, 20].
*/
public int getRssi() {
return rssi;
}
/**
* Returns the data status. Can be one of {@link PeriodicAdvertisingReport#DATA_COMPLETE}
* or {@link PeriodicAdvertisingReport#DATA_INCOMPLETE_TRUNCATED}.
*/
public int getDataStatus() {
return dataStatus;
}
/**
* Returns the data contained in this periodic advertising report.
*/
@Nullable
public ScanRecord getData() {
return data;
}
/**
* Returns timestamp since boot when the scan record was observed.
*/
public long getTimestampNanos() {
return timestampNanos;
}
@Override
public int hashCode() {
return Objects.hash(syncHandle, txPower, rssi, dataStatus, data, timestampNanos);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
PeriodicAdvertisingReport other = (PeriodicAdvertisingReport) obj;
return (syncHandle == other.syncHandle) &&
(txPower == other.txPower) &&
(rssi == other.rssi) &&
(dataStatus == other.dataStatus) &&
Objects.equals(data, other.data) &&
(timestampNanos == other.timestampNanos);
}
@Override
public String toString() {
return "PeriodicAdvertisingReport{syncHandle=" + syncHandle +
", txPower=" + txPower + ", rssi=" + rssi + ", dataStatus=" + dataStatus +
", data=" + Objects.toString(data) + ", timestampNanos=" + timestampNanos + '}';
}
public static final Parcelable.Creator<PeriodicAdvertisingReport> CREATOR = new Creator<PeriodicAdvertisingReport>() {
@Override
public PeriodicAdvertisingReport createFromParcel(Parcel source) {
return new PeriodicAdvertisingReport(source);
}
@Override
public PeriodicAdvertisingReport[] newArray(int size) {
return new PeriodicAdvertisingReport[size];
}
};
}