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