/*
 * 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.NonNull;
import android.annotation.SystemApi;
import android.net.MacAddress;
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.Handler;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;

Defines the ranging request to other devices. The ranging request is built using Builder. A ranging request is executed using WifiRttManager.startRanging(RangingRequest, Executor, RangingResultCallback).

The ranging request is a batch request - specifying a set of devices (specified using Builder.addAccessPoint(ScanResult) and Builder.addAccessPoints(List<ScanResult>)).

/** * 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)}. * <p> * 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;
Returns the maximum number of peers to range which can be specified in a single RangingRequest. The limit applies no matter how the peers are added to the request, e.g. through Builder.addAccessPoint(ScanResult) or Builder.addAccessPoints(List<ScanResult>).
Returns:Maximum number of peers.
/** * 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; }
@hide
/** @hide */
public final List<ResponderConfig> mRttPeers;
@hide
/** @hide */
private RangingRequest(List<ResponderConfig> rttPeers) { mRttPeers = rttPeers; } @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeList(mRttPeers); } public static final Creator<RangingRequest> CREATOR = new Creator<RangingRequest>() { @Override public RangingRequest[] newArray(int size) { return new RangingRequest[size]; } @Override public RangingRequest createFromParcel(Parcel in) { return new RangingRequest(in.readArrayList(null)); } };
@hide
/** @hide */
@Override public String toString() { StringJoiner sj = new StringJoiner(", ", "RangingRequest: mRttPeers=[", "]"); for (ResponderConfig rc : mRttPeers) { sj.add(rc.toString()); } return sj.toString(); }
@hide
/** @hide */
public void enforceValidity(boolean awareSupported) { if (mRttPeers.size() > MAX_PEERS) { throw new IllegalArgumentException( "Ranging to too many peers requested. Use getMaxPeers() API to get limit."); } for (ResponderConfig peer: mRttPeers) { if (!peer.isValid(awareSupported)) { throw new IllegalArgumentException("Invalid Responder specification"); } } }
Builder class used to construct RangingRequest objects.
/** * Builder class used to construct {@link RangingRequest} objects. */
public static final class Builder { private List<ResponderConfig> mRttPeers = new ArrayList<>();
Add the device specified by the 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 RangingRequest.getMaxPeers().

Ranging may not be supported if the Access Point does not support IEEE 802.11mc. Use ScanResult.is80211mcResponder() to verify the Access Point's capabilities. If not supported the result status will be RangingResult.STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC.

Params:
  • apInfo – Information of an Access Point (AP) obtained in a Scan Result.
Returns:The builder to facilitate chaining builder.setXXX(..).setXXX(..).
/** * 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()}. * <p> * Ranging may not be supported if the Access Point does not support IEEE 802.11mc. Use * {@link ScanResult#is80211mcResponder()} to verify the Access Point's capabilities. If * not supported the result status will be * {@link RangingResult#STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC}. * * @param apInfo Information of an Access Point (AP) obtained in a Scan Result. * @return The builder to facilitate chaining * {@code builder.setXXX(..).setXXX(..)}. */
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 ScanResults 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 RangingRequest.getMaxPeers().

Ranging may not be supported if the Access Point does not support IEEE 802.11mc. Use ScanResult.is80211mcResponder() to verify the Access Point's capabilities. If not supported the result status will be RangingResult.STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC.

Params:
  • apInfos – Information of an Access Points (APs) obtained in a Scan Result.
Returns:The builder to facilitate chaining builder.setXXX(..).setXXX(..).
/** * 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()}. * <p> * Ranging may not be supported if the Access Point does not support IEEE 802.11mc. Use * {@link ScanResult#is80211mcResponder()} to verify the Access Point's capabilities. If * not supported the result status will be * {@link RangingResult#STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC}. * * @param apInfos Information of an Access Points (APs) obtained in a Scan Result. * @return The builder to facilitate chaining * {@code builder.setXXX(..).setXXX(..)}. */
public Builder addAccessPoints(@NonNull List<ScanResult> apInfos) { if (apInfos == null) { throw new IllegalArgumentException("Null list of ScanResults!"); } for (ScanResult scanResult : apInfos) { addAccessPoint(scanResult); } return this; }
Add the device specified by the peerMacAddress to the list of devices with which to measure range.

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 IdentityChangedListener provided to WifiAwareManager.attach(AttachCallback, IdentityChangedListener, Handler).

Note: in order to use this API the device must support Wi-Fi Aware aware. The peer device which is being ranged to must be configured to publish a service (with any name) with:

  • Type PublishConfig.PUBLISH_TYPE_UNSOLICITED.
  • Ranging enabled Builder.setRangingEnabled(boolean).
  • Params:
    • peerMacAddress – The MAC address of the Wi-Fi Aware peer.
    Returns:The builder, to facilitate chaining builder.setXXX(..).setXXX(..).
    /** * Add the device specified by the {@code peerMacAddress} to the list of devices with * which to measure range. * <p> * 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)}. * <p> * 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: * <li>Type {@link android.net.wifi.aware.PublishConfig#PUBLISH_TYPE_UNSOLICITED}. * <li>Ranging enabled * {@link android.net.wifi.aware.PublishConfig.Builder#setRangingEnabled(boolean)}. * * @param peerMacAddress The MAC address of the Wi-Fi Aware peer. * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}. */
    public Builder addWifiAwarePeer(@NonNull MacAddress peerMacAddress) { if (peerMacAddress == null) { throw new IllegalArgumentException("Null peer MAC address"); } return addResponder( ResponderConfig.fromWifiAwarePeerMacAddressWithDefaults(peerMacAddress)); }
    Add a device specified by a PeerHandle to the list of devices with which to measure range.

    The PeerHandle may be obtained as part of the Wi-Fi Aware discovery process. E.g. using DiscoverySessionCallback.onServiceDiscovered(PeerHandle, byte[], List<byte[]>).

    Note: in order to use this API the device must support Wi-Fi Aware aware. The peer device which is being ranged to must be configured to publish a service (with any name) with:

  • Type PublishConfig.PUBLISH_TYPE_UNSOLICITED.
  • Ranging enabled Builder.setRangingEnabled(boolean).
  • Params:
    • peerHandle – The peer handler of the peer Wi-Fi Aware device.
    Returns:The builder, to facilitate chaining builder.setXXX(..).setXXX(..).
    /** * Add a device specified by a {@link PeerHandle} to the list of devices with which to * measure range. * <p> * The {@link PeerHandle} may be obtained as part of the Wi-Fi Aware discovery process. E.g. * using {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], List)}. * <p> * 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: * <li>Type {@link android.net.wifi.aware.PublishConfig#PUBLISH_TYPE_UNSOLICITED}. * <li>Ranging enabled * {@link android.net.wifi.aware.PublishConfig.Builder#setRangingEnabled(boolean)}. * * @param peerHandle The peer handler of the peer Wi-Fi Aware device. * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}. */
    public Builder addWifiAwarePeer(@NonNull PeerHandle peerHandle) { if (peerHandle == null) { throw new IllegalArgumentException("Null peer handler (identifier)"); } return addResponder(ResponderConfig.fromWifiAwarePeerHandleWithDefaults(peerHandle)); }
    Add the Responder device specified by the ResponderConfig to the list of devices with which to measure range. The total number of peers added to the request cannot exceed the limit specified by RangingRequest.getMaxPeers().
    Params:
    • responder – Information on the RTT Responder.
    Returns:The builder, to facilitate chaining builder.setXXX(..).setXXX(..).
    @hide
    /** * Add the Responder device specified by the {@link ResponderConfig} to the list of devices * with which to measure range. The total number of peers added to the request cannot exceed * the limit specified by {@link #getMaxPeers()}. * * @param responder Information on the RTT Responder. * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}. * * @hide */
    @SystemApi public Builder addResponder(@NonNull ResponderConfig responder) { if (responder == null) { throw new IllegalArgumentException("Null Responder!"); } mRttPeers.add(responder); return this; }
    Build RangingRequest given the current configurations made on the builder.
    /** * Build {@link RangingRequest} given the current configurations made on the * builder. */
    public RangingRequest build() { return new RangingRequest(mRttPeers); } } @Override public boolean equals(Object o) { if (this == o) { return true; } if (!(o instanceof RangingRequest)) { return false; } RangingRequest lhs = (RangingRequest) o; return mRttPeers.size() == lhs.mRttPeers.size() && mRttPeers.containsAll(lhs.mRttPeers); } @Override public int hashCode() { return mRttPeers.hashCode(); } }