• 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_EHT_CAPABILITIES;
21 import static android.net.wifi.ScanResult.InformationElement.EID_EXT_HE_CAPABILITIES;
22 import static android.net.wifi.ScanResult.InformationElement.EID_HT_CAPABILITIES;
23 import static android.net.wifi.ScanResult.InformationElement.EID_VHT_CAPABILITIES;
24 
25 import android.annotation.IntDef;
26 import android.annotation.IntRange;
27 import android.annotation.NonNull;
28 import android.annotation.Nullable;
29 import android.annotation.SystemApi;
30 import android.net.MacAddress;
31 import android.net.wifi.ScanResult;
32 import android.net.wifi.WifiAnnotations;
33 import android.net.wifi.aware.PeerHandle;
34 import android.os.Parcel;
35 import android.os.Parcelable;
36 import android.util.Log;
37 
38 import java.lang.annotation.Retention;
39 import java.lang.annotation.RetentionPolicy;
40 import java.util.Objects;
41 
42 /**
43  * Defines the configuration of an IEEE 802.11mc Responder. The Responder may be an Access Point
44  * (AP), a Wi-Fi Aware device, or a manually configured Responder.
45  * <p>
46  * A Responder configuration may be constructed from a {@link ScanResult} or manually (with the
47  * data obtained out-of-band from a peer).
48  */
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 access point(AP).
61      */
62 
63     public static final int RESPONDER_AP = 0;
64 
65     /**
66      * Responder is a client device(STA).
67      */
68     public static final int RESPONDER_STA = 1;
69 
70     /**
71      * Responder is a Wi-Fi Direct Group Owner (GO).
72      * @hide
73      */
74     @SystemApi
75     public static final int RESPONDER_P2P_GO = 2;
76 
77     /**
78      * Responder is a Wi-Fi Direct Group Client.
79      * @hide
80      */
81     @SystemApi
82     public static final int RESPONDER_P2P_CLIENT = 3;
83 
84     /**
85      * Responder is a Wi-Fi Aware device.
86      * @hide
87      */
88     @SystemApi
89     public static final int RESPONDER_AWARE = 4;
90 
91     /** @hide */
92     @IntDef({
93             CHANNEL_WIDTH_20MHZ, CHANNEL_WIDTH_40MHZ, CHANNEL_WIDTH_80MHZ, CHANNEL_WIDTH_160MHZ,
94             CHANNEL_WIDTH_80MHZ_PLUS_MHZ, CHANNEL_WIDTH_320MHZ})
95     @Retention(RetentionPolicy.SOURCE)
96     public @interface ChannelWidth {
97     }
98 
99 
100     /**
101      * Channel bandwidth is 20 MHZ
102      * @hide
103      */
104     @SystemApi
105     public static final int CHANNEL_WIDTH_20MHZ = 0;
106 
107     /**
108      * Channel bandwidth is 40 MHZ
109      * @hide
110      */
111     @SystemApi
112     public static final int CHANNEL_WIDTH_40MHZ = 1;
113 
114     /**
115      * Channel bandwidth is 80 MHZ
116      * @hide
117      */
118     @SystemApi
119     public static final int CHANNEL_WIDTH_80MHZ = 2;
120 
121     /**
122      * Channel bandwidth is 160 MHZ
123      * @hide
124      */
125     @SystemApi
126     public static final int CHANNEL_WIDTH_160MHZ = 3;
127 
128     /**
129      * Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ
130      * @hide
131      */
132     @SystemApi
133     public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4;
134 
135     /**
136      * Channel bandwidth is 320 MHZ
137      * @hide
138      */
139     @SystemApi
140     public static final int CHANNEL_WIDTH_320MHZ = 5;
141 
142 
143     /** @hide */
144     @IntDef({PREAMBLE_LEGACY, PREAMBLE_HT, PREAMBLE_VHT, PREAMBLE_HE, PREAMBLE_EHT})
145     @Retention(RetentionPolicy.SOURCE)
146     public @interface PreambleType {
147     }
148 
149     /**
150      * Preamble type: Legacy.
151      * @hide
152      */
153     @SystemApi
154     public static final int PREAMBLE_LEGACY = 0;
155 
156     /**
157      * Preamble type: HT.
158      * @hide
159      */
160     @SystemApi
161     public static final int PREAMBLE_HT = 1;
162 
163     /**
164      * Preamble type: VHT.
165      * @hide
166      */
167     @SystemApi
168     public static final int PREAMBLE_VHT = 2;
169 
170     /**
171      * Preamble type: HE.
172      * @hide
173      */
174     @SystemApi
175     public static final int PREAMBLE_HE = 3;
176 
177     /**
178      * Preamble type: EHT.
179      * @hide
180      */
181     @SystemApi
182     public static final int PREAMBLE_EHT = 4;
183 
184     /**
185      * The MAC address of the Responder. Will be null if a Wi-Fi Aware peer identifier (the
186      * peerHandle field) ise used to identify the Responder.
187      * @hide
188      */
189     @SystemApi
190     @Nullable public final MacAddress macAddress;
191 
192     /**
193      * The peer identifier of a Wi-Fi Aware Responder. Will be null if a MAC Address (the macAddress
194      * field) is used to identify the Responder.
195      * @hide
196      */
197     @SystemApi
198     @Nullable public final PeerHandle peerHandle;
199 
200     /**
201      * The device type of the Responder.
202      * @hide
203      */
204     @SystemApi
205     public final int responderType;
206 
207     /**
208      * Indicates whether the Responder device supports IEEE 802.11mc.
209      * @hide
210      */
211     @SystemApi
212     public final boolean supports80211mc;
213 
214     /**
215      * Responder channel bandwidth, specified using {@link ChannelWidth}.
216      * @hide
217      */
218     @SystemApi
219     public final int channelWidth;
220 
221     /**
222      * The primary 20 MHz frequency (in MHz) of the channel of the Responder.
223      * @hide
224      */
225     @SystemApi
226     public final int frequency;
227 
228     /**
229      * Not used if the {@link #channelWidth} is 20 MHz. If the Responder uses 40, 80, 160 or
230      * 320 MHz, this is the center frequency (in MHz), if the Responder uses 80 + 80 MHz,
231      * this is the center frequency of the first segment (in MHz).
232      * @hide
233      */
234     @SystemApi
235     public final int centerFreq0;
236 
237     /**
238      * Only used if the {@link #channelWidth} is 80 + 80 MHz. If the Responder uses 80 + 80 MHz,
239      * this is the center frequency of the second segment (in MHz).
240      * @hide
241      */
242     @SystemApi
243     public final int centerFreq1;
244 
245     /**
246      * The preamble used by the Responder, specified using {@link PreambleType}.
247      * @hide
248      */
249     @SystemApi
250     public final int preamble;
251 
252     /**
253      * Constructs Responder configuration, using a MAC address to identify the Responder.
254      *
255      * @param macAddress      The MAC address of the Responder.
256      * @param responderType   The type of the responder device, specified using
257      *                        {@link ResponderType}.
258      *                        For an access point (AP) use {@code RESPONDER_AP}.
259      * @param supports80211mc Indicates whether the responder supports IEEE 802.11mc.
260      * @param channelWidth    Responder channel bandwidth, specified using {@link ChannelWidth}.
261      * @param frequency       The primary 20 MHz frequency (in MHz) of the channel of the Responder.
262      * @param centerFreq0     Not used if the {@code channelWidth} is 20 MHz. If the Responder uses
263      *                        40, 80, 160 or 320 MHz, this is the center frequency (in MHz), if the
264      *                        Responder uses 80 + 80 MHz, this is the center frequency of the first
265      *                        segment (in MHz).
266      * @param centerFreq1     Only used if the {@code channelWidth} is 80 + 80 MHz. If the
267      *                        Responder
268      *                        uses 80 + 80 MHz, this is the center frequency of the second segment
269      *                        (in
270      *                        MHz).
271      * @param preamble        The preamble used by the Responder, specified using
272      *                        {@link PreambleType}.
273      * @hide
274      */
275     @SystemApi
ResponderConfig(@onNull MacAddress macAddress, @ResponderType int responderType, boolean supports80211mc, @ChannelWidth int channelWidth, int frequency, int centerFreq0, int centerFreq1, @PreambleType int preamble)276     public ResponderConfig(@NonNull MacAddress macAddress, @ResponderType int responderType,
277             boolean supports80211mc, @ChannelWidth int channelWidth, int frequency, int centerFreq0,
278             int centerFreq1, @PreambleType int preamble) {
279         if (macAddress == null) {
280             throw new IllegalArgumentException(
281                     "Invalid ResponderConfig - must specify a MAC address");
282         }
283         this.macAddress = macAddress;
284         this.peerHandle = null;
285         this.responderType = responderType;
286         this.supports80211mc = supports80211mc;
287         this.channelWidth = channelWidth;
288         this.frequency = frequency;
289         this.centerFreq0 = centerFreq0;
290         this.centerFreq1 = centerFreq1;
291         this.preamble = preamble;
292     }
293 
294     /**
295      * Constructs Responder configuration, using a Wi-Fi Aware PeerHandle to identify the Responder.
296      *
297      * @param peerHandle      The Wi-Fi Aware peer identifier of the Responder.
298      * @param responderType   The type of the responder device, specified using
299      *                        {@link ResponderType}.
300      * @param supports80211mc Indicates whether the responder supports IEEE 802.11mc.
301      * @param channelWidth    Responder channel bandwidth, specified using {@link ChannelWidth}.
302      * @param frequency       The primary 20 MHz frequency (in MHz) of the channel of the Responder.
303      * @param centerFreq0     Not used if the {@code channelWidth} is 20 MHz. If the Responder uses
304      *                        40, 80, 160, or 320 MHz, this is the center frequency (in MHz), if the
305      *                        Responder uses 80 + 80 MHz, this is the center frequency of the first
306      *                        segment (in MHz).
307      * @param centerFreq1     Only used if the {@code channelWidth} is 80 + 80 MHz. If the
308      *                        Responder
309      *                        uses 80 + 80 MHz, this is the center frequency of the second segment
310      *                        (in
311      *                        MHz).
312      * @param preamble        The preamble used by the Responder, specified using
313      *                        {@link PreambleType}.
314      * @hide
315      */
316     @SystemApi
ResponderConfig(@onNull PeerHandle peerHandle, @ResponderType int responderType, boolean supports80211mc, @ChannelWidth int channelWidth, int frequency, int centerFreq0, int centerFreq1, @PreambleType int preamble)317     public ResponderConfig(@NonNull PeerHandle peerHandle, @ResponderType int responderType,
318             boolean supports80211mc, @ChannelWidth int channelWidth, int frequency, int centerFreq0,
319             int centerFreq1, @PreambleType int preamble) {
320         this.macAddress = null;
321         this.peerHandle = peerHandle;
322         this.responderType = responderType;
323         this.supports80211mc = supports80211mc;
324         this.channelWidth = channelWidth;
325         this.frequency = frequency;
326         this.centerFreq0 = centerFreq0;
327         this.centerFreq1 = centerFreq1;
328         this.preamble = preamble;
329     }
330 
331     /**
332      * Constructs Responder configuration. This is a constructor which specifies both
333      * a MAC address and a Wi-Fi PeerHandle to identify the Responder. For an RTT RangingRequest
334      * the Wi-Fi Aware peer identifier can be constructed using an Identifier set to zero.
335      *
336      * @param macAddress      The MAC address of the Responder.
337      * @param peerHandle      The Wi-Fi Aware peer identifier of the Responder.
338      * @param responderType   The type of the responder device, specified using
339      *                        {@link ResponderType}.
340      * @param supports80211mc Indicates whether the responder supports IEEE 802.11mc.
341      * @param channelWidth    Responder channel bandwidth, specified using {@link ChannelWidth}.
342      * @param frequency       The primary 20 MHz frequency (in MHz) of the channel of the Responder.
343      * @param centerFreq0     Not used if the {@code channelWidth} is 20 MHz. If the Responder uses
344      *                        40, 80, 160 or 320 MHz, this is the center frequency (in MHz), if the
345      *                        Responder uses 80 + 80 MHz, this is the center frequency of the first
346      *                        segment (in MHz).
347      * @param centerFreq1     Only used if the {@code channelWidth} is 80 + 80 MHz. If the
348      *                        Responder
349      *                        uses 80 + 80 MHz, this is the center frequency of the second segment
350      *                        (in
351      *                        MHz).
352      * @param preamble        The preamble used by the Responder, specified using
353      *                        {@link PreambleType}.
354      *
355      * @hide
356      */
ResponderConfig(@onNull MacAddress macAddress, @NonNull PeerHandle peerHandle, @ResponderType int responderType, boolean supports80211mc, @ChannelWidth int channelWidth, int frequency, int centerFreq0, int centerFreq1, @PreambleType int preamble)357     public ResponderConfig(@NonNull MacAddress macAddress, @NonNull PeerHandle peerHandle,
358             @ResponderType int responderType, boolean supports80211mc,
359             @ChannelWidth int channelWidth, int frequency, int centerFreq0, int centerFreq1,
360             @PreambleType int preamble) {
361         this.macAddress = macAddress;
362         this.peerHandle = peerHandle;
363         this.responderType = responderType;
364         this.supports80211mc = supports80211mc;
365         this.channelWidth = channelWidth;
366         this.frequency = frequency;
367         this.centerFreq0 = centerFreq0;
368         this.centerFreq1 = centerFreq1;
369         this.preamble = preamble;
370     }
371 
372     /**
373      * Creates a Responder configuration from a {@link ScanResult} corresponding to an Access
374      * Point (AP), which can be obtained from {@link android.net.wifi.WifiManager#getScanResults()}.
375      */
376     @NonNull
fromScanResult(@onNull ScanResult scanResult)377     public static ResponderConfig fromScanResult(@NonNull ScanResult scanResult) {
378         MacAddress macAddress = MacAddress.fromString(scanResult.BSSID);
379         int responderType = RESPONDER_AP;
380         boolean supports80211mc = scanResult.is80211mcResponder();
381         int channelWidth = translateFromScanResultToLocalChannelWidth(scanResult.channelWidth);
382         int frequency = scanResult.frequency;
383         int centerFreq0 = scanResult.centerFreq0;
384         int centerFreq1 = scanResult.centerFreq1;
385 
386         int preamble;
387         if (scanResult.informationElements != null && scanResult.informationElements.length != 0) {
388             boolean htCapabilitiesPresent = false;
389             boolean vhtCapabilitiesPresent = false;
390             boolean heCapabilitiesPresent = false;
391             boolean ehtCapabilitiesPresent = false;
392 
393             for (ScanResult.InformationElement ie : scanResult.informationElements) {
394                 if (ie.id == EID_HT_CAPABILITIES) {
395                     htCapabilitiesPresent = true;
396                 } else if (ie.id == EID_VHT_CAPABILITIES) {
397                     vhtCapabilitiesPresent = true;
398                 } else if (ie.id == EID_EXTENSION_PRESENT && ie.idExt == EID_EXT_HE_CAPABILITIES) {
399                     heCapabilitiesPresent = true;
400                 } else if (ie.id == EID_EXTENSION_PRESENT && ie.idExt == EID_EXT_EHT_CAPABILITIES) {
401                     ehtCapabilitiesPresent = true;
402                 }
403             }
404 
405             if (ehtCapabilitiesPresent && ScanResult.is6GHz(frequency)) {
406                 preamble = PREAMBLE_EHT;
407             } else if (heCapabilitiesPresent && ScanResult.is6GHz(frequency)) {
408                 preamble = PREAMBLE_HE;
409             } else if (vhtCapabilitiesPresent) {
410                 preamble = PREAMBLE_VHT;
411             } else if (htCapabilitiesPresent) {
412                 preamble = PREAMBLE_HT;
413             } else {
414                 preamble = PREAMBLE_LEGACY;
415             }
416         } else {
417             Log.e(TAG, "Scan Results do not contain IEs - using backup method to select preamble");
418             if (channelWidth == CHANNEL_WIDTH_320MHZ) {
419                 preamble = PREAMBLE_EHT;
420             } else if (channelWidth == CHANNEL_WIDTH_80MHZ
421                     || channelWidth == CHANNEL_WIDTH_160MHZ) {
422                 preamble = PREAMBLE_VHT;
423             } else {
424                 preamble = PREAMBLE_HT;
425             }
426         }
427 
428         return new ResponderConfig(macAddress, responderType, supports80211mc, channelWidth,
429                 frequency, centerFreq0, centerFreq1, preamble);
430     }
431 
432     /**
433      * Creates a Responder configuration from a MAC address corresponding to a Wi-Fi Aware
434      * Responder. The Responder parameters are set to defaults.
435      * @hide
436      */
437     @SystemApi
438     @NonNull
fromWifiAwarePeerMacAddressWithDefaults( @onNull MacAddress macAddress)439     public static ResponderConfig fromWifiAwarePeerMacAddressWithDefaults(
440             @NonNull MacAddress macAddress) {
441         /* Note: the parameters are those of the Aware discovery channel (channel 6). A Responder
442          * is expected to be brought up and available to negotiate a maximum accuracy channel
443          * (i.e. Band 5 @ 80MHz). A Responder is brought up on the peer by starting an Aware
444          * Unsolicited Publisher with Ranging enabled.
445          */
446         return new ResponderConfig(macAddress, RESPONDER_AWARE, true, CHANNEL_WIDTH_20MHZ,
447                 AWARE_BAND_2_DISCOVERY_CHANNEL, 0, 0, PREAMBLE_HT);
448     }
449 
450     /**
451      * Creates a Responder configuration from a {@link PeerHandle} corresponding to a Wi-Fi Aware
452      * Responder. The Responder parameters are set to defaults.
453      * @hide
454      */
455     @SystemApi
456     @NonNull
fromWifiAwarePeerHandleWithDefaults( @onNull PeerHandle peerHandle)457     public static ResponderConfig fromWifiAwarePeerHandleWithDefaults(
458             @NonNull PeerHandle peerHandle) {
459         /* Note: the parameters are those of the Aware discovery channel (channel 6). A Responder
460          * is expected to be brought up and available to negotiate a maximum accuracy channel
461          * (i.e. Band 5 @ 80MHz). A Responder is brought up on the peer by starting an Aware
462          * Unsolicited Publisher with Ranging enabled.
463          */
464         return new ResponderConfig(peerHandle, RESPONDER_AWARE, true, CHANNEL_WIDTH_20MHZ,
465                 AWARE_BAND_2_DISCOVERY_CHANNEL, 0, 0, PREAMBLE_HT);
466     }
467 
468     /**
469      * Check whether the Responder configuration is valid.
470      *
471      * @return true if valid, false otherwise.
472      *
473      * @hide
474      */
isValid(boolean awareSupported)475     public boolean isValid(boolean awareSupported) {
476         if (macAddress == null && peerHandle == null || macAddress != null && peerHandle != null) {
477             return false;
478         }
479         if (!awareSupported && responderType == RESPONDER_AWARE) {
480             return false;
481         }
482         return true;
483     }
484 
485     /**
486      * @return the MAC address of the responder
487      */
488     @Nullable
getMacAddress()489     public MacAddress getMacAddress() {
490         return macAddress;
491     }
492 
493     /**
494      * @return true if the Responder supports the 802.11mc protocol, false otherwise.
495      */
is80211mcSupported()496     public boolean is80211mcSupported() {
497         return supports80211mc;
498     }
499 
500     /**
501      * AP Channel bandwidth; one of {@link ScanResult#CHANNEL_WIDTH_20MHZ},
502      * {@link ScanResult#CHANNEL_WIDTH_40MHZ},
503      * {@link ScanResult#CHANNEL_WIDTH_80MHZ}, {@link ScanResult#CHANNEL_WIDTH_160MHZ},
504      * {@link ScanResult #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link ScanResult#CHANNEL_WIDTH_320MHZ}.
505      *
506      * @return the bandwidth repsentation of the Wi-Fi channel
507      */
getChannelWidth()508     public @WifiAnnotations.ChannelWidth int getChannelWidth() {
509         return translateFromLocalToScanResultChannelWidth(channelWidth);
510     }
511 
512     /**
513      * @return the frequency in MHz of the Wi-Fi channel
514      */
515     @IntRange(from = 0)
getFrequencyMhz()516     public int getFrequencyMhz() {
517         return frequency;
518     }
519 
520     /**
521      * If the Access Point (AP) bandwidth is 20 MHz, 0 MHz is returned.
522      * If the AP use 40, 80 or 160 MHz, this is the center frequency (in MHz).
523      * if the AP uses 80 + 80 MHz, this is the center frequency of the first segment (in MHz).
524      *
525      * @return the center frequency in MHz of the first channel segment
526      */
527     @IntRange(from = 0)
getCenterFreq0Mhz()528     public int getCenterFreq0Mhz() {
529         return centerFreq0;
530     }
531 
532     /**
533      * If the Access Point (AP) bandwidth is 80 + 80 MHz, this param is not used and returns 0.
534      * If the AP uses 80 + 80 MHz, this is the center frequency of the second segment in MHz.
535      *
536      * @return the center frequency in MHz of the second channel segment (if used)
537      */
538     @IntRange(from = 0)
getCenterFreq1Mhz()539     public int getCenterFreq1Mhz() {
540         return centerFreq1;
541     }
542 
543     /**
544      * Get the preamble type of the channel.
545      *
546      * @return the preamble used for this channel
547      */
getPreamble()548     public @WifiAnnotations.PreambleType int getPreamble() {
549         return translateFromLocalToScanResultPreamble(preamble);
550     }
551 
552     /**
553      * Get responder type.
554      * @see Builder#setResponderType(int)
555      * @return The type of this responder
556      */
getResponderType()557     public @ResponderType int getResponderType() {
558         return responderType;
559     }
560 
561     /**
562      * Builder class used to construct {@link ResponderConfig} objects.
563      */
564     public static final class Builder {
565         private MacAddress mMacAddress;
566         private @ResponderType int mResponderType = RESPONDER_AP;
567         private boolean mSupports80211Mc = true;
568         private @ChannelWidth int mChannelWidth = CHANNEL_WIDTH_20MHZ;
569         private int mFrequency = 0;
570         private int mCenterFreq0 = 0;
571         private int mCenterFreq1 = 0;
572         private @PreambleType int mPreamble = PREAMBLE_LEGACY;
573 
574         /**
575          * Sets the Responder MAC Address.
576          *
577          * @param macAddress the phyical address of the responder
578          * @return the builder to facilitate chaining
579          *         {@code builder.setXXX(..).setXXX(..)}.
580          */
581         @NonNull
setMacAddress(@onNull MacAddress macAddress)582         public Builder setMacAddress(@NonNull MacAddress macAddress) {
583             this.mMacAddress = macAddress;
584             return this;
585         }
586 
587         /**
588          * Sets an indication the access point can to respond to the two-sided Wi-Fi RTT protocol,
589          * but, if false, indicates only one-sided Wi-Fi RTT is possible.
590          *
591          * @param supports80211mc the ability to support the Wi-Fi RTT protocol
592          * @return the builder to facilitate chaining
593          *         {@code builder.setXXX(..).setXXX(..)}.
594          */
595         @NonNull
set80211mcSupported(boolean supports80211mc)596         public Builder set80211mcSupported(boolean supports80211mc) {
597             this.mSupports80211Mc = supports80211mc;
598             return this;
599         }
600 
601         /**
602          * Sets the channel bandwidth in MHz.
603          *
604          * @param channelWidth the bandwidth of the channel in MHz
605          * @return the builder to facilitate chaining
606          *         {@code builder.setXXX(..).setXXX(..)}.
607          */
608         @NonNull
setChannelWidth(@ifiAnnotations.ChannelWidth int channelWidth)609         public Builder setChannelWidth(@WifiAnnotations.ChannelWidth int channelWidth) {
610             this.mChannelWidth = translateFromScanResultToLocalChannelWidth(channelWidth);
611             return this;
612         }
613 
614         /**
615          * Sets the frequency of the channel in MHz.
616          * <p>
617          * Note: The frequency is used as a hint, and the underlying WiFi subsystem may use it, or
618          * select an alternate if its own connectivity scans have determined the frequency of the
619          * access point has changed.
620          * </p>
621          *
622          * @param frequency the frequency of the channel in MHz
623          * @return the builder to facilitate chaining
624          *         {@code builder.setXXX(..).setXXX(..)}.
625          */
626         @NonNull
setFrequencyMhz(@ntRangefrom = 0) int frequency)627         public Builder setFrequencyMhz(@IntRange(from = 0) int frequency) {
628             this.mFrequency = frequency;
629             return this;
630         }
631 
632         /**
633          * Sets the center frequency in MHz of the first segment of the channel.
634          * <p>
635          * Note: The frequency is used as a hint, and the underlying WiFi subsystem may use it, or
636          * select an alternate if its own connectivity scans have determined the frequency of the
637          * access point has changed.
638          * </p>
639          *
640          * @param centerFreq0 the center frequency in MHz of first channel segment
641          * @return the builder to facilitate chaining
642          *         {@code builder.setXXX(..).setXXX(..)}.
643          */
644         @NonNull
setCenterFreq0Mhz(@ntRangefrom = 0) int centerFreq0)645         public Builder setCenterFreq0Mhz(@IntRange(from = 0) int centerFreq0) {
646             this.mCenterFreq0 = centerFreq0;
647             return this;
648         }
649 
650         /**
651          * Sets the center frequency in MHz of the second segment of the channel, if used.
652          * <p>
653          * Note: The frequency is used as a hint, and the underlying WiFi subsystem may use it, or
654          * select an alternate if its own connectivity scans have determined the frequency of the
655          * access point has changed.
656          * </p>
657          *
658          * @param centerFreq1 the center frequency in MHz of second channel segment
659          * @return the builder to facilitate chaining
660          *         {@code builder.setXXX(..).setXXX(..)}.
661          */
662         @NonNull
setCenterFreq1Mhz(@ntRangefrom = 0) int centerFreq1)663         public Builder setCenterFreq1Mhz(@IntRange(from = 0) int centerFreq1) {
664             this.mCenterFreq1 = centerFreq1;
665             return this;
666         }
667 
668         /**
669          * Sets the preamble encoding for the protocol.
670          *
671          * @param preamble the preamble encoding
672          * @return the builder to facilitate chaining
673          *         {@code builder.setXXX(..).setXXX(..)}.
674          */
675         @NonNull
setPreamble(@ifiAnnotations.PreambleType int preamble)676         public Builder setPreamble(@WifiAnnotations.PreambleType int preamble) {
677             this.mPreamble = translateFromScanResultToLocalPreamble(preamble);
678             return this;
679         }
680 
681         /**
682          * Sets the responder type, can be {@link #RESPONDER_AP} or {@link #RESPONDER_STA}
683          *
684          * @param responderType the type of the responder, if not set defaults to
685          * {@link #RESPONDER_AP}
686          * @return the builder to facilitate chaining {@code builder.setXXX(..).setXXX(..)}.
687          */
688         @NonNull
setResponderType(@esponderType int responderType)689         public Builder setResponderType(@ResponderType int responderType) {
690             if (responderType != RESPONDER_STA && responderType != RESPONDER_AP) {
691                 throw new IllegalArgumentException("invalid responder type");
692             }
693             mResponderType = responderType;
694             return this;
695         }
696 
697         /**
698          * Build {@link ResponderConfig} given the current configurations made on the builder.
699          * @return an instance of {@link ResponderConfig}
700          */
701         @NonNull
build()702         public ResponderConfig build() {
703             if (mMacAddress == null) {
704                 throw new IllegalArgumentException(
705                         "Invalid ResponderConfig - must specify a MAC address");
706             }
707             return new ResponderConfig(mMacAddress, mResponderType, mSupports80211Mc, mChannelWidth,
708                     mFrequency, mCenterFreq0, mCenterFreq1, mPreamble);
709         }
710     }
711 
712     @Override
describeContents()713     public int describeContents() {
714         return 0;
715     }
716 
717     @Override
writeToParcel(@onNull Parcel dest, int flags)718     public void writeToParcel(@NonNull Parcel dest, int flags) {
719         if (macAddress == null) {
720             dest.writeBoolean(false);
721         } else {
722             dest.writeBoolean(true);
723             macAddress.writeToParcel(dest, flags);
724         }
725         if (peerHandle == null) {
726             dest.writeBoolean(false);
727         } else {
728             dest.writeBoolean(true);
729             dest.writeInt(peerHandle.peerId);
730         }
731         dest.writeInt(responderType);
732         dest.writeInt(supports80211mc ? 1 : 0);
733         dest.writeInt(channelWidth);
734         dest.writeInt(frequency);
735         dest.writeInt(centerFreq0);
736         dest.writeInt(centerFreq1);
737         dest.writeInt(preamble);
738     }
739 
740     public static final @android.annotation.NonNull Creator<ResponderConfig> CREATOR = new Creator<ResponderConfig>() {
741         @Override
742         public ResponderConfig[] newArray(int size) {
743             return new ResponderConfig[size];
744         }
745 
746         @Override
747         public ResponderConfig createFromParcel(Parcel in) {
748             boolean macAddressPresent = in.readBoolean();
749             MacAddress macAddress = null;
750             if (macAddressPresent) {
751                 macAddress = MacAddress.CREATOR.createFromParcel(in);
752             }
753             boolean peerHandlePresent = in.readBoolean();
754             PeerHandle peerHandle = null;
755             if (peerHandlePresent) {
756                 peerHandle = new PeerHandle(in.readInt());
757             }
758             int responderType = in.readInt();
759             boolean supports80211mc = in.readInt() == 1;
760             int channelWidth = in.readInt();
761             int frequency = in.readInt();
762             int centerFreq0 = in.readInt();
763             int centerFreq1 = in.readInt();
764             int preamble = in.readInt();
765 
766             if (peerHandle == null) {
767                 return new ResponderConfig(macAddress, responderType, supports80211mc, channelWidth,
768                         frequency, centerFreq0, centerFreq1, preamble);
769             } else {
770                 return new ResponderConfig(peerHandle, responderType, supports80211mc, channelWidth,
771                         frequency, centerFreq0, centerFreq1, preamble);
772             }
773         }
774     };
775 
776     @Override
equals(@ullable Object o)777     public boolean equals(@Nullable Object o) {
778         if (this == o) {
779             return true;
780         }
781 
782         if (!(o instanceof ResponderConfig)) {
783             return false;
784         }
785 
786         ResponderConfig lhs = (ResponderConfig) o;
787 
788         return Objects.equals(macAddress, lhs.macAddress) && Objects.equals(peerHandle,
789                 lhs.peerHandle) && responderType == lhs.responderType
790                 && supports80211mc == lhs.supports80211mc && channelWidth == lhs.channelWidth
791                 && frequency == lhs.frequency && centerFreq0 == lhs.centerFreq0
792                 && centerFreq1 == lhs.centerFreq1 && preamble == lhs.preamble;
793     }
794 
795     @Override
hashCode()796     public int hashCode() {
797         return Objects.hash(macAddress, peerHandle, responderType, supports80211mc, channelWidth,
798                 frequency, centerFreq0, centerFreq1, preamble);
799     }
800 
801     @Override
toString()802     public String toString() {
803         return new StringBuffer("ResponderConfig: macAddress=").append(macAddress).append(
804                 ", peerHandle=").append(peerHandle == null ? "<null>" : peerHandle.peerId).append(
805                 ", responderType=").append(responderType).append(", supports80211mc=").append(
806                 supports80211mc).append(", channelWidth=").append(channelWidth).append(
807                 ", frequency=").append(frequency).append(", centerFreq0=").append(
808                 centerFreq0).append(", centerFreq1=").append(centerFreq1).append(
809                 ", preamble=").append(preamble).toString();
810     }
811 
812     /**
813      * Translate an SDK channel width encoding to a local channel width encoding
814      *
815      * @param scanResultChannelWidth the {@link ScanResult} defined channel width encoding
816      * @return the translated channel width encoding
817      *
818      * @hide
819      */
translateFromScanResultToLocalChannelWidth( @ifiAnnotations.ChannelWidth int scanResultChannelWidth)820     static int translateFromScanResultToLocalChannelWidth(
821             @WifiAnnotations.ChannelWidth int scanResultChannelWidth) {
822         switch (scanResultChannelWidth) {
823             case ScanResult.CHANNEL_WIDTH_20MHZ:
824                 return CHANNEL_WIDTH_20MHZ;
825             case ScanResult.CHANNEL_WIDTH_40MHZ:
826                 return CHANNEL_WIDTH_40MHZ;
827             case ScanResult.CHANNEL_WIDTH_80MHZ:
828                 return CHANNEL_WIDTH_80MHZ;
829             case ScanResult.CHANNEL_WIDTH_160MHZ:
830                 return CHANNEL_WIDTH_160MHZ;
831             case ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
832                 return CHANNEL_WIDTH_80MHZ_PLUS_MHZ;
833             case ScanResult.CHANNEL_WIDTH_320MHZ:
834                 return CHANNEL_WIDTH_320MHZ;
835             default:
836                 throw new IllegalArgumentException(
837                         "translateFromScanResultChannelWidth: bad " + scanResultChannelWidth);
838         }
839     }
840 
841     /**
842      * Translate the local channel width encoding to the SDK channel width encoding.
843      *
844      * @param localChannelWidth the locally defined channel width encoding
845      * @return the translated channel width encoding
846      *
847      * @hide
848      */
translateFromLocalToScanResultChannelWidth(@hannelWidth int localChannelWidth)849     static int translateFromLocalToScanResultChannelWidth(@ChannelWidth int localChannelWidth) {
850         switch (localChannelWidth) {
851             case CHANNEL_WIDTH_20MHZ:
852                 return ScanResult.CHANNEL_WIDTH_20MHZ;
853             case CHANNEL_WIDTH_40MHZ:
854                 return ScanResult.CHANNEL_WIDTH_40MHZ;
855             case CHANNEL_WIDTH_80MHZ:
856                 return ScanResult.CHANNEL_WIDTH_80MHZ;
857             case CHANNEL_WIDTH_160MHZ:
858                 return ScanResult.CHANNEL_WIDTH_160MHZ;
859             case CHANNEL_WIDTH_80MHZ_PLUS_MHZ:
860                 return ScanResult.CHANNEL_WIDTH_80MHZ_PLUS_MHZ;
861             case CHANNEL_WIDTH_320MHZ:
862                 return ScanResult.CHANNEL_WIDTH_320MHZ;
863             default:
864                 throw new IllegalArgumentException(
865                         "translateFromLocalChannelWidth: bad " + localChannelWidth);
866         }
867     }
868 
869     /**
870      * Translate the {@link ScanResult} preamble encoding to the local preamble encoding.
871      *
872      * @param scanResultPreamble the channel width supplied
873      * @return the local encoding of the Preamble
874      *
875      * @hide
876      */
translateFromScanResultToLocalPreamble( @ifiAnnotations.PreambleType int scanResultPreamble)877     static int translateFromScanResultToLocalPreamble(
878             @WifiAnnotations.PreambleType int scanResultPreamble) {
879         switch (scanResultPreamble) {
880             case ScanResult.PREAMBLE_LEGACY:
881                 return PREAMBLE_LEGACY;
882             case ScanResult.PREAMBLE_HT:
883                 return PREAMBLE_HT;
884             case ScanResult.PREAMBLE_VHT:
885                 return PREAMBLE_VHT;
886             case ScanResult.PREAMBLE_HE:
887                 return PREAMBLE_HE;
888             case ScanResult.PREAMBLE_EHT:
889                 return PREAMBLE_EHT;
890             default:
891                 throw new IllegalArgumentException(
892                         "translateFromScanResultPreamble: bad " + scanResultPreamble);
893         }
894     }
895 
896     /**
897      * Translate the local preamble encoding to the {@link ScanResult} preamble encoding.
898      *
899      * @param localPreamble the local preamble encoding
900      * @return the {@link ScanResult} encoding of the Preamble
901      *
902      * @hide
903      */
translateFromLocalToScanResultPreamble(@reambleType int localPreamble)904     static int translateFromLocalToScanResultPreamble(@PreambleType int localPreamble) {
905         switch (localPreamble) {
906             case PREAMBLE_LEGACY:
907                 return ScanResult.PREAMBLE_LEGACY;
908             case PREAMBLE_HT:
909                 return ScanResult.PREAMBLE_HT;
910             case PREAMBLE_VHT:
911                 return ScanResult.PREAMBLE_VHT;
912             case PREAMBLE_HE:
913                 return ScanResult.PREAMBLE_HE;
914             case PREAMBLE_EHT:
915                 return ScanResult.PREAMBLE_EHT;
916             default:
917                 throw new IllegalArgumentException(
918                         "translateFromLocalPreamble: bad " + localPreamble);
919         }
920     }
921 }
922