• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.net.wifi.rtt;
18 
19 import android.annotation.ElapsedRealtimeLong;
20 import android.annotation.FlaggedApi;
21 import android.annotation.IntDef;
22 import android.annotation.IntRange;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.SuppressLint;
26 import android.annotation.SystemApi;
27 import android.net.MacAddress;
28 import android.net.wifi.OuiKeyedData;
29 import android.net.wifi.ParcelUtil;
30 import android.net.wifi.ScanResult;
31 import android.net.wifi.WifiAnnotations.ChannelWidth;
32 import android.net.wifi.aware.PeerHandle;
33 import android.os.Build;
34 import android.os.Parcel;
35 import android.os.Parcelable;
36 import android.util.Log;
37 
38 import androidx.annotation.RequiresApi;
39 
40 import com.android.modules.utils.build.SdkLevel;
41 import com.android.wifi.flags.Flags;
42 
43 import java.lang.annotation.Retention;
44 import java.lang.annotation.RetentionPolicy;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.Collections;
48 import java.util.List;
49 import java.util.Objects;
50 
51 /**
52  * Ranging result for a request started by
53  * {@link WifiRttManager#startRanging(RangingRequest, java.util.concurrent.Executor, RangingResultCallback)}.
54  * Results are returned in {@link RangingResultCallback#onRangingResults(List)}.
55  * <p>
56  * A ranging result is the distance measurement result for a single device specified in the
57  * {@link RangingRequest}.
58  */
59 public final class RangingResult implements Parcelable {
60     private static final String TAG = "RangingResult";
61     private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
62 
63     /** @hide */
64     @IntDef({STATUS_SUCCESS, STATUS_FAIL, STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC})
65     @Retention(RetentionPolicy.SOURCE)
66     public @interface RangeResultStatus {
67     }
68 
69     /**
70      * Individual range request status, {@link #getStatus()}. Indicates ranging operation was
71      * successful and distance value is valid.
72      */
73     public static final int STATUS_SUCCESS = 0;
74 
75     /**
76      * Individual range request status, {@link #getStatus()}. Indicates ranging operation failed
77      * and the distance value is invalid.
78      */
79     public static final int STATUS_FAIL = 1;
80 
81     /**
82      * Individual range request status, {@link #getStatus()}. Indicates that the ranging operation
83      * failed because the specified peer does not support IEEE 802.11mc RTT operations. Support by
84      * an Access Point can be confirmed using
85      * {@link android.net.wifi.ScanResult#is80211mcResponder()}.
86      * <p>
87      * On such a failure, the individual result fields of {@link RangingResult} such as
88      * {@link RangingResult#getDistanceMm()} are invalid.
89      */
90     public static final int STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC = 2;
91 
92     /**
93      * The unspecified value.
94      */
95     public static final int UNSPECIFIED = -1;
96 
97     private final @RangeResultStatus int mStatus;
98     private final MacAddress mMac;
99     private final PeerHandle mPeerHandle;
100     private final int mDistanceMm;
101     private final int mDistanceStdDevMm;
102     private final int mRssi;
103     private final int mNumAttemptedMeasurements;
104     private final int mNumSuccessfulMeasurements;
105     private final byte[] mLci;
106     private final byte[] mLcr;
107     private final ResponderLocation mResponderLocation;
108     private final long mTimestamp;
109     private final boolean mIs80211mcMeasurement;
110     private final int mFrequencyMHz;
111     private final int mPacketBw;
112     private final boolean mIs80211azNtbMeasurement;
113     private final long mNtbMinMeasurementTime;
114     private final long mNtbMaxMeasurementTime;
115     private final int mI2rTxLtfRepetitions;
116     private final int mR2iTxLtfRepetitions;
117     private final int mNumTxSpatialStreams;
118     private final int mNumRxSpatialStreams;
119     private List<OuiKeyedData> mVendorData;
120     private final boolean mIsRangingAuthenticated;
121     private final boolean mIsRangingFrameProtected;
122     private final boolean mIsSecureHeLtfEnabled;
123     private final int mSecureHeLtfProtocolVersion;
124     private final byte[] mPasnComebackCookie;
125     private final long mPasnComebackAfterMillis;
126 
127     /**
128      * Builder class used to construct {@link RangingResult} objects.
129      */
130     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
131     public static final class Builder {
132         private @RangeResultStatus int mStatus = STATUS_FAIL;
133         private MacAddress mMac = null;
134         private PeerHandle mPeerHandle = null;
135         private int mDistanceMm = 0;
136         private int mDistanceStdDevMm = 0;
137         private int mRssi = -127;
138         private int mNumAttemptedMeasurements = 0;
139         private int mNumSuccessfulMeasurements = 0;
140         private byte[] mLci = null;
141         private  byte[] mLcr = null;
142         private ResponderLocation mResponderLocation = null;
143         private long mTimestamp = 0;
144         private boolean mIs80211mcMeasurement = false;
145         private int mFrequencyMHz = UNSPECIFIED;
146         private int mPacketBw = UNSPECIFIED;
147         private boolean mIs80211azNtbMeasurement = false;
148         private long mNtbMinMeasurementTime = UNSPECIFIED;
149         private long mNtbMaxMeasurementTime = UNSPECIFIED;
150         private int mI2rTxLtfRepetitions = UNSPECIFIED;
151         private int mR2iTxLtfRepetitions = UNSPECIFIED;
152         private int mNumTxSpatialStreams = UNSPECIFIED;
153         private int mNumRxSpatialStreams = UNSPECIFIED;
154         private List<OuiKeyedData> mVendorData = Collections.emptyList();
155         private  boolean mIsRangingAuthenticated;
156         private  boolean mIsRangingFrameProtected;
157         private  boolean mIsSecureHeLtfEnabled;
158         private  int mSecureHeLtfProtocolVersion;
159         private byte[] mPasnComebackCookie = null;
160         private long mPasnComebackAfterMillis = UNSPECIFIED;
161 
162         /**
163          * Constructs a Builder with default values (see {@link Builder}).
164          */
Builder()165         public Builder() {}
166 
167         /**
168          * Constructs a Builder initialized from an existing {@link RangingResult} instance.
169          *
170          * @hide
171          */
Builder(@onNull RangingResult other)172         public Builder(@NonNull RangingResult other) {
173             if (other == null) {
174                 Log.e(TAG, "Cannot provide a null RangingResult");
175                 return;
176             }
177 
178             mStatus = other.mStatus;
179             mMac = other.mMac;
180             mPeerHandle = other.mPeerHandle;
181             mDistanceMm = other.mDistanceMm;
182             mDistanceStdDevMm = other.mDistanceStdDevMm;
183             mRssi = other.mRssi;
184             mNumAttemptedMeasurements = other.mNumAttemptedMeasurements;
185             mNumSuccessfulMeasurements = other.mNumSuccessfulMeasurements;
186             if (other.mLci != null) mLci = other.mLci.clone();
187             if (other.mLcr != null) mLcr = other.mLcr.clone();
188             mResponderLocation = new ResponderLocation(mLci, mLcr);
189             mTimestamp = other.mTimestamp;
190             mIs80211mcMeasurement = other.mIs80211mcMeasurement;
191             mFrequencyMHz = other.mFrequencyMHz;
192             mPacketBw = other.mPacketBw;
193             mIs80211azNtbMeasurement = other.mIs80211azNtbMeasurement;
194             mNtbMinMeasurementTime = other.mNtbMinMeasurementTime;
195             mNtbMaxMeasurementTime = other.mNtbMaxMeasurementTime;
196             mI2rTxLtfRepetitions = other.mI2rTxLtfRepetitions;
197             mR2iTxLtfRepetitions = other.mR2iTxLtfRepetitions;
198             mNumTxSpatialStreams = other.mNumTxSpatialStreams;
199             mNumRxSpatialStreams = other.mNumRxSpatialStreams;
200             mIsRangingAuthenticated = other.mIsRangingAuthenticated;
201             mIsRangingFrameProtected = other.mIsRangingFrameProtected;
202             mIsSecureHeLtfEnabled = other.mIsSecureHeLtfEnabled;
203             mSecureHeLtfProtocolVersion = other.mSecureHeLtfProtocolVersion;
204             if (other.mPasnComebackCookie != null) {
205                 mPasnComebackCookie = other.mPasnComebackCookie.clone();
206                 mPasnComebackAfterMillis = other.mPasnComebackAfterMillis;
207             }
208             mVendorData = new ArrayList<>(other.mVendorData);
209         }
210 
211         /**
212          * Sets the Range result status.
213          *
214          * @param status Ranging result status, if not set defaults to
215          *               {@link #STATUS_FAIL}.
216          * @return The builder to facilitate chaining.
217          */
218         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
219         @NonNull
setStatus(@angeResultStatus int status)220         public Builder setStatus(@RangeResultStatus int status) {
221             mStatus = status;
222             return this;
223         }
224 
225         /**
226          * Sets the MAC address of the ranging result.
227          *
228          * @param macAddress Mac address, if not defaults to null.
229          * @return The builder to facilitate chaining.
230          */
231         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
232         @NonNull
setMacAddress(@ullable MacAddress macAddress)233         public Builder setMacAddress(@Nullable MacAddress macAddress) {
234             mMac = macAddress;
235             return this;
236         }
237 
238 
239         /**
240          * Sets the peer handle. Applicable only for NAN Ranging.
241          *
242          * @param peerHandle Opaque object used to represent a Wi-Fi Aware peer. If not set,
243          *                   defaults to null.
244          * @return The builder to facilitate chaining.
245          */
246         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
247         @NonNull
setPeerHandle(@ullable PeerHandle peerHandle)248         public Builder setPeerHandle(@Nullable PeerHandle peerHandle) {
249             mPeerHandle = peerHandle;
250             return this;
251         }
252 
253         /**
254          * Sets the distance in millimeter.
255          *
256          * @param distanceMm distance. If not set, defaults to 0.
257          * @return The builder to facilitate chaining.
258          */
259         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
260         @NonNull
setDistanceMm(int distanceMm)261         public Builder setDistanceMm(int distanceMm) {
262             mDistanceMm = distanceMm;
263             return this;
264         }
265 
266         /**
267          * Sets the standard deviation of the distance in millimeter.
268          *
269          * @param distanceStdDevMm Standard deviation of the distance measurement. If not set
270          *                         defaults to 0.
271          * @return The builder to facilitate chaining.
272          */
273         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
274         @NonNull
setDistanceStdDevMm(int distanceStdDevMm)275         public Builder setDistanceStdDevMm(int distanceStdDevMm) {
276             mDistanceStdDevMm = distanceStdDevMm;
277             return this;
278         }
279 
280         /**
281          * Sets the average RSSI.
282          *
283          * @param rssi Average RSSI. If not set, defaults to -127.
284          * @return The builder to facilitate chaining.
285          */
286         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
287         @NonNull
setRssi(int rssi)288         public Builder setRssi(int rssi) {
289             mRssi = rssi;
290             return this;
291         }
292 
293         /**
294          * Sets the total number of RTT measurements attempted.
295          *
296          * @param numAttemptedMeasurements Number of attempted measurements. If not set, default
297          *                                 to 0.
298          * @return The builder to facilitate chaining.
299          */
300         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
301         @NonNull
setNumAttemptedMeasurements(int numAttemptedMeasurements)302         public Builder setNumAttemptedMeasurements(int numAttemptedMeasurements) {
303             mNumAttemptedMeasurements = numAttemptedMeasurements;
304             return this;
305         }
306 
307         /**
308          * Sets the total number of successful RTT measurements.
309          *
310          * @param numSuccessfulMeasurements Number of successful measurements. If not set, default
311          *                                 to 0.
312          * @return The builder to facilitate chaining.
313          */
314         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
315         @NonNull
setNumSuccessfulMeasurements(int numSuccessfulMeasurements)316         public Builder setNumSuccessfulMeasurements(int numSuccessfulMeasurements) {
317             mNumSuccessfulMeasurements = numSuccessfulMeasurements;
318             return this;
319         }
320 
321         /**
322          * Sets the Location Configuration Information (LCI).
323          *
324          * LCI provides data about the access point's (AP) physical location, such as its
325          * latitude, longitude, and altitude. The format is specified in the IEEE 802.11-2016
326          * specifications, section 9.4.2.22.10.
327          *
328          * @param lci Location configuration information. If not set, defaults to null.
329          * @return The builder to facilitate chaining.
330          */
331         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
332         @NonNull
setLci(@ullable byte[] lci)333         public Builder setLci(@Nullable byte[] lci) {
334             mLci = lci;
335             return this;
336         }
337 
338         /**
339          * Sets the Location Civic Report (LCR).
340          *
341          * LCR provides additional details about the AP's location in a human-readable format,
342          * such as the street address, building name, or floor number. This can be helpful for
343          * users to understand the context of their location within a building or complex.
344          *
345          * The format is
346          * specified in the IEEE 802.11-2016 specifications, section 9.4.2.22.13.
347          *
348          * @param lcr Location civic report. If not set, defaults to null.
349          * @return The builder to facilitate chaining.
350          */
351         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
352         @NonNull
setLcr(@ullable byte[] lcr)353         public Builder setLcr(@Nullable byte[] lcr) {
354             mLcr = lcr;
355             return this;
356         }
357 
358         /**
359          * Sets Responder Location.
360          *
361          * ResponderLocation is both a Location Configuration Information (LCI) decoder and a
362          * Location Civic Report (LCR) decoder for information received from a Wi-Fi Access Point
363          * (AP) during Wi-Fi RTT ranging process.
364          *
365          * @param responderLocation Responder location. If not set, defaults to null.
366          * @return The builder to facilitate chaining.
367          */
368         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
369         @NonNull
setUnverifiedResponderLocation( @ullable ResponderLocation responderLocation)370         public Builder setUnverifiedResponderLocation(
371                 @Nullable ResponderLocation responderLocation) {
372             mResponderLocation = responderLocation;
373             return this;
374         }
375 
376         /**
377          * Sets the time stamp at which the ranging operation was performed.
378          *
379          * The timestamp is in milliseconds since boot, including time spent in sleep,
380          * corresponding to values provided by {@link android.os.SystemClock#elapsedRealtime()}.
381          *
382          * @param timestamp time stamp in milliseconds. If not set, default to 0.
383          * @return The builder to facilitate chaining.
384          */
385         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
386         @NonNull
setRangingTimestampMillis(@lapsedRealtimeLong long timestamp)387         public Builder setRangingTimestampMillis(@ElapsedRealtimeLong long timestamp) {
388             mTimestamp = timestamp;
389             return this;
390         }
391 
392 
393         /**
394          * Sets whether the ranging measurement was performed using IEEE 802.11mc ranging method.
395          * If {@link #set80211mcMeasurement(boolean)} is set as false and
396          * {@link #set80211azNtbMeasurement(boolean)} is also set as false, ranging measurement was
397          * performed using one-side RTT. If not set, default to false.
398          *
399          * @param is80211mcMeasurement true for IEEE 802.11mc measure, otherwise false.
400          * @return The builder to facilitate chaining.
401          */
402         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
403         @NonNull
set80211mcMeasurement(boolean is80211mcMeasurement)404         public Builder set80211mcMeasurement(boolean is80211mcMeasurement) {
405             mIs80211mcMeasurement = is80211mcMeasurement;
406             return this;
407         }
408 
409         /**
410          * Sets the center frequency of the primary 20 MHz frequency (in MHz) of the channel over
411          * which the measurement frames are sent. If not set, default to
412          * {@link RangingResult#UNSPECIFIED}
413          *
414          * @param frequencyMHz Frequency.
415          * @return The builder to facilitate chaining.
416          */
417         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
418         @NonNull
setMeasurementChannelFrequencyMHz(int frequencyMHz)419         public Builder setMeasurementChannelFrequencyMHz(int frequencyMHz) {
420             mFrequencyMHz = frequencyMHz;
421             return this;
422         }
423 
424         /**
425          * Sets the bandwidth used to transmit the RTT measurement frame. If not set, default to
426          * {@link RangingResult#UNSPECIFIED}.
427          *
428          * @param measurementBandwidth Measurement bandwidth.
429          * @return The builder to facilitate chaining.
430          */
431         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
432         @NonNull
setMeasurementBandwidth(@hannelWidth int measurementBandwidth)433         public Builder setMeasurementBandwidth(@ChannelWidth int measurementBandwidth) {
434             mPacketBw = measurementBandwidth;
435             return this;
436         }
437 
438         /**
439          * Sets whether the ranging measurement was performed using IEEE 802.11az non-trigger
440          * ranging method. If {@link #set80211azNtbMeasurement(boolean)} is set as false and
441          * {@link #set80211mcMeasurement(boolean)} is also set as false, ranging measurement was
442          * performed using one-side RTT. If not set defaults to false.
443          *
444          * @param is80211azNtbMeasurement true for IEEE 802.11az non-trigger based measurement,
445          *                                otherwise false.
446          * @return The builder to facilitate chaining.
447          */
448         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
449         @NonNull
set80211azNtbMeasurement(boolean is80211azNtbMeasurement)450         public Builder set80211azNtbMeasurement(boolean is80211azNtbMeasurement) {
451             mIs80211azNtbMeasurement = is80211azNtbMeasurement;
452             return this;
453         }
454 
455         /**
456          * Sets minimum time between measurements in microseconds for IEEE 802.11az non-trigger
457          * based ranging.  If not set, defaults to {@link RangingResult#UNSPECIFIED}.
458          *
459          * @param ntbMinMeasurementTime non-trigger based ranging minimum measurement time.
460          * @return The builder to facilitate chaining.
461          */
462         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
463         @NonNull
setMinTimeBetweenNtbMeasurementsMicros(long ntbMinMeasurementTime)464         public Builder setMinTimeBetweenNtbMeasurementsMicros(long ntbMinMeasurementTime) {
465             mNtbMinMeasurementTime = ntbMinMeasurementTime;
466             return this;
467         }
468 
469         /**
470          * Sets maximum time between measurements in microseconds for IEEE 802.11az non-trigger
471          * based ranging. If not set, defaults to {@link RangingResult#UNSPECIFIED}.
472          *
473          * @param ntbMaxMeasurementTime non-trigger based ranging maximum measurement time.
474          * @return The builder to facilitate chaining.
475          */
476         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
477         @NonNull
setMaxTimeBetweenNtbMeasurementsMicros(long ntbMaxMeasurementTime)478         public Builder setMaxTimeBetweenNtbMeasurementsMicros(long ntbMaxMeasurementTime) {
479             mNtbMaxMeasurementTime = ntbMaxMeasurementTime;
480             return this;
481         }
482 
483         /**
484          * Sets LTF repetitions that the initiator station used in the preamble. If not set,
485          * defaults to {@link RangingResult#UNSPECIFIED}.
486          *
487          * @param i2rTxLtfRepetitions LFT repetition count.
488          * @return The builder to facilitate chaining.
489          */
490         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
491         @NonNull
set80211azInitiatorTxLtfRepetitionsCount(int i2rTxLtfRepetitions)492         public Builder set80211azInitiatorTxLtfRepetitionsCount(int i2rTxLtfRepetitions) {
493             mI2rTxLtfRepetitions = i2rTxLtfRepetitions;
494             return this;
495         }
496 
497         /**
498          * Sets LTF repetitions that the responder station used in the preamble. If not set,
499          * defaults to {@link RangingResult#UNSPECIFIED}.
500          *
501          * @param r2iTxLtfRepetitions LFT repetition count.
502          * @return The builder to facilitate chaining.
503          */
504         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
505         @NonNull
set80211azResponderTxLtfRepetitionsCount(int r2iTxLtfRepetitions)506         public Builder set80211azResponderTxLtfRepetitionsCount(int r2iTxLtfRepetitions) {
507             mR2iTxLtfRepetitions = r2iTxLtfRepetitions;
508             return this;
509         }
510 
511         /**
512          * Sets number of transmit spatial streams that the initiator station used for the
513          * ranging result. If not set, defaults to {@link RangingResult#UNSPECIFIED}.
514          *
515          * @param numTxSpatialStreams Number of transmit spatial streams.
516          * @return The builder to facilitate chaining.
517          */
518         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
519         @NonNull
set80211azNumberOfTxSpatialStreams(int numTxSpatialStreams)520         public Builder set80211azNumberOfTxSpatialStreams(int numTxSpatialStreams) {
521             mNumTxSpatialStreams = numTxSpatialStreams;
522             return this;
523         }
524 
525         /**
526          * Sets number of receive spatial streams that the initiator station used for the ranging
527          * result. If not set, defaults to {@link RangingResult#UNSPECIFIED}.
528          *
529          * @param numRxSpatialStreams Number of receive spatial streams.
530          * @return The builder to facilitate chaining.
531          */
532         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
533         @NonNull
set80211azNumberOfRxSpatialStreams(int numRxSpatialStreams)534         public Builder set80211azNumberOfRxSpatialStreams(int numRxSpatialStreams) {
535             mNumRxSpatialStreams = numRxSpatialStreams;
536             return this;
537         }
538 
539         /**
540          * Set additional vendor-provided configuration data.
541          *
542          * @param vendorData List of {@link android.net.wifi.OuiKeyedData} containing the
543          *                   vendor-provided configuration data. Note that multiple elements with
544          *                   the same OUI are allowed.
545          * @hide
546          */
547         @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
548         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
549         @SystemApi
550         @NonNull
setVendorData(@onNull List<OuiKeyedData> vendorData)551         public Builder setVendorData(@NonNull List<OuiKeyedData> vendorData) {
552             if (!SdkLevel.isAtLeastV()) {
553                 throw new UnsupportedOperationException();
554             }
555             if (vendorData == null) {
556                 throw new IllegalArgumentException("setVendorData received a null value");
557             }
558             mVendorData = vendorData;
559             return this;
560         }
561 
562         /**
563          * Set whether mutual authentication is done for the ranging. Authentication of ranging
564          * enables frame protection also. See {@link #setRangingFrameProtected(boolean)}.
565          *
566          * @param isRangingAuthenticated true if ranging is mutually authenticated, otherwise false.
567          * @return The builder to facilitate chaining.
568          */
569         @NonNull
570         @FlaggedApi(Flags.FLAG_SECURE_RANGING)
setRangingAuthenticated(boolean isRangingAuthenticated)571         public Builder setRangingAuthenticated(boolean isRangingAuthenticated) {
572             mIsRangingAuthenticated = isRangingAuthenticated;
573             return this;
574         }
575 
576         /**
577          * Set whether ranging frames are protected. Frame protection provides both encryption and
578          * integrity protection to the ranging frames.
579          *
580          * @param isRangingFrameProtected true if ranging frames are protected, otherwise false.
581          * @return The builder to facilitate chaining.
582          */
583         @NonNull
584         @FlaggedApi(Flags.FLAG_SECURE_RANGING)
setRangingFrameProtected(boolean isRangingFrameProtected)585         public Builder setRangingFrameProtected(boolean isRangingFrameProtected) {
586             mIsRangingFrameProtected = isRangingFrameProtected;
587             return this;
588         }
589 
590         /**
591          * Set whether secure HE-LTF is used for this ranging.
592          *
593          * @param isSecureHeLtfEnabled true if secure HE-LTF is enabled, otherwise false.
594          * @return The builder to facilitate chaining.
595          */
596         @NonNull
597         @FlaggedApi(Flags.FLAG_SECURE_RANGING)
setSecureHeLtfEnabled(boolean isSecureHeLtfEnabled)598         public Builder setSecureHeLtfEnabled(boolean isSecureHeLtfEnabled) {
599             mIsSecureHeLtfEnabled = isSecureHeLtfEnabled;
600             return this;
601         }
602 
603         /**
604          * Set secure HE-LTF protocol version used for this ranging.
605          *
606          * The secure HE-LTF negotiation supports negotiation of the secure HE-LTF protocol version
607          * which allows a responder and an initiator to negotiate the highest mutually supported
608          * secure HE-LTF protocol version.
609          *
610          * Refer IEEE 802.11az-2022 spec, section 9.4.2.298 Ranging Parameters element.
611          *
612          * @param secureHeLtfProtocolVersion Secure HE-LTF protocol version.
613          * @return The builder to facilitate chaining.
614          */
615         @NonNull
616         @FlaggedApi(Flags.FLAG_SECURE_RANGING)
setSecureHeLtfProtocolVersion( @ntRangefrom = 0, to = 7) int secureHeLtfProtocolVersion)617         public Builder setSecureHeLtfProtocolVersion(
618                 @IntRange(from = 0, to = 7) int secureHeLtfProtocolVersion) {
619             mSecureHeLtfProtocolVersion = secureHeLtfProtocolVersion;
620             return  this;
621         }
622 
623         /**
624          * Set comeback cookie. See {@link #getPasnComebackCookie()}. If not set, default value
625          * is null.
626          *
627          * @param pasnComebackCookie an opaque  sequence of octets
628          * @return The builder to facilitate chaining.
629          */
630         @NonNull
631         @FlaggedApi(Flags.FLAG_SECURE_RANGING)
setPasnComebackCookie(@onNull byte[] pasnComebackCookie)632         public Builder setPasnComebackCookie(@NonNull byte[] pasnComebackCookie) {
633             mPasnComebackCookie = pasnComebackCookie;
634             return  this;
635         }
636 
637         /**
638          * Set comeback after time. See {@link #getPasnComebackAfterMillis()}. If not set default
639          * value is {@link RangingResult#UNSPECIFIED}.
640          *
641          * @param comebackAfterMillis the ranging initiator (STA) must wait for the specified
642          *                            time before retrying secure ranging
643          * @return The builder to facilitate chaining.
644          */
645         @NonNull
646         @FlaggedApi(Flags.FLAG_SECURE_RANGING)
setPasnComebackAfterMillis(long comebackAfterMillis)647         public Builder setPasnComebackAfterMillis(long comebackAfterMillis) {
648             mPasnComebackAfterMillis = comebackAfterMillis;
649             return  this;
650         }
651 
652         /**
653          * Build {@link RangingResult}
654          * @return an instance of {@link RangingResult}
655          */
656         @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
657         @NonNull
build()658         public RangingResult build() {
659             if (mMac == null && mPeerHandle == null) {
660                 throw new IllegalArgumentException("Either MAC address or Peer handle is needed");
661             }
662             if (mIs80211azNtbMeasurement && mIs80211mcMeasurement) {
663                 throw new IllegalArgumentException(
664                         "A ranging result cannot use both IEEE 802.11mc and IEEE 802.11az "
665                                 + "measurements simultaneously");
666             }
667             return new RangingResult(this);
668         }
669     }
670 
671     /** @hide */
RangingResult(Builder builder)672     private RangingResult(Builder builder) {
673         mStatus = builder.mStatus;
674         mMac = builder.mMac;
675         mPeerHandle = builder.mPeerHandle;
676         mDistanceMm = builder.mDistanceMm;
677         mDistanceStdDevMm = builder.mDistanceStdDevMm;
678         mRssi = builder.mRssi;
679         mNumAttemptedMeasurements = builder.mNumAttemptedMeasurements;
680         mNumSuccessfulMeasurements = builder.mNumSuccessfulMeasurements;
681         mLci = (builder.mLci == null) ? EMPTY_BYTE_ARRAY : builder.mLci;
682         mLcr = (builder.mLcr == null) ? EMPTY_BYTE_ARRAY : builder.mLcr;
683         mResponderLocation = builder.mResponderLocation;
684         mTimestamp = builder.mTimestamp;
685         mIs80211mcMeasurement = builder.mIs80211mcMeasurement;
686         mFrequencyMHz = builder.mFrequencyMHz;
687         mPacketBw = builder.mPacketBw;
688         mIs80211azNtbMeasurement = builder.mIs80211azNtbMeasurement;
689         mNtbMinMeasurementTime = builder.mNtbMinMeasurementTime;
690         mNtbMaxMeasurementTime = builder.mNtbMaxMeasurementTime;
691         mI2rTxLtfRepetitions = builder.mI2rTxLtfRepetitions;
692         mR2iTxLtfRepetitions = builder.mR2iTxLtfRepetitions;
693         mNumRxSpatialStreams = builder.mNumRxSpatialStreams;
694         mNumTxSpatialStreams = builder.mNumTxSpatialStreams;
695         mVendorData = builder.mVendorData;
696         mIsRangingAuthenticated = builder.mIsRangingAuthenticated;
697         mIsRangingFrameProtected = builder.mIsRangingFrameProtected;
698         mIsSecureHeLtfEnabled = builder.mIsSecureHeLtfEnabled;
699         mSecureHeLtfProtocolVersion = builder.mSecureHeLtfProtocolVersion;
700         mPasnComebackCookie = builder.mPasnComebackCookie;
701         mPasnComebackAfterMillis = builder.mPasnComebackAfterMillis;
702     }
703 
704     /**
705      * @return The status of ranging measurement: {@link #STATUS_SUCCESS} in case of success, and
706      * {@link #STATUS_FAIL} in case of failure.
707      */
708     @RangeResultStatus
getStatus()709     public int getStatus() {
710         return mStatus;
711     }
712 
713     /**
714      * @return The MAC address of the device whose range measurement was requested. Will correspond
715      * to the MAC address of the device in the {@link RangingRequest}.
716      * <p>
717      * Will return a {@code null} for results corresponding to requests issued using a {@code
718      * PeerHandle}, i.e. using the {@link RangingRequest.Builder#addWifiAwarePeer(PeerHandle)} API.
719      */
720     @Nullable
getMacAddress()721     public MacAddress getMacAddress() {
722         return mMac;
723     }
724 
725     /**
726      * @return The PeerHandle of the device whose reange measurement was requested. Will correspond
727      * to the PeerHandle of the devices requested using
728      * {@link RangingRequest.Builder#addWifiAwarePeer(PeerHandle)}.
729      * <p>
730      * Will return a {@code null} for results corresponding to requests issued using a MAC address.
731      */
getPeerHandle()732     @Nullable public PeerHandle getPeerHandle() {
733         return mPeerHandle;
734     }
735 
736     /**
737      * @return The distance (in mm) to the device specified by {@link #getMacAddress()} or
738      * {@link #getPeerHandle()}.
739      * <p>
740      * Note: the measured distance may be negative for very close devices.
741      * <p>
742      * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
743      * exception.
744      */
getDistanceMm()745     public int getDistanceMm() {
746         if (mStatus != STATUS_SUCCESS) {
747             throw new IllegalStateException(
748                     "getDistanceMm(): invoked on an invalid result: getStatus()=" + mStatus);
749         }
750         return mDistanceMm;
751     }
752 
753     /**
754      * @return The standard deviation of the measured distance (in mm) to the device specified by
755      * {@link #getMacAddress()} or {@link #getPeerHandle()}. The standard deviation is calculated
756      * over the measurements executed in a single RTT burst. The number of measurements is returned
757      * by {@link #getNumSuccessfulMeasurements()} - 0 successful measurements indicate that the
758      * standard deviation is not valid (a valid standard deviation requires at least 2 data points).
759      * <p>
760      * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
761      * exception.
762      */
getDistanceStdDevMm()763     public int getDistanceStdDevMm() {
764         if (mStatus != STATUS_SUCCESS) {
765             throw new IllegalStateException(
766                     "getDistanceStdDevMm(): invoked on an invalid result: getStatus()=" + mStatus);
767         }
768         return mDistanceStdDevMm;
769     }
770 
771     /**
772      * @return The average RSSI, in units of dBm, observed during the RTT measurement.
773      * <p>
774      * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
775      * exception.
776      */
getRssi()777     public int getRssi() {
778         if (mStatus != STATUS_SUCCESS) {
779             throw new IllegalStateException(
780                     "getRssi(): invoked on an invalid result: getStatus()=" + mStatus);
781         }
782         return mRssi;
783     }
784 
785     /**
786      * @return The number of attempted measurements used in the RTT exchange resulting in this set
787      * of results. The number of successful measurements is returned by
788      * {@link #getNumSuccessfulMeasurements()} which at most, if there are no errors, will be 1
789      * less than the number of attempted measurements.
790      * <p>
791      * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
792      * exception. If the value is 0, it should be interpreted as no information available, which may
793      * occur for one-sided RTT measurements. Instead {@link RangingRequest#getRttBurstSize()}
794      * should be used instead.
795      */
getNumAttemptedMeasurements()796     public int getNumAttemptedMeasurements() {
797         if (mStatus != STATUS_SUCCESS) {
798             throw new IllegalStateException(
799                     "getNumAttemptedMeasurements(): invoked on an invalid result: getStatus()="
800                             + mStatus);
801         }
802         return mNumAttemptedMeasurements;
803     }
804 
805     /**
806      * @return The number of successful measurements used to calculate the distance and standard
807      * deviation. If the number of successful measurements if 1 then then standard deviation,
808      * returned by {@link #getDistanceStdDevMm()}, is not valid (a 0 is returned for the standard
809      * deviation).
810      * <p>
811      * The total number of measurement attempts is returned by
812      * {@link #getNumAttemptedMeasurements()}. The number of successful measurements will be at
813      * most 1 less then the number of attempted measurements.
814      * <p>
815      * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
816      * exception.
817      */
getNumSuccessfulMeasurements()818     public int getNumSuccessfulMeasurements() {
819         if (mStatus != STATUS_SUCCESS) {
820             throw new IllegalStateException(
821                     "getNumSuccessfulMeasurements(): invoked on an invalid result: getStatus()="
822                             + mStatus);
823         }
824         return mNumSuccessfulMeasurements;
825     }
826 
827     /**
828      * @return The unverified responder location represented as {@link ResponderLocation} which
829      * captures location information the responder is programmed to broadcast. The responder
830      * location is referred to as unverified, because we are relying on the device/site
831      * administrator to correctly configure its location data.
832      * <p>
833      * Will return a {@code null} when the location information cannot be parsed.
834      * <p>
835      * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
836      * exception.
837      */
838     @Nullable
getUnverifiedResponderLocation()839     public ResponderLocation getUnverifiedResponderLocation() {
840         if (mStatus != STATUS_SUCCESS) {
841             throw new IllegalStateException(
842                     "getUnverifiedResponderLocation(): invoked on an invalid result: getStatus()="
843                             + mStatus);
844         }
845         return mResponderLocation;
846     }
847 
848     /**
849      * @return The Location Configuration Information (LCI) as self-reported by the peer. The format
850      * is specified in the IEEE 802.11-2016 specifications, section 9.4.2.22.10.
851      * <p>
852      * Note: the information is NOT validated - use with caution. Consider validating it with
853      * other sources of information before using it.
854      */
855     @SuppressLint("UnflaggedApi") // Flagging API promotion from @SystemApi to public not supported
856     @NonNull
getLci()857     public byte[] getLci() {
858         if (mStatus != STATUS_SUCCESS) {
859             throw new IllegalStateException(
860                     "getLci(): invoked on an invalid result: getStatus()=" + mStatus);
861         }
862         return mLci;
863     }
864 
865     /**
866      * @return The Location Civic report (LCR) as self-reported by the peer. The format
867      * is specified in the IEEE 802.11-2016 specifications, section 9.4.2.22.13.
868      * <p>
869      * Note: the information is NOT validated - use with caution. Consider validating it with
870      * other sources of information before using it.
871      */
872     @SuppressLint("UnflaggedApi") // Flagging API promotion from @SystemApi to public not supported
873     @NonNull
getLcr()874     public byte[] getLcr() {
875         if (mStatus != STATUS_SUCCESS) {
876             throw new IllegalStateException(
877                     "getReportedLocationCivic(): invoked on an invalid result: getStatus()="
878                             + mStatus);
879         }
880         return mLcr;
881     }
882 
883     /**
884      * @return The timestamp at which the ranging operation was performed. The timestamp is in
885      * milliseconds since boot, including time spent in sleep, corresponding to values provided by
886      * {@link android.os.SystemClock#elapsedRealtime()}.
887      * <p>
888      * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
889      * exception.
890      */
getRangingTimestampMillis()891     public long getRangingTimestampMillis() {
892         if (mStatus != STATUS_SUCCESS) {
893             throw new IllegalStateException(
894                     "getRangingTimestampMillis(): invoked on an invalid result: getStatus()="
895                             + mStatus);
896         }
897         return mTimestamp;
898     }
899 
900     /**
901      * @return The result is true if the IEEE 802.11mc protocol was used. If the result is false,
902      * and {@link #is80211azNtbMeasurement()} is also false a one-side RTT result is provided
903      * which does not subtract the turnaround time at the responder.
904      * <p>
905      * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
906      * exception.
907      */
is80211mcMeasurement()908     public boolean is80211mcMeasurement() {
909         if (mStatus != STATUS_SUCCESS) {
910             throw new IllegalStateException(
911                     "is80211mcMeasurementResult(): invoked on an invalid result: getStatus()="
912                             + mStatus);
913         }
914         return mIs80211mcMeasurement;
915     }
916 
917     /**
918      * @return The result is true if the IEEE 802.11az non-trigger based protocol was used. If the
919      * result is false, and {@link #is80211mcMeasurement()} is also false a one-side RTT result
920      * is provided which does not subtract the turnaround time at the responder.
921      * <p>.
922      * Only valid if {@link #getStatus()} returns {@link #STATUS_SUCCESS}, otherwise will throw an
923      * exception.
924      */
925     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
is80211azNtbMeasurement()926     public boolean is80211azNtbMeasurement() {
927         if (mStatus != STATUS_SUCCESS) {
928             throw new IllegalStateException(
929                     "is80211azNtbMeasurement(): invoked on an invalid result: getStatus()="
930                             + mStatus);
931         }
932         return mIs80211azNtbMeasurement;
933     }
934 
935     /**
936      * Gets minimum time between measurements in microseconds for IEEE 802.11az non-trigger based
937      * ranging.
938      *
939      * The next 11az ranging measurement request must be invoked after the minimum time from the
940      * last measurement time {@link #getRangingTimestampMillis()} for the peer. Otherwise, cached
941      * ranging result will be returned for the peer.
942      */
943     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
getMinTimeBetweenNtbMeasurementsMicros()944     public long getMinTimeBetweenNtbMeasurementsMicros() {
945         return mNtbMinMeasurementTime;
946     }
947 
948     /**
949      * Gets maximum time between measurements in microseconds for IEEE 802.11az non-trigger based
950      * ranging.
951      *
952      * The next 11az ranging request needs to be invoked before the maximum time from the last
953      * measurement time {@link #getRangingTimestampMillis()}. Otherwise, the non-trigger based
954      * ranging session will be terminated and a new ranging negotiation will happen with
955      * the responding station.
956      */
957     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
getMaxTimeBetweenNtbMeasurementsMicros()958     public long getMaxTimeBetweenNtbMeasurementsMicros() {
959         return mNtbMaxMeasurementTime;
960     }
961 
962     /**
963      * Gets LTF repetitions that the responder station (RSTA) used in the preamble of the
964      * responder to initiator (I2R) null data PPDU (NDP) for this result.
965      *
966      * LTF repetitions is the multiple transmissions of HE-LTF symbols in an HE ranging NDP. An
967      * HE-LTF repetition value of 1 indicates no repetitions.
968      *
969      * @return LTF repetitions count
970      */
971     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
get80211azResponderTxLtfRepetitionsCount()972     public int get80211azResponderTxLtfRepetitionsCount() {
973         return mR2iTxLtfRepetitions;
974     }
975 
976     /**
977      * Gets LTF repetitions that the initiator station (ISTA) used in the preamble of the
978      * initiator to responder (I2R) null data PPDU (NDP) for this result.
979      *
980      * LTF repetitions is the multiple transmissions of HE-LTF symbols in an HE ranging NDP. An
981      * HE-LTF repetition value of 1 indicates no repetitions.
982      *
983      * @return LTF repetitions count
984      */
985     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
get80211azInitiatorTxLtfRepetitionsCount()986     public int get80211azInitiatorTxLtfRepetitionsCount() {
987         return mI2rTxLtfRepetitions;
988     }
989 
990     /**
991      * Gets number of transmit spatial streams that the initiator station (ISTA) used for the
992      * initiator to responder (I2R) null data PPDU (NDP) for this result.
993      *
994      * @return Number of spatial streams
995      */
996     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
get80211azNumberOfTxSpatialStreams()997     public int get80211azNumberOfTxSpatialStreams() {
998         return mNumTxSpatialStreams;
999     }
1000 
1001     /**
1002      * Gets number of receive spatial streams that the initiator station (ISTA) used for the
1003      * initiator to responder (I2R) null data PPDU (NDP) for this result.
1004      *
1005      * @return Number of spatial streams
1006      */
1007     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
get80211azNumberOfRxSpatialStreams()1008     public int get80211azNumberOfRxSpatialStreams() {
1009         return mNumRxSpatialStreams;
1010     }
1011 
1012     /**
1013      * The center frequency of the primary 20 MHz frequency (in MHz) of the channel over
1014      * which the measurement frames are sent.
1015      * @return center frequency in Mhz of the channel if available, otherwise {@link #UNSPECIFIED}
1016      * is returned.
1017      * <p>
1018      * @throws IllegalStateException if {@link #getStatus()} does not return
1019      * {@link #STATUS_SUCCESS}.
1020      */
getMeasurementChannelFrequencyMHz()1021     public int getMeasurementChannelFrequencyMHz() {
1022         if (mStatus != STATUS_SUCCESS) {
1023             throw new IllegalStateException(
1024                     "getMeasurementChannelFrequencyMHz():"
1025                     + " invoked on an invalid result: getStatus()= " + mStatus);
1026         }
1027         return mFrequencyMHz;
1028     }
1029 
1030     /**
1031      * The bandwidth used to transmit the RTT measurement frame.
1032      * @return one of {@link ScanResult#CHANNEL_WIDTH_20MHZ},
1033      * {@link ScanResult#CHANNEL_WIDTH_40MHZ},
1034      * {@link ScanResult#CHANNEL_WIDTH_80MHZ}, {@link ScanResult#CHANNEL_WIDTH_160MHZ},
1035      * {@link ScanResult #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link ScanResult #CHANNEL_WIDTH_320MHZ}
1036      * if available, otherwise {@link #UNSPECIFIED} is returned.
1037      * <p>
1038      * @throws IllegalStateException if {@link #getStatus()} does not return
1039      * {@link #STATUS_SUCCESS}.
1040      */
getMeasurementBandwidth()1041     public @ChannelWidth int getMeasurementBandwidth() {
1042         if (mStatus != STATUS_SUCCESS) {
1043             throw new IllegalStateException(
1044                     "getMeasurementBandwidth(): invoked on an invalid result: getStatus()="
1045                             + mStatus);
1046         }
1047         return mPacketBw;
1048     }
1049 
1050     /**
1051      * Get the vendor-provided configuration data, if it exists.
1052      *
1053      * @return Vendor configuration data, or empty list if it does not exist.
1054      * @hide
1055      */
1056     @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
1057     @FlaggedApi(Flags.FLAG_ANDROID_V_WIFI_API)
1058     @SystemApi
1059     @NonNull
getVendorData()1060     public List<OuiKeyedData> getVendorData() {
1061         if (!SdkLevel.isAtLeastV()) {
1062             throw new UnsupportedOperationException();
1063         }
1064         return mVendorData;
1065     }
1066 
1067     /**
1068      * @return whether the ranging is authenticated or not.
1069      *
1070      * Refer IEEE 802.11az-2022 spec, section 12 Security.
1071      */
1072     @FlaggedApi(Flags.FLAG_SECURE_RANGING)
isRangingAuthenticated()1073     public boolean isRangingAuthenticated() {
1074         return mIsRangingAuthenticated;
1075     }
1076 
1077     /**
1078      * @return whether the ranging frames are protected or not.
1079      *
1080      * Refer IEEE 802.11az-2022 spec, section 12 Security.
1081      */
1082     @FlaggedApi(Flags.FLAG_SECURE_RANGING)
isRangingFrameProtected()1083     public boolean isRangingFrameProtected() {
1084         return mIsRangingFrameProtected;
1085     }
1086 
1087     /**
1088      * @return whether the secure HE-LTF is enabled or not.
1089      *
1090      * Refer IEEE 802.11az-2022 spec, section 9.4.2.298 Ranging Parameters element.
1091      */
1092     @FlaggedApi(Flags.FLAG_SECURE_RANGING)
isSecureHeLtfEnabled()1093     public boolean isSecureHeLtfEnabled() {
1094         return mIsSecureHeLtfEnabled;
1095     }
1096 
1097     /**
1098      * Get Secure HE-LTF protocol version used.
1099      *
1100      * The secure HE-LTF negotiation supports negotiation of the secure HE-LTF protocol version
1101      * which allows a responder and an initiator to negotiate the highest mutually supported
1102      * secure HE-LTF protocol version.
1103      *
1104      * Refer IEEE 802.11az-2022 spec, section 9.4.2.298 Ranging Parameters element.
1105      */
1106     @FlaggedApi(Flags.FLAG_SECURE_RANGING)
1107     @IntRange(from = 0, to = 7)
getSecureHeLtfProtocolVersion()1108     public int getSecureHeLtfProtocolVersion() {
1109         return mSecureHeLtfProtocolVersion;
1110     }
1111 
1112     /**
1113      * Get PASN comeback cookie. PASN authentication allows an AP to indicate the deferral time
1114      * and optionally a Cookie. See {@link #getPasnComebackAfterMillis()}
1115      * <p>
1116      * When an AP receives a large volume of initial PASN Authentication frames, it can use
1117      * the comeback after field in the PASN Parameters element to indicate a deferral time
1118      * and optionally provide a comeback cookie which is an opaque sequence of octets. Upon
1119      * receiving this response, the ranging initiator (STA) must wait for the specified time
1120      * before retrying secure authentication, presenting the received cookie to the AP.
1121      **/
1122     @FlaggedApi(Flags.FLAG_SECURE_RANGING)
1123     @Nullable
getPasnComebackCookie()1124     public byte[] getPasnComebackCookie() {
1125         return mPasnComebackCookie;
1126     }
1127 
1128     /**
1129      * Get Comeback after time in milliseconds. See {@link #getPasnComebackCookie()}. A value 0
1130      * indicates the ranging request operation can be tried immediately with the cookie.
1131      */
1132     @FlaggedApi(Flags.FLAG_SECURE_RANGING)
getPasnComebackAfterMillis()1133     public long getPasnComebackAfterMillis() {
1134         return mPasnComebackAfterMillis;
1135     }
1136 
1137     @Override
describeContents()1138     public int describeContents() {
1139         return 0;
1140     }
1141 
1142     @Override
writeToParcel(Parcel dest, int flags)1143     public void writeToParcel(Parcel dest, int flags) {
1144         dest.writeInt(mStatus);
1145         if (mMac == null) {
1146             dest.writeBoolean(false);
1147         } else {
1148             dest.writeBoolean(true);
1149             mMac.writeToParcel(dest, flags);
1150         }
1151         if (mPeerHandle == null) {
1152             dest.writeBoolean(false);
1153         } else {
1154             dest.writeBoolean(true);
1155             dest.writeInt(mPeerHandle.peerId);
1156         }
1157         dest.writeInt(mDistanceMm);
1158         dest.writeInt(mDistanceStdDevMm);
1159         dest.writeInt(mRssi);
1160         dest.writeInt(mNumAttemptedMeasurements);
1161         dest.writeInt(mNumSuccessfulMeasurements);
1162         dest.writeByteArray(mLci);
1163         dest.writeByteArray(mLcr);
1164         dest.writeParcelable(mResponderLocation, flags);
1165         dest.writeLong(mTimestamp);
1166         dest.writeBoolean(mIs80211mcMeasurement);
1167         dest.writeInt(mFrequencyMHz);
1168         dest.writeInt(mPacketBw);
1169         dest.writeBoolean(mIs80211azNtbMeasurement);
1170         dest.writeLong(mNtbMinMeasurementTime);
1171         dest.writeLong(mNtbMaxMeasurementTime);
1172         dest.writeInt(mI2rTxLtfRepetitions);
1173         dest.writeInt(mR2iTxLtfRepetitions);
1174         dest.writeInt(mNumTxSpatialStreams);
1175         dest.writeInt(mNumRxSpatialStreams);
1176         if (SdkLevel.isAtLeastV()) {
1177             dest.writeList(mVendorData);
1178         }
1179         dest.writeBoolean(mIsRangingAuthenticated);
1180         dest.writeBoolean(mIsRangingFrameProtected);
1181         dest.writeBoolean(mIsSecureHeLtfEnabled);
1182         dest.writeLong(mPasnComebackAfterMillis);
1183         dest.writeByteArray(mPasnComebackCookie);
1184         dest.writeInt(mSecureHeLtfProtocolVersion);
1185     }
1186 
1187     public static final @android.annotation.NonNull Creator<RangingResult> CREATOR =
1188             new Creator<RangingResult>() {
1189                 @Override
1190                 public RangingResult[] newArray(int size) {
1191                     return new RangingResult[size];
1192                 }
1193 
1194                 @Override
1195                 public RangingResult createFromParcel(Parcel in) {
1196                     RangingResult.Builder builder = new Builder()
1197                             .setStatus(in.readInt())
1198                             .setMacAddress(
1199                                     in.readBoolean() ? MacAddress.CREATOR.createFromParcel(in)
1200                                             : null)
1201                             .setPeerHandle(in.readBoolean() ? new PeerHandle(in.readInt()) : null)
1202                             .setDistanceMm(in.readInt())
1203                             .setDistanceStdDevMm(in.readInt())
1204                             .setRssi(in.readInt())
1205                             .setNumAttemptedMeasurements(in.readInt())
1206                             .setNumSuccessfulMeasurements(in.readInt())
1207                             .setLci(in.createByteArray())
1208                             .setLcr(in.createByteArray())
1209                             .setUnverifiedResponderLocation(
1210                                     in.readParcelable(this.getClass().getClassLoader()))
1211                             .setRangingTimestampMillis(in.readLong())
1212                             .set80211mcMeasurement(in.readBoolean())
1213                             .setMeasurementChannelFrequencyMHz(in.readInt())
1214                             .setMeasurementBandwidth(in.readInt())
1215                             .set80211azNtbMeasurement(in.readBoolean())
1216                             .setMinTimeBetweenNtbMeasurementsMicros(in.readLong())
1217                             .setMaxTimeBetweenNtbMeasurementsMicros(in.readLong())
1218                             .set80211azInitiatorTxLtfRepetitionsCount(in.readInt())
1219                             .set80211azResponderTxLtfRepetitionsCount(in.readInt())
1220                             .set80211azNumberOfTxSpatialStreams(in.readInt())
1221                             .set80211azNumberOfRxSpatialStreams(in.readInt());
1222                     if (SdkLevel.isAtLeastV()) {
1223                         builder.setVendorData(ParcelUtil.readOuiKeyedDataList(in));
1224                     }
1225                     builder.setRangingAuthenticated(in.readBoolean())
1226                             .setRangingFrameProtected(in.readBoolean())
1227                             .setSecureHeLtfEnabled(in.readBoolean())
1228                             .setPasnComebackAfterMillis(in.readLong())
1229                             .setPasnComebackCookie(in.createByteArray())
1230                             .setSecureHeLtfProtocolVersion(in.readInt());
1231                     return builder.build();
1232                 }
1233             };
1234 
1235     /** @hide */
1236     @Override
toString()1237     public String toString() {
1238         return new StringBuilder("RangingResult: [status=").append(mStatus)
1239                 .append(", mac=").append(mMac)
1240                 .append(", peerHandle=").append(
1241                         mPeerHandle == null ? "<null>" : mPeerHandle.peerId)
1242                 .append(", distanceMm=").append(mDistanceMm)
1243                 .append(", distanceStdDevMm=").append(mDistanceStdDevMm)
1244                 .append(", rssi=").append(mRssi)
1245                 .append(", numAttemptedMeasurements=").append(mNumAttemptedMeasurements)
1246                 .append(", numSuccessfulMeasurements=").append(mNumSuccessfulMeasurements)
1247                 .append(", lci=").append(Arrays.toString(mLci))
1248                 .append(", lcr=").append(Arrays.toString(mLcr))
1249                 .append(", responderLocation=").append(mResponderLocation)
1250                 .append(", timestamp=").append(mTimestamp).append(", is80211mcMeasurement=")
1251                 .append(mIs80211mcMeasurement)
1252                 .append(", frequencyMHz=").append(mFrequencyMHz)
1253                 .append(", packetBw=").append(mPacketBw)
1254                 .append(", is80211azNtbMeasurement=").append(mIs80211azNtbMeasurement)
1255                 .append(", ntbMinMeasurementTimeMicros=").append(mNtbMinMeasurementTime)
1256                 .append(", ntbMaxMeasurementTimeMicros=").append(mNtbMaxMeasurementTime)
1257                 .append(", i2rTxLtfRepetitions=").append(mI2rTxLtfRepetitions)
1258                 .append(", r2iTxLtfRepetitions=").append(mR2iTxLtfRepetitions)
1259                 .append(", numTxSpatialStreams=").append(mNumTxSpatialStreams)
1260                 .append(", numRxSpatialStreams=").append(mNumRxSpatialStreams)
1261                 .append(", vendorData=").append(mVendorData)
1262                 .append(", isRangingAuthenticated=").append(mIsRangingAuthenticated)
1263                 .append(", isRangingFrameProtected=").append(mIsRangingFrameProtected)
1264                 .append(", isSecureHeLtfEnabled=").append(mIsSecureHeLtfEnabled)
1265                 .append(", pasnComebackCookie=").append(Arrays.toString(mPasnComebackCookie))
1266                 .append(", pasnComebackAfterMillis=").append(mPasnComebackAfterMillis)
1267                 .append("]").toString();
1268     }
1269 
1270     @Override
equals(Object o)1271     public boolean equals(Object o) {
1272         if (this == o) {
1273             return true;
1274         }
1275 
1276         if (!(o instanceof RangingResult)) {
1277             return false;
1278         }
1279 
1280         RangingResult lhs = (RangingResult) o;
1281 
1282         return mStatus == lhs.mStatus && Objects.equals(mMac, lhs.mMac) && Objects.equals(
1283                 mPeerHandle, lhs.mPeerHandle) && mDistanceMm == lhs.mDistanceMm
1284                 && mDistanceStdDevMm == lhs.mDistanceStdDevMm && mRssi == lhs.mRssi
1285                 && mNumAttemptedMeasurements == lhs.mNumAttemptedMeasurements
1286                 && mNumSuccessfulMeasurements == lhs.mNumSuccessfulMeasurements
1287                 && Arrays.equals(mLci, lhs.mLci) && Arrays.equals(mLcr, lhs.mLcr)
1288                 && mTimestamp == lhs.mTimestamp
1289                 && mIs80211mcMeasurement == lhs.mIs80211mcMeasurement
1290                 && Objects.equals(mResponderLocation, lhs.mResponderLocation)
1291                 && mFrequencyMHz == lhs.mFrequencyMHz
1292                 && mPacketBw == lhs.mPacketBw
1293                 && mIs80211azNtbMeasurement == lhs.mIs80211azNtbMeasurement
1294                 && mNtbMinMeasurementTime == lhs.mNtbMinMeasurementTime
1295                 && mNtbMaxMeasurementTime == lhs.mNtbMaxMeasurementTime
1296                 && mI2rTxLtfRepetitions == lhs.mI2rTxLtfRepetitions
1297                 && mR2iTxLtfRepetitions == lhs.mR2iTxLtfRepetitions
1298                 && mNumTxSpatialStreams == lhs.mNumTxSpatialStreams
1299                 && mNumRxSpatialStreams == lhs.mNumRxSpatialStreams
1300                 && Objects.equals(mVendorData, lhs.mVendorData)
1301                 && mIsRangingAuthenticated == lhs.mIsRangingAuthenticated
1302                 && mIsRangingFrameProtected == lhs.mIsRangingFrameProtected
1303                 && mIsSecureHeLtfEnabled == lhs.isSecureHeLtfEnabled()
1304                 && mPasnComebackAfterMillis == lhs.mPasnComebackAfterMillis
1305                 && Arrays.equals(mPasnComebackCookie, lhs.mPasnComebackCookie);
1306 
1307     }
1308 
1309     @Override
hashCode()1310     public int hashCode() {
1311         return Objects.hash(mStatus, mMac, mPeerHandle, mDistanceMm, mDistanceStdDevMm, mRssi,
1312                 mNumAttemptedMeasurements, mNumSuccessfulMeasurements, Arrays.hashCode(mLci),
1313                 Arrays.hashCode(mLcr), mResponderLocation, mTimestamp, mIs80211mcMeasurement,
1314                 mFrequencyMHz, mPacketBw, mIs80211azNtbMeasurement, mNtbMinMeasurementTime,
1315                 mNtbMaxMeasurementTime, mI2rTxLtfRepetitions, mR2iTxLtfRepetitions,
1316                 mNumTxSpatialStreams, mR2iTxLtfRepetitions, mVendorData, mIsRangingAuthenticated,
1317                 mIsRangingFrameProtected, mIsSecureHeLtfEnabled, mPasnComebackAfterMillis,
1318                 Arrays.hashCode(mPasnComebackCookie));
1319     }
1320 }
1321