• 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 static android.net.wifi.ScanResult.InformationElement.EID_EXTENSION_PRESENT;
20 import static android.net.wifi.ScanResult.InformationElement.EID_EXT_HE_CAPABILITIES;
21 import static android.net.wifi.ScanResult.InformationElement.EID_HT_CAPABILITIES;
22 import static android.net.wifi.ScanResult.InformationElement.EID_VHT_CAPABILITIES;
23 
24 import android.annotation.IntDef;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.annotation.SystemApi;
28 import android.net.MacAddress;
29 import android.net.wifi.ScanResult;
30 import android.net.wifi.aware.PeerHandle;
31 import android.os.Parcel;
32 import android.os.Parcelable;
33 import android.util.Log;
34 
35 import java.lang.annotation.Retention;
36 import java.lang.annotation.RetentionPolicy;
37 import java.util.Objects;
38 
39 /**
40  * Defines the configuration of an IEEE 802.11mc Responder. The Responder may be an Access Point
41  * (AP), a Wi-Fi Aware device, or a manually configured Responder.
42  * <p>
43  * A Responder configuration may be constructed from a {@link ScanResult} or manually (with the
44  * data obtained out-of-band from a peer).
45  *
46  * @hide
47  */
48 @SystemApi
49 public final class ResponderConfig implements Parcelable {
50     private static final String TAG = "ResponderConfig";
51     private static final int AWARE_BAND_2_DISCOVERY_CHANNEL = 2437;
52 
53     /** @hide */
54     @IntDef({RESPONDER_AP, RESPONDER_STA, RESPONDER_P2P_GO, RESPONDER_P2P_CLIENT, RESPONDER_AWARE})
55     @Retention(RetentionPolicy.SOURCE)
56     public @interface ResponderType {
57     }
58 
59     /**
60      * Responder is an AP.
61      */
62     public static final int RESPONDER_AP = 0;
63     /**
64      * Responder is a STA.
65      */
66     public static final int RESPONDER_STA = 1;
67     /**
68      * Responder is a Wi-Fi Direct Group Owner (GO).
69      */
70     public static final int RESPONDER_P2P_GO = 2;
71     /**
72      * Responder is a Wi-Fi Direct Group Client.
73      */
74     public static final int RESPONDER_P2P_CLIENT = 3;
75     /**
76      * Responder is a Wi-Fi Aware device.
77      */
78     public static final int RESPONDER_AWARE = 4;
79 
80 
81     /** @hide */
82     @IntDef({
83             CHANNEL_WIDTH_20MHZ, CHANNEL_WIDTH_40MHZ, CHANNEL_WIDTH_80MHZ, CHANNEL_WIDTH_160MHZ,
84             CHANNEL_WIDTH_80MHZ_PLUS_MHZ})
85     @Retention(RetentionPolicy.SOURCE)
86     public @interface ChannelWidth {
87     }
88 
89     /**
90      * Channel bandwidth is 20 MHZ
91      */
92     public static final int CHANNEL_WIDTH_20MHZ = 0;
93     /**
94      * Channel bandwidth is 40 MHZ
95      */
96     public static final int CHANNEL_WIDTH_40MHZ = 1;
97     /**
98      * Channel bandwidth is 80 MHZ
99      */
100     public static final int CHANNEL_WIDTH_80MHZ = 2;
101     /**
102      * Channel bandwidth is 160 MHZ
103      */
104     public static final int CHANNEL_WIDTH_160MHZ = 3;
105     /**
106      * Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ
107      */
108     public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4;
109 
110     /** @hide */
111     @IntDef({PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT, PREAMBLE_HE})
112     @Retention(RetentionPolicy.SOURCE)
113     public @interface PreambleType {
114     }
115 
116     /**
117      * Preamble type: Legacy.
118      */
119     public static final int PREAMBLE_LEGACY = 0;
120 
121     /**
122      * Preamble type: HT.
123      */
124     public static final int PREAMBLE_HT = 1;
125 
126     /**
127      * Preamble type: VHT.
128      */
129     public static final int PREAMBLE_VHT = 2;
130 
131     /**
132      * Preamble type: HE.
133      */
134     public static final int PREAMBLE_HE = 3;
135 
136     /**
137      * The MAC address of the Responder. Will be null if a Wi-Fi Aware peer identifier (the
138      * peerHandle field) ise used to identify the Responder.
139      */
140     public final MacAddress macAddress;
141 
142     /**
143      * The peer identifier of a Wi-Fi Aware Responder. Will be null if a MAC Address (the macAddress
144      * field) is used to identify the Responder.
145      */
146     public final PeerHandle peerHandle;
147 
148     /**
149      * The device type of the Responder.
150      */
151     public final int responderType;
152 
153     /**
154      * Indicates whether the Responder device supports IEEE 802.11mc.
155      */
156     public final boolean supports80211mc;
157 
158     /**
159      * Responder channel bandwidth, specified using {@link ChannelWidth}.
160      */
161     public final int channelWidth;
162 
163     /**
164      * The primary 20 MHz frequency (in MHz) of the channel of the Responder.
165      */
166     public final int frequency;
167 
168     /**
169      * Not used if the {@link #channelWidth} is 20 MHz. If the Responder uses 40, 80 or 160 MHz,
170      * this is the center frequency (in MHz), if the Responder uses 80 + 80 MHz, this is the
171      * center frequency of the first segment (in MHz).
172      */
173     public final int centerFreq0;
174 
175     /**
176      * Only used if the {@link #channelWidth} is 80 + 80 MHz. If the Responder uses 80 + 80 MHz,
177      * this is the center frequency of the second segment (in MHz).
178      */
179     public final int centerFreq1;
180 
181     /**
182      * The preamble used by the Responder, specified using {@link PreambleType}.
183      */
184     public final int preamble;
185 
186     /**
187      * Constructs Responder configuration, using a MAC address to identify the Responder.
188      *
189      * @param macAddress      The MAC address of the Responder.
190      * @param responderType   The type of the responder device, specified using
191      *                        {@link ResponderType}.
192      * @param supports80211mc Indicates whether the responder supports IEEE 802.11mc.
193      * @param channelWidth    Responder channel bandwidth, specified using {@link ChannelWidth}.
194      * @param frequency       The primary 20 MHz frequency (in MHz) of the channel of the Responder.
195      * @param centerFreq0     Not used if the {@code channelWidth} is 20 MHz. If the Responder uses
196      *                        40, 80 or 160 MHz, this is the center frequency (in MHz), if the
197      *                        Responder uses 80 + 80 MHz, this is the center frequency of the first
198      *                        segment (in MHz).
199      * @param centerFreq1     Only used if the {@code channelWidth} is 80 + 80 MHz. If the
200      *                        Responder
201      *                        uses 80 + 80 MHz, this is the center frequency of the second segment
202      *                        (in
203      *                        MHz).
204      * @param preamble        The preamble used by the Responder, specified using
205      *                        {@link PreambleType}.
206      */
ResponderConfig(@onNull MacAddress macAddress, @ResponderType int responderType, boolean supports80211mc, @ChannelWidth int channelWidth, int frequency, int centerFreq0, int centerFreq1, @PreambleType int preamble)207     public ResponderConfig(@NonNull MacAddress macAddress, @ResponderType int responderType,
208             boolean supports80211mc, @ChannelWidth int channelWidth, int frequency, int centerFreq0,
209             int centerFreq1, @PreambleType int preamble) {
210         if (macAddress == null) {
211             throw new IllegalArgumentException(
212                     "Invalid ResponderConfig - must specify a MAC address");
213         }
214         this.macAddress = macAddress;
215         this.peerHandle = null;
216         this.responderType = responderType;
217         this.supports80211mc = supports80211mc;
218         this.channelWidth = channelWidth;
219         this.frequency = frequency;
220         this.centerFreq0 = centerFreq0;
221         this.centerFreq1 = centerFreq1;
222         this.preamble = preamble;
223     }
224 
225     /**
226      * Constructs Responder configuration, using a Wi-Fi Aware PeerHandle to identify the Responder.
227      *
228      * @param peerHandle      The Wi-Fi Aware peer identifier of the Responder.
229      * @param responderType   The type of the responder device, specified using
230      *                        {@link ResponderType}.
231      * @param supports80211mc Indicates whether the responder supports IEEE 802.11mc.
232      * @param channelWidth    Responder channel bandwidth, specified using {@link ChannelWidth}.
233      * @param frequency       The primary 20 MHz frequency (in MHz) of the channel of the Responder.
234      * @param centerFreq0     Not used if the {@code channelWidth} is 20 MHz. If the Responder uses
235      *                        40, 80 or 160 MHz, this is the center frequency (in MHz), if the
236      *                        Responder uses 80 + 80 MHz, this is the center frequency of the first
237      *                        segment (in MHz).
238      * @param centerFreq1     Only used if the {@code channelWidth} is 80 + 80 MHz. If the
239      *                        Responder
240      *                        uses 80 + 80 MHz, this is the center frequency of the second segment
241      *                        (in
242      *                        MHz).
243      * @param preamble        The preamble used by the Responder, specified using
244      *                        {@link PreambleType}.
245      */
ResponderConfig(@onNull PeerHandle peerHandle, @ResponderType int responderType, boolean supports80211mc, @ChannelWidth int channelWidth, int frequency, int centerFreq0, int centerFreq1, @PreambleType int preamble)246     public ResponderConfig(@NonNull PeerHandle peerHandle, @ResponderType int responderType,
247             boolean supports80211mc, @ChannelWidth int channelWidth, int frequency, int centerFreq0,
248             int centerFreq1, @PreambleType int preamble) {
249         this.macAddress = null;
250         this.peerHandle = peerHandle;
251         this.responderType = responderType;
252         this.supports80211mc = supports80211mc;
253         this.channelWidth = channelWidth;
254         this.frequency = frequency;
255         this.centerFreq0 = centerFreq0;
256         this.centerFreq1 = centerFreq1;
257         this.preamble = preamble;
258     }
259 
260     /**
261      * Constructs Responder configuration. This is an internal-only constructor which specifies both
262      * a MAC address and a Wi-Fi PeerHandle to identify the Responder.
263      *
264      * @param macAddress      The MAC address of the Responder.
265      * @param peerHandle      The Wi-Fi Aware peer identifier of the Responder.
266      * @param responderType   The type of the responder device, specified using
267      *                        {@link ResponderType}.
268      * @param supports80211mc Indicates whether the responder supports IEEE 802.11mc.
269      * @param channelWidth    Responder channel bandwidth, specified using {@link ChannelWidth}.
270      * @param frequency       The primary 20 MHz frequency (in MHz) of the channel of the Responder.
271      * @param centerFreq0     Not used if the {@code channelWidth} is 20 MHz. If the Responder uses
272      *                        40, 80 or 160 MHz, this is the center frequency (in MHz), if the
273      *                        Responder uses 80 + 80 MHz, this is the center frequency of the first
274      *                        segment (in MHz).
275      * @param centerFreq1     Only used if the {@code channelWidth} is 80 + 80 MHz. If the
276      *                        Responder
277      *                        uses 80 + 80 MHz, this is the center frequency of the second segment
278      *                        (in
279      *                        MHz).
280      * @param preamble        The preamble used by the Responder, specified using
281      *                        {@link PreambleType}.
282      * @hide
283      */
ResponderConfig(@onNull MacAddress macAddress, @NonNull PeerHandle peerHandle, @ResponderType int responderType, boolean supports80211mc, @ChannelWidth int channelWidth, int frequency, int centerFreq0, int centerFreq1, @PreambleType int preamble)284     public ResponderConfig(@NonNull MacAddress macAddress, @NonNull PeerHandle peerHandle,
285             @ResponderType int responderType, boolean supports80211mc,
286             @ChannelWidth int channelWidth, int frequency, int centerFreq0, int centerFreq1,
287             @PreambleType int preamble) {
288         this.macAddress = macAddress;
289         this.peerHandle = peerHandle;
290         this.responderType = responderType;
291         this.supports80211mc = supports80211mc;
292         this.channelWidth = channelWidth;
293         this.frequency = frequency;
294         this.centerFreq0 = centerFreq0;
295         this.centerFreq1 = centerFreq1;
296         this.preamble = preamble;
297     }
298 
299     /**
300      * Creates a Responder configuration from a {@link ScanResult} corresponding to an Access
301      * Point (AP), which can be obtained from {@link android.net.wifi.WifiManager#getScanResults()}.
302      */
fromScanResult(ScanResult scanResult)303     public static ResponderConfig fromScanResult(ScanResult scanResult) {
304         MacAddress macAddress = MacAddress.fromString(scanResult.BSSID);
305         int responderType = RESPONDER_AP;
306         boolean supports80211mc = scanResult.is80211mcResponder();
307         int channelWidth = translateScanResultChannelWidth(scanResult.channelWidth);
308         int frequency = scanResult.frequency;
309         int centerFreq0 = scanResult.centerFreq0;
310         int centerFreq1 = scanResult.centerFreq1;
311 
312         int preamble;
313         if (scanResult.informationElements != null && scanResult.informationElements.length != 0) {
314             boolean htCapabilitiesPresent = false;
315             boolean vhtCapabilitiesPresent = false;
316             boolean heCapabilitiesPresent = false;
317 
318             for (ScanResult.InformationElement ie : scanResult.informationElements) {
319                 if (ie.id == EID_HT_CAPABILITIES) {
320                     htCapabilitiesPresent = true;
321                 } else if (ie.id == EID_VHT_CAPABILITIES) {
322                     vhtCapabilitiesPresent = true;
323                 } else if (ie.id == EID_EXTENSION_PRESENT && ie.idExt == EID_EXT_HE_CAPABILITIES) {
324                     heCapabilitiesPresent = true;
325                 }
326             }
327 
328             if (heCapabilitiesPresent && ScanResult.is6GHz(frequency)) {
329                 preamble = PREAMBLE_HE;
330             } else if (vhtCapabilitiesPresent) {
331                 preamble = PREAMBLE_VHT;
332             } else if (htCapabilitiesPresent) {
333                 preamble = PREAMBLE_HT;
334             } else {
335                 preamble = PREAMBLE_LEGACY;
336             }
337         } else {
338             Log.e(TAG, "Scan Results do not contain IEs - using backup method to select preamble");
339             if (channelWidth == CHANNEL_WIDTH_80MHZ || channelWidth == CHANNEL_WIDTH_160MHZ) {
340                 preamble = PREAMBLE_VHT;
341             } else {
342                 preamble = PREAMBLE_HT;
343             }
344         }
345 
346         return new ResponderConfig(macAddress, responderType, supports80211mc, channelWidth,
347                 frequency, centerFreq0, centerFreq1, preamble);
348     }
349 
350     /**
351      * Creates a Responder configuration from a MAC address corresponding to a Wi-Fi Aware
352      * Responder. The Responder parameters are set to defaults.
353      */
fromWifiAwarePeerMacAddressWithDefaults(MacAddress macAddress)354     public static ResponderConfig fromWifiAwarePeerMacAddressWithDefaults(MacAddress macAddress) {
355         /* Note: the parameters are those of the Aware discovery channel (channel 6). A Responder
356          * is expected to be brought up and available to negotiate a maximum accuracy channel
357          * (i.e. Band 5 @ 80MHz). A Responder is brought up on the peer by starting an Aware
358          * Unsolicited Publisher with Ranging enabled.
359          */
360         return new ResponderConfig(macAddress, RESPONDER_AWARE, true, CHANNEL_WIDTH_20MHZ,
361                 AWARE_BAND_2_DISCOVERY_CHANNEL, 0, 0, PREAMBLE_HT);
362     }
363 
364     /**
365      * Creates a Responder configuration from a {@link PeerHandle} corresponding to a Wi-Fi Aware
366      * Responder. The Responder parameters are set to defaults.
367      */
fromWifiAwarePeerHandleWithDefaults(PeerHandle peerHandle)368     public static ResponderConfig fromWifiAwarePeerHandleWithDefaults(PeerHandle peerHandle) {
369         /* Note: the parameters are those of the Aware discovery channel (channel 6). A Responder
370          * is expected to be brought up and available to negotiate a maximum accuracy channel
371          * (i.e. Band 5 @ 80MHz). A Responder is brought up on the peer by starting an Aware
372          * Unsolicited Publisher with Ranging enabled.
373          */
374         return new ResponderConfig(peerHandle, RESPONDER_AWARE, true, CHANNEL_WIDTH_20MHZ,
375                 AWARE_BAND_2_DISCOVERY_CHANNEL, 0, 0, PREAMBLE_HT);
376     }
377 
378     /**
379      * Check whether the Responder configuration is valid.
380      *
381      * @return true if valid, false otherwise.
382      * @hide
383      */
isValid(boolean awareSupported)384     public boolean isValid(boolean awareSupported) {
385         if (macAddress == null && peerHandle == null || macAddress != null && peerHandle != null) {
386             return false;
387         }
388         if (!awareSupported && responderType == RESPONDER_AWARE) {
389             return false;
390         }
391 
392         return true;
393     }
394 
395     @Override
describeContents()396     public int describeContents() {
397         return 0;
398     }
399 
400     @Override
writeToParcel(Parcel dest, int flags)401     public void writeToParcel(Parcel dest, int flags) {
402         if (macAddress == null) {
403             dest.writeBoolean(false);
404         } else {
405             dest.writeBoolean(true);
406             macAddress.writeToParcel(dest, flags);
407         }
408         if (peerHandle == null) {
409             dest.writeBoolean(false);
410         } else {
411             dest.writeBoolean(true);
412             dest.writeInt(peerHandle.peerId);
413         }
414         dest.writeInt(responderType);
415         dest.writeInt(supports80211mc ? 1 : 0);
416         dest.writeInt(channelWidth);
417         dest.writeInt(frequency);
418         dest.writeInt(centerFreq0);
419         dest.writeInt(centerFreq1);
420         dest.writeInt(preamble);
421     }
422 
423     public static final @android.annotation.NonNull Creator<ResponderConfig> CREATOR = new Creator<ResponderConfig>() {
424         @Override
425         public ResponderConfig[] newArray(int size) {
426             return new ResponderConfig[size];
427         }
428 
429         @Override
430         public ResponderConfig createFromParcel(Parcel in) {
431             boolean macAddressPresent = in.readBoolean();
432             MacAddress macAddress = null;
433             if (macAddressPresent) {
434                 macAddress = MacAddress.CREATOR.createFromParcel(in);
435             }
436             boolean peerHandlePresent = in.readBoolean();
437             PeerHandle peerHandle = null;
438             if (peerHandlePresent) {
439                 peerHandle = new PeerHandle(in.readInt());
440             }
441             int responderType = in.readInt();
442             boolean supports80211mc = in.readInt() == 1;
443             int channelWidth = in.readInt();
444             int frequency = in.readInt();
445             int centerFreq0 = in.readInt();
446             int centerFreq1 = in.readInt();
447             int preamble = in.readInt();
448 
449             if (peerHandle == null) {
450                 return new ResponderConfig(macAddress, responderType, supports80211mc, channelWidth,
451                         frequency, centerFreq0, centerFreq1, preamble);
452             } else {
453                 return new ResponderConfig(peerHandle, responderType, supports80211mc, channelWidth,
454                         frequency, centerFreq0, centerFreq1, preamble);
455             }
456         }
457     };
458 
459     @Override
equals(@ullable Object o)460     public boolean equals(@Nullable Object o) {
461         if (this == o) {
462             return true;
463         }
464 
465         if (!(o instanceof ResponderConfig)) {
466             return false;
467         }
468 
469         ResponderConfig lhs = (ResponderConfig) o;
470 
471         return Objects.equals(macAddress, lhs.macAddress) && Objects.equals(peerHandle,
472                 lhs.peerHandle) && responderType == lhs.responderType
473                 && supports80211mc == lhs.supports80211mc && channelWidth == lhs.channelWidth
474                 && frequency == lhs.frequency && centerFreq0 == lhs.centerFreq0
475                 && centerFreq1 == lhs.centerFreq1 && preamble == lhs.preamble;
476     }
477 
478     @Override
hashCode()479     public int hashCode() {
480         return Objects.hash(macAddress, peerHandle, responderType, supports80211mc, channelWidth,
481                 frequency, centerFreq0, centerFreq1, preamble);
482     }
483 
484     /** @hide */
485     @Override
toString()486     public String toString() {
487         return new StringBuffer("ResponderConfig: macAddress=").append(macAddress).append(
488                 ", peerHandle=").append(peerHandle == null ? "<null>" : peerHandle.peerId).append(
489                 ", responderType=").append(responderType).append(", supports80211mc=").append(
490                 supports80211mc).append(", channelWidth=").append(channelWidth).append(
491                 ", frequency=").append(frequency).append(", centerFreq0=").append(
492                 centerFreq0).append(", centerFreq1=").append(centerFreq1).append(
493                 ", preamble=").append(preamble).toString();
494     }
495 
496     /** @hide */
translateScanResultChannelWidth(int scanResultChannelWidth)497     static int translateScanResultChannelWidth(int scanResultChannelWidth) {
498         switch (scanResultChannelWidth) {
499             case ScanResult.CHANNEL_WIDTH_20MHZ:
500                 return CHANNEL_WIDTH_20MHZ;
501             case ScanResult.CHANNEL_WIDTH_40MHZ:
502                 return CHANNEL_WIDTH_40MHZ;
503             case ScanResult.CHANNEL_WIDTH_80MHZ:
504                 return CHANNEL_WIDTH_80MHZ;
505             case ScanResult.CHANNEL_WIDTH_160MHZ:
506                 return CHANNEL_WIDTH_160MHZ;
507             case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
508                 return CHANNEL_WIDTH_80MHZ_PLUS_MHZ;
509             default:
510                 throw new IllegalArgumentException(
511                         "translateScanResultChannelWidth: bad " + scanResultChannelWidth);
512         }
513     }
514 }
515