1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.bluetooth.le; 18 19import android.annotation.Nullable; 20import android.os.Parcel; 21import android.os.Parcelable; 22 23import java.util.Objects; 24 25/** 26 * PeriodicAdvertisingReport for Bluetooth LE synchronized advertising. 27 * @hide 28 */ 29public final class PeriodicAdvertisingReport implements Parcelable { 30 31 /** 32 * The data returned is complete 33 */ 34 public static final int DATA_COMPLETE = 0; 35 36 /** 37 * The data returned is incomplete. The controller was unsuccessfull to 38 * receive all chained packets, returning only partial data. 39 */ 40 public static final int DATA_INCOMPLETE_TRUNCATED = 2; 41 42 private int syncHandle; 43 private int txPower; 44 private int rssi; 45 private int dataStatus; 46 47 // periodic advertising data. 48 @Nullable 49 private ScanRecord data; 50 51 // Device timestamp when the result was last seen. 52 private long timestampNanos; 53 54 /** 55 * Constructor of periodic advertising result. 56 * 57 */ 58 public PeriodicAdvertisingReport(int syncHandle, int txPower, int rssi, 59 int dataStatus, ScanRecord data) { 60 this.syncHandle = syncHandle; 61 this.txPower = txPower; 62 this.rssi = rssi; 63 this.dataStatus = dataStatus; 64 this.data = data; 65 } 66 67 private PeriodicAdvertisingReport(Parcel in) { 68 readFromParcel(in); 69 } 70 71 @Override 72 public void writeToParcel(Parcel dest, int flags) { 73 dest.writeInt(syncHandle); 74 dest.writeLong(txPower); 75 dest.writeInt(rssi); 76 dest.writeInt(dataStatus); 77 if (data != null) { 78 dest.writeInt(1); 79 dest.writeByteArray(data.getBytes()); 80 } else { 81 dest.writeInt(0); 82 } 83 } 84 85 private void readFromParcel(Parcel in) { 86 syncHandle = in.readInt(); 87 txPower = in.readInt(); 88 rssi = in.readInt(); 89 dataStatus = in.readInt(); 90 if (in.readInt() == 1) { 91 data = ScanRecord.parseFromBytes(in.createByteArray()); 92 } 93 } 94 95 @Override 96 public int describeContents() { 97 return 0; 98 } 99 100 /** 101 * Returns the synchronization handle. 102 */ 103 public int getSyncHandle() { 104 return syncHandle; 105 } 106 107 /** 108 * Returns the transmit power in dBm. The valid range is [-127, 126]. Value 109 * of 127 means information was not available. 110 */ 111 public int getTxPower() { 112 return txPower; 113 } 114 115 /** 116 * Returns the received signal strength in dBm. The valid range is [-127, 20]. 117 */ 118 public int getRssi() { 119 return rssi; 120 } 121 122 /** 123 * Returns the data status. Can be one of {@link PeriodicAdvertisingReport#DATA_COMPLETE} 124 * or {@link PeriodicAdvertisingReport#DATA_INCOMPLETE_TRUNCATED}. 125 */ 126 public int getDataStatus() { 127 return dataStatus; 128 } 129 130 /** 131 * Returns the data contained in this periodic advertising report. 132 */ 133 @Nullable 134 public ScanRecord getData() { 135 return data; 136 } 137 138 /** 139 * Returns timestamp since boot when the scan record was observed. 140 */ 141 public long getTimestampNanos() { 142 return timestampNanos; 143 } 144 145 @Override 146 public int hashCode() { 147 return Objects.hash(syncHandle, txPower, rssi, dataStatus, data, timestampNanos); 148 } 149 150 @Override 151 public boolean equals(Object obj) { 152 if (this == obj) { 153 return true; 154 } 155 if (obj == null || getClass() != obj.getClass()) { 156 return false; 157 } 158 PeriodicAdvertisingReport other = (PeriodicAdvertisingReport) obj; 159 return (syncHandle == other.syncHandle) && 160 (txPower == other.txPower) && 161 (rssi == other.rssi) && 162 (dataStatus == other.dataStatus) && 163 Objects.equals(data, other.data) && 164 (timestampNanos == other.timestampNanos); 165 } 166 167 @Override 168 public String toString() { 169 return "PeriodicAdvertisingReport{syncHandle=" + syncHandle + 170 ", txPower=" + txPower + ", rssi=" + rssi + ", dataStatus=" + dataStatus + 171 ", data=" + Objects.toString(data) + ", timestampNanos=" + timestampNanos + '}'; 172 } 173 174 public static final Parcelable.Creator<PeriodicAdvertisingReport> CREATOR = new Creator<PeriodicAdvertisingReport>() { 175 @Override 176 public PeriodicAdvertisingReport createFromParcel(Parcel source) { 177 return new PeriodicAdvertisingReport(source); 178 } 179 180 @Override 181 public PeriodicAdvertisingReport[] newArray(int size) { 182 return new PeriodicAdvertisingReport[size]; 183 } 184 }; 185} 186