/* * 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.net.wifi.rtt; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.MacAddress; import android.net.wifi.OuiKeyedData; import android.net.wifi.ParcelUtil; import android.net.wifi.ScanResult; import android.net.wifi.aware.AttachCallback; import android.net.wifi.aware.DiscoverySessionCallback; import android.net.wifi.aware.IdentityChangedListener; import android.net.wifi.aware.PeerHandle; import android.net.wifi.aware.WifiAwareManager; import android.os.Build; import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; import androidx.annotation.RequiresApi; import com.android.modules.utils.build.SdkLevel; import com.android.wifi.flags.Flags; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.StringJoiner; /** * Defines the ranging request to other devices. The ranging request is built using * {@link RangingRequest.Builder}. * A ranging request is executed using * {@link WifiRttManager#startRanging(RangingRequest, java.util.concurrent.Executor, RangingResultCallback)}. *
* The ranging request is a batch request - specifying a set of devices (specified using
* {@link RangingRequest.Builder#addAccessPoint(ScanResult)} and
* {@link RangingRequest.Builder#addAccessPoints(List)}).
*/
public final class RangingRequest implements Parcelable {
private static final int MAX_PEERS = 10;
private static final int DEFAULT_RTT_BURST_SIZE = 8;
private static final int MIN_RTT_BURST_SIZE = 2;
private static final int MAX_RTT_BURST_SIZE = 31;
/**
* Returns the maximum number of peers to range which can be specified in a single {@code
* RangingRequest}. The limit applies no matter how the peers are added to the request, e.g.
* through {@link RangingRequest.Builder#addAccessPoint(ScanResult)} or
* {@link RangingRequest.Builder#addAccessPoints(List)}.
*
* @return Maximum number of peers.
*/
public static int getMaxPeers() {
return MAX_PEERS;
}
/**
* Returns the default RTT burst size used to determine the average range.
*
* @return the RTT burst size used by default
*/
public static int getDefaultRttBurstSize() {
return DEFAULT_RTT_BURST_SIZE;
}
/**
* Returns the minimum RTT burst size that can be used to determine a average range.
*
* @return the minimum RTT burst size that can be used
*/
public static int getMinRttBurstSize() {
return MIN_RTT_BURST_SIZE;
}
/**
* Returns the minimum RTT burst size that can be used to determine a average range.
*
* @return the maximum RTT burst size that can be used
*/
public static int getMaxRttBurstSize() {
return MAX_RTT_BURST_SIZE;
}
/** @hide */
public final List
* If not set, the default RTT burst size given by
* {@link #getDefaultRttBurstSize()} is used to determine the default value.
* If set, the value must be in the range {@link #getMinRttBurstSize()} and
* {@link #getMaxRttBurstSize()} inclusively, or a
* {@link java.lang.IllegalArgumentException} will be thrown.
*
* Note: RTT burst size is applicable to IEEE 802.11mc, and for one special case it is
* also applicable to IEEE 802.11az to generate multiple NTB ranging requests per
* measurement. It is applicable for IEEE 802.11az based ranging requests when MIMO is
* not available, with the transmit and receive spatial streams between the initiator and
* responder station is equal to 1. See
* {@link RangingResult#get80211azNumberOfRxSpatialStreams()} and
* {@link RangingResult#get80211azNumberOfTxSpatialStreams()}.
*
* @param rttBurstSize The number of FTM packets used to estimate a range.
* @return The builder to facilitate chaining
* {@code builder.setXXX(..).setXXX(..)}.
*/
@NonNull
public Builder setRttBurstSize(int rttBurstSize) {
if (rttBurstSize < MIN_RTT_BURST_SIZE || rttBurstSize > MAX_RTT_BURST_SIZE) {
throw new IllegalArgumentException("RTT burst size out of range.");
}
mRttBurstSize = rttBurstSize;
return this;
}
/**
* Add the device specified by the {@link ScanResult} to the list of devices with
* which to measure range. The total number of peers added to a request cannot exceed the
* limit specified by {@link #getMaxPeers()}.
*
* Two-sided Ranging will be performed if the local device and the AP support IEEE 802.11az
* (non-trigger based ranging) or IEEE 802.11mc. AP capability is determined by the method
* {@link ScanResult#is80211azNtbResponder()} or {@link ScanResult#is80211mcResponder()}.
*
* If both 11az and 11mc are supported by the local device and the AP, 11az non-trigger
* based ranging will be performed.
*
* If two-sided ranging is not supported, one-sided RTT will be performed with no
* correction for the AP packet turnaround time.
*
* @param apInfo Information about an Access Point (AP) obtained in a Scan Result.
* @return The builder to facilitate chaining
* {@code builder.setXXX(..).setXXX(..)}.
*/
@NonNull
public Builder addAccessPoint(@NonNull ScanResult apInfo) {
if (apInfo == null) {
throw new IllegalArgumentException("Null ScanResult!");
}
return addResponder(ResponderConfig.fromScanResult(apInfo));
}
/**
* Add the devices specified by the {@link ScanResult}s to the list of devices with
* which to measure range. The total number of peers added to a request cannot exceed the
* limit specified by {@link #getMaxPeers()}.
*
* Two-sided Ranging will be performed if the local device and the AP support IEEE 802.11az
* (non-trigger based ranging) or IEEE 802.11mc. AP capability is determined by the method
* {@link ScanResult#is80211azNtbResponder()} or {@link ScanResult#is80211mcResponder()}.
*
* If both 11az and 11mc are supported by the local device and the AP, 11az non-trigger
* based ranging will be performed.
*
* If two-sided ranging is not supported, one-sided RTT will be performed with no
* correction for the AP packet turnaround time.
*
* @param apInfos Information about Access Points (APs) obtained in a Scan Result.
* @return The builder to facilitate chaining
* {@code builder.setXXX(..).setXXX(..)}.
*/
@NonNull
public Builder addAccessPoints(@NonNull List
* Two-sided Ranging will be performed if the local device and the AP support IEEE 802.11az
* (non-trigger based ranging) or IEEE 802.11mc. AP capability is determined by the method
* {@link ScanResult#is80211azNtbResponder()} or {@link ScanResult#is80211mcResponder()}.
*
* If both 11az and 11mc are supported by the local device and the AP, 11az non-trigger
* based ranging will be performed.
*
* If two-sided ranging is not supported, one-sided RTT will be performed with no
* correction for the AP packet turnaround time.
*
* @param responder Information on the RTT Responder.
* @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
*/
@NonNull
public Builder addResponder(@NonNull ResponderConfig responder) {
if (responder == null) {
throw new IllegalArgumentException("Null Responder!");
}
mRttPeers.add(responder);
return this;
}
/**
* Add the devices specified by the {@link ResponderConfig}s to the list of devices with
* which to measure range. The total number of peers added to a request cannot exceed the
* limit specified by {@link #getMaxPeers()}.
*
* Two-sided Ranging will be performed if the local device and the AP support IEEE 802.11az
* (non-trigger based ranging) or IEEE 802.11mc. AP capability is determined by the method
* {@link ScanResult#is80211azNtbResponder()} or {@link ScanResult#is80211mcResponder()}.
*
* If both 11az and 11mc are supported by the local device and the AP, 11az non-trigger
* based ranging will be performed.
*
* If two-sided ranging is not supported, one-sided RTT will be performed with no
* correction for the AP packet turnaround time.
*
* @param responders Information representing the set of access points to be ranged
* @return The builder to facilitate chaining
* {@code builder.setXXX(..).setXXX(..)}.
*/
@NonNull
public Builder addResponders(@NonNull List
* Accurate ranging cannot be supported if the Access Point does not support IEEE 802.11mc
* and IEEE 802.11az, and instead an alternate protocol called one-sided RTT will be used
* with lower accuracy. Use {@link ScanResult#is80211mcResponder()} to verify the Access
* Point(s) are not 802.11mc capable. Use {@link ScanResult#is80211azNtbResponder()} ()} to
* verify the Access Point)s) are not 802.11az capable.
*
* One-sided RTT does not subtract the RTT turnaround time at the Access Point, which can
* add hundreds of meters to the estimate. With experimentation, it is possible to use this
* information to make a statistical estimate of the range by taking multiple measurements
* to several Access Points and normalizing the result. For some applications this can be
* used to improve range estimates based on Receive Signal Strength Indication (RSSI), but
* will not be as accurate as IEEE 802.11mc (two-sided RTT).
*
* Note: one-sided RTT should only be used if you are very familiar with statistical
* estimation techniques.
*
* @param apInfo Information about an Access Point (AP) obtained in a Scan Result
* @return The builder to facilitate chaining
* {@code builder.setXXX(..).setXXX(..)}.
*/
@NonNull
public Builder addNon80211mcCapableAccessPoint(@NonNull ScanResult apInfo) {
if (apInfo == null) {
throw new IllegalArgumentException("Null ScanResult!");
}
if (apInfo.is80211mcResponder() || apInfo.is80211azNtbResponder()) {
throw new IllegalArgumentException(
"AP supports the 802.11mc or 8022.11az protocol.");
}
return addResponder(ResponderConfig.fromScanResult(apInfo));
}
/**
* Add the non-802.11mc and non-802.11az capable devices specified by the {@link ScanResult}
* to the list of devices with which to measure range. The total number of peers added to a
* request cannot exceed the limit specified by {@link #getMaxPeers()}.
*
* Accurate ranging cannot be supported if the Access Point does not support IEEE 802.11mc
* and IEEE 802.11az, and instead an alternate protocol called one-sided RTT will be used
* with lower accuracy. Use {@link ScanResult#is80211mcResponder()} to verify the Access
* Point(s) are not 802.11mc capable. Use {@link ScanResult#is80211azNtbResponder()} ()} to
* verify the Access Point(s) are not 802.11az capable.
*
* One-sided RTT does not subtract the RTT turnaround time at the Access Point, which can
* add hundreds of meters to the estimate. With experimentation, it is possible to use this
* information to make a statistical estimate of the range by taking multiple measurements
* to several Access Points and normalizing the result. For some applications this can be
* used to improve range estimates based on Receive Signal Strength Indication (RSSI), but
* will not be as accurate as IEEE 802.11mc (two-sided RTT).
*
* Note: one-sided RTT should only be used if you are very familiar with statistical
* estimation techniques.
*
* @param apInfos Information about Access Points (APs) obtained in a Scan Result.
* @return The builder to facilitate chaining
* {@code builder.setXXX(..).setXXX(..)}.
*/
@NonNull
public Builder addNon80211mcCapableAccessPoints(@NonNull List
* The MAC address may be obtained out-of-band from a peer Wi-Fi Aware device. A Wi-Fi
* Aware device may obtain its MAC address using the {@link IdentityChangedListener}
* provided to
* {@link WifiAwareManager#attach(AttachCallback, IdentityChangedListener, Handler)}.
*
* Note: in order to use this API the device must support Wi-Fi Aware
* {@link android.net.wifi.aware}. The peer device which is being ranged to must be
* configured to publish a service (with any name) with:
*
* The {@link PeerHandle} may be obtained as part of the Wi-Fi Aware discovery process. E.g.
* using {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], List)}.
*
* Note: in order to use this API the device must support Wi-Fi Aware
* {@link android.net.wifi.aware}. The requesting device can be either publisher or
* subscriber in a discovery session. For both requesting device and peer device ranging
* must be enabled on the discovery session:
*