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 
17 package android.bluetooth.le;
18 
19 import android.annotation.Nullable;
20 import android.os.Parcel;
21 import android.os.Parcelable;
22 
23 import java.util.Objects;
24 
25 /**
26  * PeriodicAdvertisingReport for Bluetooth LE synchronized advertising.
27  *
28  * @hide
29  */
30 public final class PeriodicAdvertisingReport implements Parcelable {
31 
32     /** The data returned is complete */
33     public static final int DATA_COMPLETE = 0;
34 
35     /**
36      * The data returned is incomplete. The controller was unsuccessful to receive all chained
37      * packets, returning only partial data.
38      */
39     public static final int DATA_INCOMPLETE_TRUNCATED = 2;
40 
41     private int mSyncHandle;
42     private int mTxPower;
43     private int mRssi;
44     private int mDataStatus;
45 
46     // periodic advertising data.
47     @Nullable private ScanRecord mData;
48 
49     // Device timestamp when the result was last seen.
50     private long mTimestampNanos;
51 
52     /** Constructor of periodic advertising result. */
PeriodicAdvertisingReport( int syncHandle, int txPower, int rssi, int dataStatus, ScanRecord data)53     public PeriodicAdvertisingReport(
54             int syncHandle, int txPower, int rssi, int dataStatus, ScanRecord data) {
55         mSyncHandle = syncHandle;
56         mTxPower = txPower;
57         mRssi = rssi;
58         mDataStatus = dataStatus;
59         mData = data;
60     }
61 
PeriodicAdvertisingReport(Parcel in)62     private PeriodicAdvertisingReport(Parcel in) {
63         readFromParcel(in);
64     }
65 
66     @Override
writeToParcel(Parcel dest, int flags)67     public void writeToParcel(Parcel dest, int flags) {
68         dest.writeInt(mSyncHandle);
69         dest.writeInt(mTxPower);
70         dest.writeInt(mRssi);
71         dest.writeInt(mDataStatus);
72         if (mData != null) {
73             dest.writeInt(1);
74             dest.writeByteArray(mData.getBytes());
75         } else {
76             dest.writeInt(0);
77         }
78     }
79 
readFromParcel(Parcel in)80     private void readFromParcel(Parcel in) {
81         mSyncHandle = in.readInt();
82         mTxPower = in.readInt();
83         mRssi = in.readInt();
84         mDataStatus = in.readInt();
85         if (in.readInt() == 1) {
86             mData = ScanRecord.parseFromBytes(in.createByteArray());
87         }
88     }
89 
90     @Override
describeContents()91     public int describeContents() {
92         return 0;
93     }
94 
95     /** Returns the synchronization handle. */
getSyncHandle()96     public int getSyncHandle() {
97         return mSyncHandle;
98     }
99 
100     /**
101      * Returns the transmit power in dBm. The valid range is [-127, 126]. Value of 127 means
102      * information was not available.
103      */
getTxPower()104     public int getTxPower() {
105         return mTxPower;
106     }
107 
108     /** Returns the received signal strength in dBm. The valid range is [-127, 20]. */
getRssi()109     public int getRssi() {
110         return mRssi;
111     }
112 
113     /**
114      * Returns the data status. Can be one of {@link PeriodicAdvertisingReport#DATA_COMPLETE} or
115      * {@link PeriodicAdvertisingReport#DATA_INCOMPLETE_TRUNCATED}.
116      */
getDataStatus()117     public int getDataStatus() {
118         return mDataStatus;
119     }
120 
121     /** Returns the data contained in this periodic advertising report. */
122     @Nullable
getData()123     public ScanRecord getData() {
124         return mData;
125     }
126 
127     /** Returns timestamp since boot when the scan record was observed. */
getTimestampNanos()128     public long getTimestampNanos() {
129         return mTimestampNanos;
130     }
131 
132     @Override
hashCode()133     public int hashCode() {
134         return Objects.hash(mSyncHandle, mTxPower, mRssi, mDataStatus, mData, mTimestampNanos);
135     }
136 
137     @Override
equals(@ullable Object obj)138     public boolean equals(@Nullable Object obj) {
139         if (this == obj) {
140             return true;
141         }
142         if (obj == null || getClass() != obj.getClass()) {
143             return false;
144         }
145         PeriodicAdvertisingReport other = (PeriodicAdvertisingReport) obj;
146         return (mSyncHandle == other.mSyncHandle)
147                 && (mTxPower == other.mTxPower)
148                 && (mRssi == other.mRssi)
149                 && (mDataStatus == other.mDataStatus)
150                 && Objects.equals(mData, other.mData)
151                 && (mTimestampNanos == other.mTimestampNanos);
152     }
153 
154     @Override
toString()155     public String toString() {
156         return "PeriodicAdvertisingReport{syncHandle="
157                 + mSyncHandle
158                 + ", txPower="
159                 + mTxPower
160                 + ", rssi="
161                 + mRssi
162                 + ", dataStatus="
163                 + mDataStatus
164                 + ", data="
165                 + Objects.toString(mData)
166                 + ", timestampNanos="
167                 + mTimestampNanos
168                 + '}';
169     }
170 
171     public static final @android.annotation.NonNull Parcelable.Creator<PeriodicAdvertisingReport>
172             CREATOR =
173                     new Creator<PeriodicAdvertisingReport>() {
174                         @Override
175                         public PeriodicAdvertisingReport createFromParcel(Parcel source) {
176                             return new PeriodicAdvertisingReport(source);
177                         }
178 
179                         @Override
180                         public PeriodicAdvertisingReport[] newArray(int size) {
181                             return new PeriodicAdvertisingReport[size];
182                         }
183                     };
184 }
185