• 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.NonNull;
20 import android.annotation.SystemApi;
21 import android.net.MacAddress;
22 import android.net.wifi.ScanResult;
23 import android.net.wifi.aware.AttachCallback;
24 import android.net.wifi.aware.DiscoverySessionCallback;
25 import android.net.wifi.aware.IdentityChangedListener;
26 import android.net.wifi.aware.PeerHandle;
27 import android.net.wifi.aware.WifiAwareManager;
28 import android.os.Handler;
29 import android.os.Parcel;
30 import android.os.Parcelable;
31 
32 import java.util.ArrayList;
33 import java.util.List;
34 import java.util.StringJoiner;
35 
36 /**
37  * Defines the ranging request to other devices. The ranging request is built using
38  * {@link RangingRequest.Builder}.
39  * A ranging request is executed using
40  * {@link WifiRttManager#startRanging(RangingRequest, java.util.concurrent.Executor, RangingResultCallback)}.
41  * <p>
42  * The ranging request is a batch request - specifying a set of devices (specified using
43  * {@link RangingRequest.Builder#addAccessPoint(ScanResult)} and
44  * {@link RangingRequest.Builder#addAccessPoints(List)}).
45  */
46 public final class RangingRequest implements Parcelable {
47     private static final int MAX_PEERS = 10;
48 
49     /**
50      * Returns the maximum number of peers to range which can be specified in a single {@code
51      * RangingRequest}. The limit applies no matter how the peers are added to the request, e.g.
52      * through {@link RangingRequest.Builder#addAccessPoint(ScanResult)} or
53      * {@link RangingRequest.Builder#addAccessPoints(List)}.
54      *
55      * @return Maximum number of peers.
56      */
getMaxPeers()57     public static int getMaxPeers() {
58         return MAX_PEERS;
59     }
60 
61     /** @hide */
62     public final List<ResponderConfig> mRttPeers;
63 
64     /** @hide */
RangingRequest(List<ResponderConfig> rttPeers)65     private RangingRequest(List<ResponderConfig> rttPeers) {
66         mRttPeers = rttPeers;
67     }
68 
69     @Override
describeContents()70     public int describeContents() {
71         return 0;
72     }
73 
74     @Override
writeToParcel(Parcel dest, int flags)75     public void writeToParcel(Parcel dest, int flags) {
76         dest.writeList(mRttPeers);
77     }
78 
79     public static final @android.annotation.NonNull Creator<RangingRequest> CREATOR = new Creator<RangingRequest>() {
80         @Override
81         public RangingRequest[] newArray(int size) {
82             return new RangingRequest[size];
83         }
84 
85         @Override
86         public RangingRequest createFromParcel(Parcel in) {
87             return new RangingRequest(in.readArrayList(null));
88         }
89     };
90 
91     /** @hide */
92     @Override
toString()93     public String toString() {
94         StringJoiner sj = new StringJoiner(", ", "RangingRequest: mRttPeers=[", "]");
95         for (ResponderConfig rc : mRttPeers) {
96             sj.add(rc.toString());
97         }
98         return sj.toString();
99     }
100 
101     /** @hide */
enforceValidity(boolean awareSupported)102     public void enforceValidity(boolean awareSupported) {
103         if (mRttPeers.size() > MAX_PEERS) {
104             throw new IllegalArgumentException(
105                     "Ranging to too many peers requested. Use getMaxPeers() API to get limit.");
106         }
107 
108         for (ResponderConfig peer: mRttPeers) {
109             if (!peer.isValid(awareSupported)) {
110                 throw new IllegalArgumentException("Invalid Responder specification");
111             }
112         }
113     }
114 
115     /**
116      * Builder class used to construct {@link RangingRequest} objects.
117      */
118     public static final class Builder {
119         private List<ResponderConfig> mRttPeers = new ArrayList<>();
120 
121         /**
122          * Add the device specified by the {@link ScanResult} to the list of devices with
123          * which to measure range. The total number of peers added to a request cannot exceed the
124          * limit specified by {@link #getMaxPeers()}.
125          * <p>
126          * Ranging may not be supported if the Access Point does not support IEEE 802.11mc. Use
127          * {@link ScanResult#is80211mcResponder()} to verify the Access Point's capabilities. If
128          * not supported the result status will be
129          * {@link RangingResult#STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC}.
130          *
131          * @param apInfo Information of an Access Point (AP) obtained in a Scan Result.
132          * @return The builder to facilitate chaining
133          *         {@code builder.setXXX(..).setXXX(..)}.
134          */
addAccessPoint(@onNull ScanResult apInfo)135         public Builder addAccessPoint(@NonNull ScanResult apInfo) {
136             if (apInfo == null) {
137                 throw new IllegalArgumentException("Null ScanResult!");
138             }
139             return addResponder(ResponderConfig.fromScanResult(apInfo));
140         }
141 
142         /**
143          * Add the devices specified by the {@link ScanResult}s to the list of devices with
144          * which to measure range. The total number of peers added to a request cannot exceed the
145          * limit specified by {@link #getMaxPeers()}.
146          * <p>
147          * Ranging may not be supported if the Access Point does not support IEEE 802.11mc. Use
148          * {@link ScanResult#is80211mcResponder()} to verify the Access Point's capabilities. If
149          * not supported the result status will be
150          * {@link RangingResult#STATUS_RESPONDER_DOES_NOT_SUPPORT_IEEE80211MC}.
151          *
152          * @param apInfos Information of an Access Points (APs) obtained in a Scan Result.
153          * @return The builder to facilitate chaining
154          *         {@code builder.setXXX(..).setXXX(..)}.
155          */
addAccessPoints(@onNull List<ScanResult> apInfos)156         public Builder addAccessPoints(@NonNull List<ScanResult> apInfos) {
157             if (apInfos == null) {
158                 throw new IllegalArgumentException("Null list of ScanResults!");
159             }
160             for (ScanResult scanResult : apInfos) {
161                 addAccessPoint(scanResult);
162             }
163             return this;
164         }
165 
166         /**
167          * Add the device specified by the {@code peerMacAddress} to the list of devices with
168          * which to measure range.
169          * <p>
170          * The MAC address may be obtained out-of-band from a peer Wi-Fi Aware device. A Wi-Fi
171          * Aware device may obtain its MAC address using the {@link IdentityChangedListener}
172          * provided to
173          * {@link WifiAwareManager#attach(AttachCallback, IdentityChangedListener, Handler)}.
174          * <p>
175          * Note: in order to use this API the device must support Wi-Fi Aware
176          * {@link android.net.wifi.aware}. The peer device which is being ranged to must be
177          * configured to publish a service (with any name) with:
178          * <li>Type {@link android.net.wifi.aware.PublishConfig#PUBLISH_TYPE_UNSOLICITED}.
179          * <li>Ranging enabled
180          * {@link android.net.wifi.aware.PublishConfig.Builder#setRangingEnabled(boolean)}.
181          *
182          * @param peerMacAddress The MAC address of the Wi-Fi Aware peer.
183          * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
184          */
addWifiAwarePeer(@onNull MacAddress peerMacAddress)185         public Builder addWifiAwarePeer(@NonNull MacAddress peerMacAddress) {
186             if (peerMacAddress == null) {
187                 throw new IllegalArgumentException("Null peer MAC address");
188             }
189             return addResponder(
190                     ResponderConfig.fromWifiAwarePeerMacAddressWithDefaults(peerMacAddress));
191         }
192 
193         /**
194          * Add a device specified by a {@link PeerHandle} to the list of devices with which to
195          * measure range.
196          * <p>
197          * The {@link PeerHandle} may be obtained as part of the Wi-Fi Aware discovery process. E.g.
198          * using {@link DiscoverySessionCallback#onServiceDiscovered(PeerHandle, byte[], List)}.
199          * <p>
200          * Note: in order to use this API the device must support Wi-Fi Aware
201          * {@link android.net.wifi.aware}. The peer device which is being ranged to must be
202          * configured to publish a service (with any name) with:
203          * <li>Type {@link android.net.wifi.aware.PublishConfig#PUBLISH_TYPE_UNSOLICITED}.
204          * <li>Ranging enabled
205          * {@link android.net.wifi.aware.PublishConfig.Builder#setRangingEnabled(boolean)}.
206          *
207          * @param peerHandle The peer handler of the peer Wi-Fi Aware device.
208          * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
209          */
addWifiAwarePeer(@onNull PeerHandle peerHandle)210         public Builder addWifiAwarePeer(@NonNull PeerHandle peerHandle) {
211             if (peerHandle == null) {
212                 throw new IllegalArgumentException("Null peer handler (identifier)");
213             }
214 
215             return addResponder(ResponderConfig.fromWifiAwarePeerHandleWithDefaults(peerHandle));
216         }
217 
218         /**
219          * Add the Responder device specified by the {@link ResponderConfig} to the list of devices
220          * with which to measure range. The total number of peers added to the request cannot exceed
221          * the limit specified by {@link #getMaxPeers()}.
222          *
223          * @param responder Information on the RTT Responder.
224          * @return The builder, to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
225          *
226          * @hide
227          */
228         @SystemApi
addResponder(@onNull ResponderConfig responder)229         public Builder addResponder(@NonNull ResponderConfig responder) {
230             if (responder == null) {
231                 throw new IllegalArgumentException("Null Responder!");
232             }
233 
234             mRttPeers.add(responder);
235             return this;
236         }
237 
238         /**
239          * Build {@link RangingRequest} given the current configurations made on the
240          * builder.
241          */
build()242         public RangingRequest build() {
243             return new RangingRequest(mRttPeers);
244         }
245     }
246 
247     @Override
equals(Object o)248     public boolean equals(Object o) {
249         if (this == o) {
250             return true;
251         }
252 
253         if (!(o instanceof RangingRequest)) {
254             return false;
255         }
256 
257         RangingRequest lhs = (RangingRequest) o;
258 
259         return mRttPeers.size() == lhs.mRttPeers.size() && mRttPeers.containsAll(lhs.mRttPeers);
260     }
261 
262     @Override
hashCode()263     public int hashCode() {
264         return mRttPeers.hashCode();
265     }
266 }
267