• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2008 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;
18  
19  import android.annotation.IntDef;
20  import android.annotation.NonNull;
21  import android.annotation.SystemApi;
22  import android.annotation.UnsupportedAppUsage;
23  import android.content.pm.PackageManager;
24  import android.net.IpConfiguration;
25  import android.net.IpConfiguration.ProxySettings;
26  import android.net.MacAddress;
27  import android.net.NetworkSpecifier;
28  import android.net.ProxyInfo;
29  import android.net.StaticIpConfiguration;
30  import android.net.Uri;
31  import android.os.Build;
32  import android.os.Parcel;
33  import android.os.Parcelable;
34  import android.os.SystemClock;
35  import android.os.UserHandle;
36  import android.text.TextUtils;
37  import android.util.BackupUtils;
38  import android.util.Log;
39  import android.util.TimeUtils;
40  
41  import java.io.ByteArrayOutputStream;
42  import java.io.DataInputStream;
43  import java.io.DataOutputStream;
44  import java.io.IOException;
45  import java.lang.annotation.Retention;
46  import java.lang.annotation.RetentionPolicy;
47  import java.util.Arrays;
48  import java.util.BitSet;
49  import java.util.HashMap;
50  
51  /**
52   * A class representing a configured Wi-Fi network, including the
53   * security configuration.
54   *
55   * @deprecated Use {@link WifiNetworkSpecifier.Builder} to create {@link NetworkSpecifier} and
56   * {@link WifiNetworkSuggestion.Builder} to create {@link WifiNetworkSuggestion}. This will become a
57   * system use only object in the future.
58   */
59  @Deprecated
60  public class WifiConfiguration implements Parcelable {
61      private static final String TAG = "WifiConfiguration";
62      /**
63       * Current Version of the Backup Serializer.
64      */
65      private static final int BACKUP_VERSION = 3;
66      /** {@hide} */
67      public static final String ssidVarName = "ssid";
68      /** {@hide} */
69      public static final String bssidVarName = "bssid";
70      /** {@hide} */
71      public static final String pskVarName = "psk";
72      /** {@hide} */
73      @Deprecated
74      @UnsupportedAppUsage
75      public static final String[] wepKeyVarNames = { "wep_key0", "wep_key1", "wep_key2", "wep_key3" };
76      /** {@hide} */
77      @Deprecated
78      public static final String wepTxKeyIdxVarName = "wep_tx_keyidx";
79      /** {@hide} */
80      public static final String priorityVarName = "priority";
81      /** {@hide} */
82      public static final String hiddenSSIDVarName = "scan_ssid";
83      /** {@hide} */
84      public static final String pmfVarName = "ieee80211w";
85      /** {@hide} */
86      public static final String updateIdentiferVarName = "update_identifier";
87      /** {@hide} */
88      public static final int INVALID_NETWORK_ID = -1;
89      /** {@hide} */
90      public static final int LOCAL_ONLY_NETWORK_ID = -2;
91  
92      /** {@hide} */
93      private String mPasspointManagementObjectTree;
94      /** {@hide} */
95      private static final int MAXIMUM_RANDOM_MAC_GENERATION_RETRY = 3;
96  
97      /**
98       * Recognized key management schemes.
99       */
100      public static class KeyMgmt {
KeyMgmt()101          private KeyMgmt() { }
102  
103          /** WPA is not used; plaintext or static WEP could be used. */
104          public static final int NONE = 0;
105          /** WPA pre-shared key (requires {@code preSharedKey} to be specified). */
106          public static final int WPA_PSK = 1;
107          /** WPA using EAP authentication. Generally used with an external authentication server. */
108          public static final int WPA_EAP = 2;
109          /** IEEE 802.1X using EAP authentication and (optionally) dynamically
110           * generated WEP keys. */
111          public static final int IEEE8021X = 3;
112  
113          /** WPA2 pre-shared key for use with soft access point
114            * (requires {@code preSharedKey} to be specified).
115            * @hide
116            */
117          @SystemApi
118          public static final int WPA2_PSK = 4;
119          /**
120           * Hotspot 2.0 r2 OSEN:
121           * @hide
122           */
123          public static final int OSEN = 5;
124  
125          /**
126           * IEEE 802.11r Fast BSS Transition with PSK authentication.
127           * @hide
128           */
129          public static final int FT_PSK = 6;
130  
131          /**
132           * IEEE 802.11r Fast BSS Transition with EAP authentication.
133           * @hide
134           */
135          public static final int FT_EAP = 7;
136  
137          /**
138           * Simultaneous Authentication of Equals
139           */
140          public static final int SAE = 8;
141  
142          /**
143           * Opportunististic Wireless Encryption
144           */
145          public static final int OWE = 9;
146  
147          /**
148           * SUITE_B_192 192 bit level
149           */
150          public static final int SUITE_B_192 = 10;
151  
152          /**
153           * WPA pre-shared key with stronger SHA256-based algorithms.
154           * @hide
155           */
156          public static final int WPA_PSK_SHA256 = 11;
157  
158          /**
159           * WPA using EAP authentication with stronger SHA256-based algorithms.
160           * @hide
161           */
162          public static final int WPA_EAP_SHA256 = 12;
163  
164          public static final String varName = "key_mgmt";
165  
166          public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP",
167                  "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP",
168                  "SAE", "OWE", "SUITE_B_192", "WPA_PSK_SHA256", "WPA_EAP_SHA256" };
169      }
170  
171      /**
172       * Recognized security protocols.
173       */
174      public static class Protocol {
Protocol()175          private Protocol() { }
176  
177          /** WPA/IEEE 802.11i/D3.0
178           * @deprecated Due to security and performance limitations, use of WPA-1 networks
179           * is discouraged. WPA-2 (RSN) should be used instead. */
180          @Deprecated
181          public static final int WPA = 0;
182          /** RSN WPA2/WPA3/IEEE 802.11i */
183          public static final int RSN = 1;
184          /** HS2.0 r2 OSEN
185           * @hide
186           */
187          public static final int OSEN = 2;
188  
189          public static final String varName = "proto";
190  
191          public static final String[] strings = { "WPA", "RSN", "OSEN" };
192      }
193  
194      /**
195       * Recognized IEEE 802.11 authentication algorithms.
196       */
197      public static class AuthAlgorithm {
AuthAlgorithm()198          private AuthAlgorithm() { }
199  
200          /** Open System authentication (required for WPA/WPA2) */
201          public static final int OPEN = 0;
202          /** Shared Key authentication (requires static WEP keys)
203           * @deprecated Due to security and performance limitations, use of WEP networks
204           * is discouraged. */
205          @Deprecated
206          public static final int SHARED = 1;
207          /** LEAP/Network EAP (only used with LEAP) */
208          public static final int LEAP = 2;
209  
210          public static final String varName = "auth_alg";
211  
212          public static final String[] strings = { "OPEN", "SHARED", "LEAP" };
213      }
214  
215      /**
216       * Recognized pairwise ciphers for WPA.
217       */
218      public static class PairwiseCipher {
PairwiseCipher()219          private PairwiseCipher() { }
220  
221          /** Use only Group keys (deprecated) */
222          public static final int NONE = 0;
223          /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
224           * @deprecated Due to security and performance limitations, use of WPA-1 networks
225           * is discouraged. WPA-2 (RSN) should be used instead. */
226          @Deprecated
227          public static final int TKIP = 1;
228          /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
229          public static final int CCMP = 2;
230          /**
231           * AES in Galois/Counter Mode
232           */
233          public static final int GCMP_256 = 3;
234  
235          public static final String varName = "pairwise";
236  
237          public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256" };
238      }
239  
240      /**
241       * Recognized group ciphers.
242       * <pre>
243       * CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
244       * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
245       * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
246       * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
247       * GCMP_256 = AES in Galois/Counter Mode
248       * </pre>
249       */
250      public static class GroupCipher {
GroupCipher()251          private GroupCipher() { }
252  
253          /** WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11)
254           * @deprecated Due to security and performance limitations, use of WEP networks
255           * is discouraged. */
256          @Deprecated
257          public static final int WEP40 = 0;
258          /** WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
259           * @deprecated Due to security and performance limitations, use of WEP networks
260           * is discouraged. */
261          @Deprecated
262          public static final int WEP104 = 1;
263          /** Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] */
264          public static final int TKIP = 2;
265          /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */
266          public static final int CCMP = 3;
267          /** Hotspot 2.0 r2 OSEN
268           * @hide
269           */
270          public static final int GTK_NOT_USED = 4;
271          /**
272           * AES in Galois/Counter Mode
273           */
274          public static final int GCMP_256 = 5;
275  
276          public static final String varName = "group";
277  
278          public static final String[] strings =
279                  { /* deprecated */ "WEP40", /* deprecated */ "WEP104",
280                          "TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256" };
281      }
282  
283      /**
284       * Recognized group management ciphers.
285       * <pre>
286       * BIP_CMAC_256 = Cipher-based Message Authentication Code 256 bits
287       * BIP_GMAC_128 = Galois Message Authentication Code 128 bits
288       * BIP_GMAC_256 = Galois Message Authentication Code 256 bits
289       * </pre>
290       */
291      public static class GroupMgmtCipher {
GroupMgmtCipher()292          private GroupMgmtCipher() { }
293  
294          /** CMAC-256 = Cipher-based Message Authentication Code */
295          public static final int BIP_CMAC_256 = 0;
296  
297          /** GMAC-128 = Galois Message Authentication Code */
298          public static final int BIP_GMAC_128 = 1;
299  
300          /** GMAC-256 = Galois Message Authentication Code */
301          public static final int BIP_GMAC_256 = 2;
302  
303          private static final String varName = "groupMgmt";
304  
305          private static final String[] strings = { "BIP_CMAC_256",
306                  "BIP_GMAC_128", "BIP_GMAC_256"};
307      }
308  
309      /**
310       * Recognized suiteB ciphers.
311       * <pre>
312       * ECDHE_ECDSA
313       * ECDHE_RSA
314       * </pre>
315       * @hide
316       */
317      public static class SuiteBCipher {
SuiteBCipher()318          private SuiteBCipher() { }
319  
320          /** Diffie-Hellman with Elliptic Curve_ECDSA signature */
321          public static final int ECDHE_ECDSA = 0;
322  
323          /** Diffie-Hellman with_RSA signature */
324          public static final int ECDHE_RSA = 1;
325  
326          private static final String varName = "SuiteB";
327  
328          private static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" };
329      }
330  
331      /** Possible status of a network configuration. */
332      public static class Status {
Status()333          private Status() { }
334  
335          /** this is the network we are currently connected to */
336          public static final int CURRENT = 0;
337          /** supplicant will not attempt to use this network */
338          public static final int DISABLED = 1;
339          /** supplicant will consider this network available for association */
340          public static final int ENABLED = 2;
341  
342          public static final String[] strings = { "current", "disabled", "enabled" };
343      }
344  
345      /**
346       * Security types we support.
347       */
348      /** @hide */
349      public static final int SECURITY_TYPE_OPEN = 0;
350      /** @hide */
351      public static final int SECURITY_TYPE_WEP = 1;
352      /** @hide */
353      public static final int SECURITY_TYPE_PSK = 2;
354      /** @hide */
355      public static final int SECURITY_TYPE_EAP = 3;
356      /** @hide */
357      public static final int SECURITY_TYPE_SAE = 4;
358      /** @hide */
359      public static final int SECURITY_TYPE_EAP_SUITE_B = 5;
360      /** @hide */
361      public static final int SECURITY_TYPE_OWE = 6;
362  
363      /** @hide */
364      @Retention(RetentionPolicy.SOURCE)
365      @IntDef(prefix = { "SECURITY_TYPE_" }, value = {
366              SECURITY_TYPE_OPEN,
367              SECURITY_TYPE_WEP,
368              SECURITY_TYPE_PSK,
369              SECURITY_TYPE_EAP,
370              SECURITY_TYPE_SAE,
371              SECURITY_TYPE_EAP_SUITE_B,
372              SECURITY_TYPE_OWE
373      })
374      public @interface SecurityType {}
375  
376      /**
377       * @hide
378       * Set security params (sets the various bitsets exposed in WifiConfiguration).
379       *
380       * @param securityType One of the security types from {@link SecurityType}.
381       */
setSecurityParams(@ecurityType int securityType)382      public void setSecurityParams(@SecurityType int securityType) {
383          // Clear all the bitsets.
384          allowedKeyManagement.clear();
385          allowedProtocols.clear();
386          allowedAuthAlgorithms.clear();
387          allowedPairwiseCiphers.clear();
388          allowedGroupCiphers.clear();
389          allowedGroupManagementCiphers.clear();
390          allowedSuiteBCiphers.clear();
391  
392          switch (securityType) {
393              case SECURITY_TYPE_OPEN:
394                  allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
395                  break;
396              case SECURITY_TYPE_WEP:
397                  allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
398                  allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
399                  allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
400                  break;
401              case SECURITY_TYPE_PSK:
402                  allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
403                  break;
404              case SECURITY_TYPE_EAP:
405                  allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
406                  allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
407                  break;
408              case SECURITY_TYPE_SAE:
409                  allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE);
410                  requirePMF = true;
411                  break;
412              case SECURITY_TYPE_EAP_SUITE_B:
413                  allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
414                  allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
415                  allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256);
416                  // Note: allowedSuiteBCiphers bitset will be set by the service once the
417                  // certificates are attached to this profile
418                  requirePMF = true;
419                  break;
420              case SECURITY_TYPE_OWE:
421                  allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE);
422                  requirePMF = true;
423                  break;
424              default:
425                  throw new IllegalArgumentException("unknown security type " + securityType);
426          }
427      }
428  
429      /** @hide */
430      public static final int UNKNOWN_UID = -1;
431  
432      /**
433       * The ID number that the supplicant uses to identify this
434       * network configuration entry. This must be passed as an argument
435       * to most calls into the supplicant.
436       */
437      public int networkId;
438  
439      // Fixme We need remove this field to use only Quality network selection status only
440      /**
441       * The current status of this network configuration entry.
442       * @see Status
443       */
444      public int status;
445  
446      /**
447       * The network's SSID. Can either be a UTF-8 string,
448       * which must be enclosed in double quotation marks
449       * (e.g., {@code "MyNetwork"}), or a string of
450       * hex digits, which are not enclosed in quotes
451       * (e.g., {@code 01a243f405}).
452       */
453      public String SSID;
454  
455      /**
456       * When set, this network configuration entry should only be used when
457       * associating with the AP having the specified BSSID. The value is
458       * a string in the format of an Ethernet MAC address, e.g.,
459       * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit.
460       */
461      public String BSSID;
462  
463      /**
464       * 2GHz band.
465       * @hide
466       */
467      public static final int AP_BAND_2GHZ = 0;
468  
469      /**
470       * 5GHz band.
471       * @hide
472       */
473      public static final int AP_BAND_5GHZ = 1;
474  
475      /**
476       * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability,
477       * operating country code and current radio conditions.
478       * @hide
479       */
480      public static final int AP_BAND_ANY = -1;
481  
482      /**
483       * The band which AP resides on
484       * -1:Any 0:2G 1:5G
485       * By default, 2G is chosen
486       * @hide
487       */
488      @UnsupportedAppUsage
489      public int apBand = AP_BAND_2GHZ;
490  
491      /**
492       * The channel which AP resides on,currently, US only
493       * 2G  1-11
494       * 5G  36,40,44,48,149,153,157,161,165
495       * 0 - find a random available channel according to the apBand
496       * @hide
497       */
498      @UnsupportedAppUsage
499      public int apChannel = 0;
500  
501      /**
502       * Pre-shared key for use with WPA-PSK. Either an ASCII string enclosed in
503       * double quotation marks (e.g., {@code "abcdefghij"} for PSK passphrase or
504       * a string of 64 hex digits for raw PSK.
505       * <p/>
506       * When the value of this key is read, the actual key is
507       * not returned, just a "*" if the key has a value, or the null
508       * string otherwise.
509       */
510      public String preSharedKey;
511  
512      /**
513       * Four WEP keys. For each of the four values, provide either an ASCII
514       * string enclosed in double quotation marks (e.g., {@code "abcdef"}),
515       * a string of hex digits (e.g., {@code 0102030405}), or an empty string
516       * (e.g., {@code ""}).
517       * <p/>
518       * When the value of one of these keys is read, the actual key is
519       * not returned, just a "*" if the key has a value, or the null
520       * string otherwise.
521       * @deprecated Due to security and performance limitations, use of WEP networks
522       * is discouraged.
523       */
524      @Deprecated
525      public String[] wepKeys;
526  
527      /** Default WEP key index, ranging from 0 to 3.
528       * @deprecated Due to security and performance limitations, use of WEP networks
529       * is discouraged. */
530      @Deprecated
531      public int wepTxKeyIndex;
532  
533      /**
534       * Priority determines the preference given to a network by {@code wpa_supplicant}
535       * when choosing an access point with which to associate.
536       * @deprecated This field does not exist anymore.
537       */
538      @Deprecated
539      public int priority;
540  
541      /**
542       * This is a network that does not broadcast its SSID, so an
543       * SSID-specific probe request must be used for scans.
544       */
545      public boolean hiddenSSID;
546  
547      /**
548       * This is a network that requries Protected Management Frames (PMF).
549       * @hide
550       */
551      public boolean requirePMF;
552  
553      /**
554       * Update identifier, for Passpoint network.
555       * @hide
556       */
557      public String updateIdentifier;
558  
559      /**
560       * The set of key management protocols supported by this configuration.
561       * See {@link KeyMgmt} for descriptions of the values.
562       * Defaults to WPA-PSK WPA-EAP.
563       */
564      @NonNull
565      public BitSet allowedKeyManagement;
566      /**
567       * The set of security protocols supported by this configuration.
568       * See {@link Protocol} for descriptions of the values.
569       * Defaults to WPA RSN.
570       */
571      @NonNull
572      public BitSet allowedProtocols;
573      /**
574       * The set of authentication protocols supported by this configuration.
575       * See {@link AuthAlgorithm} for descriptions of the values.
576       * Defaults to automatic selection.
577       */
578      @NonNull
579      public BitSet allowedAuthAlgorithms;
580      /**
581       * The set of pairwise ciphers for WPA supported by this configuration.
582       * See {@link PairwiseCipher} for descriptions of the values.
583       * Defaults to CCMP TKIP.
584       */
585      @NonNull
586      public BitSet allowedPairwiseCiphers;
587      /**
588       * The set of group ciphers supported by this configuration.
589       * See {@link GroupCipher} for descriptions of the values.
590       * Defaults to CCMP TKIP WEP104 WEP40.
591       */
592      @NonNull
593      public BitSet allowedGroupCiphers;
594      /**
595       * The set of group management ciphers supported by this configuration.
596       * See {@link GroupMgmtCipher} for descriptions of the values.
597       */
598      @NonNull
599      public BitSet allowedGroupManagementCiphers;
600      /**
601       * The set of SuiteB ciphers supported by this configuration.
602       * To be used for WPA3-Enterprise mode.
603       * See {@link SuiteBCipher} for descriptions of the values.
604       */
605      @NonNull
606      public BitSet allowedSuiteBCiphers;
607      /**
608       * The enterprise configuration details specifying the EAP method,
609       * certificates and other settings associated with the EAP.
610       */
611      public WifiEnterpriseConfig enterpriseConfig;
612  
613      /**
614       * Fully qualified domain name of a Passpoint configuration
615       */
616      public String FQDN;
617  
618      /**
619       * Name of Passpoint credential provider
620       */
621      public String providerFriendlyName;
622  
623      /**
624       * Flag indicating if this network is provided by a home Passpoint provider or a roaming
625       * Passpoint provider.  This flag will be {@code true} if this network is provided by
626       * a home Passpoint provider and {@code false} if is provided by a roaming Passpoint provider
627       * or is a non-Passpoint network.
628       */
629      public boolean isHomeProviderNetwork;
630  
631      /**
632       * Roaming Consortium Id list for Passpoint credential; identifies a set of networks where
633       * Passpoint credential will be considered valid
634       */
635      public long[] roamingConsortiumIds;
636  
637      /**
638       * @hide
639       * This network configuration is visible to and usable by other users on the
640       * same device.
641       */
642      @UnsupportedAppUsage
643      public boolean shared;
644  
645      /**
646       * @hide
647       */
648      @NonNull
649      @UnsupportedAppUsage
650      private IpConfiguration mIpConfiguration;
651  
652      /**
653       * @hide
654       * dhcp server MAC address if known
655       */
656      public String dhcpServer;
657  
658      /**
659       * @hide
660       * default Gateway MAC address if known
661       */
662      @UnsupportedAppUsage
663      public String defaultGwMacAddress;
664  
665      /**
666       * @hide
667       * last time we connected, this configuration had validated internet access
668       */
669      @UnsupportedAppUsage
670      public boolean validatedInternetAccess;
671  
672      /**
673       * @hide
674       * The number of beacon intervals between Delivery Traffic Indication Maps (DTIM)
675       * This value is populated from scan results that contain Beacon Frames, which are infrequent.
676       * The value is not guaranteed to be set or current (Although it SHOULDNT change once set)
677       * Valid values are from 1 - 255. Initialized here as 0, use this to check if set.
678       */
679      public int dtimInterval = 0;
680  
681      /**
682       * Flag indicating if this configuration represents a legacy Passpoint configuration
683       * (Release N or older).  This is used for migrating Passpoint configuration from N to O.
684       * This will no longer be needed after O.
685       * @hide
686       */
687      public boolean isLegacyPasspointConfig = false;
688      /**
689       * @hide
690       * Uid of app creating the configuration
691       */
692      @SystemApi
693      public int creatorUid;
694  
695      /**
696       * @hide
697       * Uid of last app issuing a connection related command
698       */
699      @UnsupportedAppUsage
700      public int lastConnectUid;
701  
702      /**
703       * @hide
704       * Uid of last app modifying the configuration
705       */
706      @SystemApi
707      public int lastUpdateUid;
708  
709      /**
710       * @hide
711       * Universal name for app creating the configuration
712       *    see {@link PackageManager#getNameForUid(int)}
713       */
714      @SystemApi
715      public String creatorName;
716  
717      /**
718       * @hide
719       * Universal name for app updating the configuration
720       *    see {@link PackageManager#getNameForUid(int)}
721       */
722      @SystemApi
723      public String lastUpdateName;
724  
725      /**
726       * @hide
727       * Status of user approval for connection
728       */
729      public int userApproved = USER_UNSPECIFIED;
730  
731      /** The Below RSSI thresholds are used to configure AutoJoin
732       *  - GOOD/LOW/BAD thresholds are used so as to calculate link score
733       *  - UNWANTED_SOFT are used by the blacklisting logic so as to handle
734       *  the unwanted network message coming from CS
735       *  - UNBLACKLIST thresholds are used so as to tweak the speed at which
736       *  the network is unblacklisted (i.e. if
737       *          it is seen with good RSSI, it is blacklisted faster)
738       *  - INITIAL_AUTOJOIN_ATTEMPT, used to determine how close from
739       *  the network we need to be before autojoin kicks in
740       */
741      /** @hide **/
742      @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
743      public static int INVALID_RSSI = -127;
744  
745      // States for the userApproved field
746      /**
747       * @hide
748       * User hasn't specified if connection is okay
749       */
750      public static final int USER_UNSPECIFIED = 0;
751      /**
752       * @hide
753       * User has approved this for connection
754       */
755      public static final int USER_APPROVED = 1;
756      /**
757       * @hide
758       * User has banned this from connection
759       */
760      public static final int USER_BANNED = 2;
761      /**
762       * @hide
763       * Waiting for user input
764       */
765      public static final int USER_PENDING = 3;
766  
767      /**
768       * @hide
769       * Number of reports indicating no Internet Access
770       */
771      @UnsupportedAppUsage
772      public int numNoInternetAccessReports;
773  
774      /**
775       * @hide
776       * For debug: date at which the config was last updated
777       */
778      public String updateTime;
779  
780      /**
781       * @hide
782       * For debug: date at which the config was last updated
783       */
784      public String creationTime;
785  
786      /**
787       * @hide
788       * The WiFi configuration is considered to have no internet access for purpose of autojoining
789       * if there has been a report of it having no internet access, and, it never have had
790       * internet access in the past.
791       */
792      @SystemApi
hasNoInternetAccess()793      public boolean hasNoInternetAccess() {
794          return numNoInternetAccessReports > 0 && !validatedInternetAccess;
795      }
796  
797      /**
798       * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a
799       * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to
800       * this configuration and selects "don't ask again".
801       * @hide
802       */
803      @UnsupportedAppUsage
804      public boolean noInternetAccessExpected;
805  
806      /**
807       * The WiFi configuration is expected not to have Internet access (e.g., a wireless printer, a
808       * Chromecast hotspot, etc.). This will be set if the user explicitly confirms a connection to
809       * this configuration and selects "don't ask again".
810       * @hide
811       */
812      @SystemApi
isNoInternetAccessExpected()813      public boolean isNoInternetAccessExpected() {
814          return noInternetAccessExpected;
815      }
816  
817      /**
818       * This Wifi configuration is expected for OSU(Online Sign Up) of Passpoint Release 2.
819       * @hide
820       */
821      public boolean osu;
822  
823      /**
824       * @hide
825       * Last time the system was connected to this configuration.
826       */
827      public long lastConnected;
828  
829      /**
830       * @hide
831       * Last time the system was disconnected to this configuration.
832       */
833      public long lastDisconnected;
834  
835      /**
836       * Set if the configuration was self added by the framework
837       * This boolean is cleared if we get a connect/save/ update or
838       * any wifiManager command that indicate the user interacted with the configuration
839       * since we will now consider that the configuration belong to him.
840       * @hide
841       */
842      @UnsupportedAppUsage
843      public boolean selfAdded;
844  
845      /**
846       * Set if the configuration was self added by the framework
847       * This boolean is set once and never cleared. It is used
848       * so as we never loose track of who created the
849       * configuration in the first place.
850       * @hide
851       */
852      public boolean didSelfAdd;
853  
854      /**
855       * Peer WifiConfiguration this WifiConfiguration was added for
856       * @hide
857       */
858      public String peerWifiConfiguration;
859  
860      /**
861       * @hide
862       * Indicate that a WifiConfiguration is temporary and should not be saved
863       * nor considered by AutoJoin.
864       */
865      public boolean ephemeral;
866  
867      /**
868       * @hide
869       * Indicate that a WifiConfiguration is temporary and should not be saved
870       * nor considered by AutoJoin.
871       */
872      @SystemApi
isEphemeral()873      public boolean isEphemeral() {
874        return ephemeral;
875      }
876  
877      /**
878       * Indicate whther the network is trusted or not. Networks are considered trusted
879       * if the user explicitly allowed this network connection.
880       * @hide
881       */
882      public boolean trusted;
883  
884      /**
885       * This Wifi configuration is created from a {@link WifiNetworkSuggestion}
886       * @hide
887       */
888      public boolean fromWifiNetworkSuggestion;
889  
890      /**
891       * This Wifi configuration is created from a {@link WifiNetworkSpecifier}
892       * @hide
893       */
894      public boolean fromWifiNetworkSpecifier;
895  
896      /**
897       * Indicates if the creator of this configuration has expressed that it
898       * should be considered metered.
899       *
900       * @see #isMetered(WifiConfiguration, WifiInfo)
901       * @hide
902       */
903      @SystemApi
904      public boolean meteredHint;
905  
906      /** {@hide} */
907      public static final int METERED_OVERRIDE_NONE = 0;
908      /** {@hide} */
909      public static final int METERED_OVERRIDE_METERED = 1;
910      /** {@hide} */
911      public static final int METERED_OVERRIDE_NOT_METERED = 2;
912  
913      /**
914       * Indicates if the end user has expressed an explicit opinion about the
915       * meteredness of this network, such as through the Settings app.
916       * <p>
917       * This should always override any values from {@link #meteredHint} or
918       * {@link WifiInfo#getMeteredHint()}.
919       *
920       * @see #isMetered(WifiConfiguration, WifiInfo)
921       * @hide
922       */
923      public int meteredOverride = METERED_OVERRIDE_NONE;
924  
925      /**
926       * Blend together all the various opinions to decide if the given network
927       * should be considered metered or not.
928       *
929       * @hide
930       */
isMetered(WifiConfiguration config, WifiInfo info)931      public static boolean isMetered(WifiConfiguration config, WifiInfo info) {
932          boolean metered = false;
933          if (info != null && info.getMeteredHint()) {
934              metered = true;
935          }
936          if (config != null && config.meteredHint) {
937              metered = true;
938          }
939          if (config != null
940                  && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) {
941              metered = true;
942          }
943          if (config != null
944                  && config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_NOT_METERED) {
945              metered = false;
946          }
947          return metered;
948      }
949  
950      /**
951       * @hide
952       * Returns true if this WiFi config is for an open network.
953       */
isOpenNetwork()954      public boolean isOpenNetwork() {
955          final int cardinality = allowedKeyManagement.cardinality();
956          final boolean hasNoKeyMgmt = cardinality == 0
957                  || (cardinality == 1 && (allowedKeyManagement.get(KeyMgmt.NONE)
958                  || allowedKeyManagement.get(KeyMgmt.OWE)));
959  
960          boolean hasNoWepKeys = true;
961          if (wepKeys != null) {
962              for (int i = 0; i < wepKeys.length; i++) {
963                  if (wepKeys[i] != null) {
964                      hasNoWepKeys = false;
965                      break;
966                  }
967              }
968          }
969  
970          return hasNoKeyMgmt && hasNoWepKeys;
971      }
972  
973      /**
974       * @hide
975       * Setting this value will force scan results associated with this configuration to
976       * be included in the bucket of networks that are externally scored.
977       * If not set, associated scan results will be treated as legacy saved networks and
978       * will take precedence over networks in the scored category.
979       */
980      @SystemApi
981      public boolean useExternalScores;
982  
983      /**
984       * @hide
985       * Number of time the scorer overrode a the priority based choice, when comparing two
986       * WifiConfigurations, note that since comparing WifiConfiguration happens very often
987       * potentially at every scan, this number might become very large, even on an idle
988       * system.
989       */
990      @SystemApi
991      public int numScorerOverride;
992  
993      /**
994       * @hide
995       * Number of time the scorer overrode a the priority based choice, and the comparison
996       * triggered a network switch
997       */
998      @SystemApi
999      public int numScorerOverrideAndSwitchedNetwork;
1000  
1001      /**
1002       * @hide
1003       * Number of time we associated to this configuration.
1004       */
1005      @SystemApi
1006      public int numAssociation;
1007  
1008      /**
1009       * @hide
1010       * Use factory MAC when connecting to this network
1011       */
1012      public static final int RANDOMIZATION_NONE = 0;
1013      /**
1014       * @hide
1015       * Generate a randomized MAC once and reuse it for all connections to this network
1016       */
1017      public static final int RANDOMIZATION_PERSISTENT = 1;
1018  
1019      /**
1020       * @hide
1021       * Level of MAC randomization for this network
1022       */
1023      public int macRandomizationSetting = RANDOMIZATION_PERSISTENT;
1024  
1025      /**
1026       * @hide
1027       * Randomized MAC address to use with this particular network
1028       */
1029      @NonNull
1030      private MacAddress mRandomizedMacAddress;
1031  
1032      /**
1033       * @hide
1034       * Checks if the given MAC address can be used for Connected Mac Randomization
1035       * by verifying that it is non-null, unicast, locally assigned, and not default mac.
1036       * @param mac MacAddress to check
1037       * @return true if mac is good to use
1038       */
isValidMacAddressForRandomization(MacAddress mac)1039      public static boolean isValidMacAddressForRandomization(MacAddress mac) {
1040          return mac != null && !mac.isMulticastAddress() && mac.isLocallyAssigned()
1041                  && !MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS).equals(mac);
1042      }
1043  
1044      /**
1045       * @hide
1046       * Returns Randomized MAC address to use with the network.
1047       * If it is not set/valid, creates a new randomized address.
1048       * If it can't generate a valid mac, returns the default MAC.
1049       */
getOrCreateRandomizedMacAddress()1050      public @NonNull MacAddress getOrCreateRandomizedMacAddress() {
1051          int randomMacGenerationCount = 0;
1052          while (!isValidMacAddressForRandomization(mRandomizedMacAddress)
1053                  && randomMacGenerationCount < MAXIMUM_RANDOM_MAC_GENERATION_RETRY) {
1054              mRandomizedMacAddress = MacAddress.createRandomUnicastAddress();
1055              randomMacGenerationCount++;
1056          }
1057  
1058          if (!isValidMacAddressForRandomization(mRandomizedMacAddress)) {
1059              mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS);
1060          }
1061          return mRandomizedMacAddress;
1062      }
1063  
1064      /**
1065       * Returns MAC address set to be the local randomized MAC address.
1066       * Depending on user preference, the device may or may not use the returned MAC address for
1067       * connections to this network.
1068       * <p>
1069       * Information is restricted to Device Owner, Profile Owner, and Carrier apps
1070       * (which will only obtain addresses for configurations which they create). Other callers
1071       * will receive a default "02:00:00:00:00:00" MAC address.
1072       */
getRandomizedMacAddress()1073      public @NonNull MacAddress getRandomizedMacAddress() {
1074          return mRandomizedMacAddress;
1075      }
1076  
1077      /**
1078       * @hide
1079       * @param mac MacAddress to change into
1080       */
setRandomizedMacAddress(@onNull MacAddress mac)1081      public void setRandomizedMacAddress(@NonNull MacAddress mac) {
1082          if (mac == null) {
1083              Log.e(TAG, "setRandomizedMacAddress received null MacAddress.");
1084              return;
1085          }
1086          mRandomizedMacAddress = mac;
1087      }
1088  
1089      /** @hide
1090       * Boost given to RSSI on a home network for the purpose of calculating the score
1091       * This adds stickiness to home networks, as defined by:
1092       * - less than 4 known BSSIDs
1093       * - PSK only
1094       * - TODO: add a test to verify that all BSSIDs are behind same gateway
1095       ***/
1096      public static final int HOME_NETWORK_RSSI_BOOST = 5;
1097  
1098      /**
1099       * @hide
1100       * This class is used to contain all the information and API used for quality network selection
1101       */
1102      public static class NetworkSelectionStatus {
1103          /**
1104           * Quality Network Selection Status enable, temporary disabled, permanently disabled
1105           */
1106          /**
1107           * This network is allowed to join Quality Network Selection
1108           */
1109          public static final int NETWORK_SELECTION_ENABLED = 0;
1110          /**
1111           * network was temporary disabled. Can be re-enabled after a time period expire
1112           */
1113          public static final int NETWORK_SELECTION_TEMPORARY_DISABLED  = 1;
1114          /**
1115           * network was permanently disabled.
1116           */
1117          public static final int NETWORK_SELECTION_PERMANENTLY_DISABLED  = 2;
1118          /**
1119           * Maximum Network selection status
1120           */
1121          public static final int NETWORK_SELECTION_STATUS_MAX = 3;
1122  
1123          /**
1124           * Quality network selection status String (for debug purpose). Use Quality network
1125           * selection status value as index to extec the corresponding debug string
1126           */
1127          public static final String[] QUALITY_NETWORK_SELECTION_STATUS = {
1128                  "NETWORK_SELECTION_ENABLED",
1129                  "NETWORK_SELECTION_TEMPORARY_DISABLED",
1130                  "NETWORK_SELECTION_PERMANENTLY_DISABLED"};
1131  
1132          //Quality Network disabled reasons
1133          /**
1134           * Default value. Means not disabled
1135           */
1136          public static final int NETWORK_SELECTION_ENABLE = 0;
1137          /**
1138           * The starting index for network selection disabled reasons
1139           */
1140          public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1;
1141          /**
1142           * @deprecated it is not used any more.
1143           * This network is disabled because higher layer (>2) network is bad
1144           */
1145          public static final int DISABLED_BAD_LINK = 1;
1146          /**
1147           * This network is disabled because multiple association rejects
1148           */
1149          public static final int DISABLED_ASSOCIATION_REJECTION = 2;
1150          /**
1151           * This network is disabled because multiple authentication failure
1152           */
1153          public static final int DISABLED_AUTHENTICATION_FAILURE = 3;
1154          /**
1155           * This network is disabled because multiple DHCP failure
1156           */
1157          public static final int DISABLED_DHCP_FAILURE = 4;
1158          /**
1159           * This network is disabled because of security network but no credentials
1160           */
1161          public static final int DISABLED_DNS_FAILURE = 5;
1162          /**
1163           * This network is temporarily disabled because it has no Internet access.
1164           */
1165          public static final int DISABLED_NO_INTERNET_TEMPORARY = 6;
1166          /**
1167           * This network is disabled because we started WPS
1168           */
1169          public static final int DISABLED_WPS_START = 7;
1170          /**
1171           * This network is disabled because EAP-TLS failure
1172           */
1173          public static final int DISABLED_TLS_VERSION_MISMATCH = 8;
1174          // Values above are for temporary disablement; values below are for permanent disablement.
1175          /**
1176           * This network is disabled due to absence of user credentials
1177           */
1178          public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 9;
1179          /**
1180           * This network is permanently disabled because it has no Internet access and user does not
1181           * want to stay connected.
1182           */
1183          public static final int DISABLED_NO_INTERNET_PERMANENT = 10;
1184          /**
1185           * This network is disabled due to WifiManager disable it explicitly
1186           */
1187          public static final int DISABLED_BY_WIFI_MANAGER = 11;
1188          /**
1189           * This network is disabled due to user switching
1190           */
1191          public static final int DISABLED_DUE_TO_USER_SWITCH = 12;
1192          /**
1193           * This network is disabled due to wrong password
1194           */
1195          public static final int DISABLED_BY_WRONG_PASSWORD = 13;
1196          /**
1197           * This network is disabled because service is not subscribed
1198           */
1199          public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 14;
1200          /**
1201           * This Maximum disable reason value
1202           */
1203          public static final int NETWORK_SELECTION_DISABLED_MAX = 15;
1204  
1205          /**
1206           * Quality network selection disable reason String (for debug purpose)
1207           */
1208          public static final String[] QUALITY_NETWORK_SELECTION_DISABLE_REASON = {
1209                  "NETWORK_SELECTION_ENABLE",
1210                  "NETWORK_SELECTION_DISABLED_BAD_LINK", // deprecated
1211                  "NETWORK_SELECTION_DISABLED_ASSOCIATION_REJECTION ",
1212                  "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE",
1213                  "NETWORK_SELECTION_DISABLED_DHCP_FAILURE",
1214                  "NETWORK_SELECTION_DISABLED_DNS_FAILURE",
1215                  "NETWORK_SELECTION_DISABLED_NO_INTERNET_TEMPORARY",
1216                  "NETWORK_SELECTION_DISABLED_WPS_START",
1217                  "NETWORK_SELECTION_DISABLED_TLS_VERSION",
1218                  "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_CREDENTIALS",
1219                  "NETWORK_SELECTION_DISABLED_NO_INTERNET_PERMANENT",
1220                  "NETWORK_SELECTION_DISABLED_BY_WIFI_MANAGER",
1221                  "NETWORK_SELECTION_DISABLED_BY_USER_SWITCH",
1222                  "NETWORK_SELECTION_DISABLED_BY_WRONG_PASSWORD",
1223                  "NETWORK_SELECTION_DISABLED_AUTHENTICATION_NO_SUBSCRIPTION"
1224          };
1225  
1226          /**
1227           * Invalid time stamp for network selection disable
1228           */
1229          public static final long INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP = -1L;
1230  
1231          /**
1232           *  This constant indicates the current configuration has connect choice set
1233           */
1234          private static final int CONNECT_CHOICE_EXISTS = 1;
1235  
1236          /**
1237           *  This constant indicates the current configuration does not have connect choice set
1238           */
1239          private static final int CONNECT_CHOICE_NOT_EXISTS = -1;
1240  
1241          // fields for QualityNetwork Selection
1242          /**
1243           * Network selection status, should be in one of three status: enable, temporaily disabled
1244           * or permanently disabled
1245           */
1246          private int mStatus;
1247  
1248          /**
1249           * Reason for disable this network
1250           */
1251          private int mNetworkSelectionDisableReason;
1252  
1253          /**
1254           * Last time we temporarily disabled the configuration
1255           */
1256          private long mTemporarilyDisabledTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP;
1257  
1258          /**
1259           * counter for each Network selection disable reason
1260           */
1261          private int[] mNetworkSeclectionDisableCounter = new int[NETWORK_SELECTION_DISABLED_MAX];
1262  
1263          /**
1264           * Connect Choice over this configuration
1265           *
1266           * When current wifi configuration is visible to the user but user explicitly choose to
1267           * connect to another network X, the another networks X's configure key will be stored here.
1268           * We will consider user has a preference of X over this network. And in the future,
1269           * network selection will always give X a higher preference over this configuration.
1270           * configKey is : "SSID"-WEP-WPA_PSK-WPA_EAP
1271           */
1272          private String mConnectChoice;
1273  
1274          /**
1275           * The system timestamp when we records the connectChoice. This value is obtained from
1276           * System.currentTimeMillis
1277           */
1278          private long mConnectChoiceTimestamp = INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP;
1279  
1280          /**
1281           * Used to cache the temporary candidate during the network selection procedure. It will be
1282           * kept updating once a new scan result has a higher score than current one
1283           */
1284          private ScanResult mCandidate;
1285  
1286          /**
1287           * Used to cache the score of the current temporary candidate during the network
1288           * selection procedure.
1289           */
1290          private int mCandidateScore;
1291  
1292          /**
1293           * Indicate whether this network is visible in latest Qualified Network Selection. This
1294           * means there is scan result found related to this Configuration and meet the minimum
1295           * requirement. The saved network need not join latest Qualified Network Selection. For
1296           * example, it is disabled. True means network is visible in latest Qualified Network
1297           * Selection and false means network is invisible
1298           */
1299          private boolean mSeenInLastQualifiedNetworkSelection;
1300  
1301          /**
1302           * Boolean indicating if we have ever successfully connected to this network.
1303           *
1304           * This value will be set to true upon a successful connection.
1305           * This value will be set to false if a previous value was not stored in the config or if
1306           * the credentials are updated (ex. a password change).
1307           */
1308          private boolean mHasEverConnected;
1309  
1310          /**
1311           * Boolean indicating whether {@link com.android.server.wifi.RecommendedNetworkEvaluator}
1312           * chose not to connect to this network in the last qualified network selection process.
1313           */
1314          private boolean mNotRecommended;
1315  
1316          /**
1317           * Set whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} does not
1318           * recommend connecting to this network.
1319           */
setNotRecommended(boolean notRecommended)1320          public void setNotRecommended(boolean notRecommended) {
1321              mNotRecommended = notRecommended;
1322          }
1323  
1324          /**
1325           * Returns whether {@link com.android.server.wifi.RecommendedNetworkEvaluator} does not
1326           * recommend connecting to this network.
1327           */
isNotRecommended()1328          public boolean isNotRecommended() {
1329              return mNotRecommended;
1330          }
1331  
1332          /**
1333           * set whether this network is visible in latest Qualified Network Selection
1334           * @param seen value set to candidate
1335           */
setSeenInLastQualifiedNetworkSelection(boolean seen)1336          public void setSeenInLastQualifiedNetworkSelection(boolean seen) {
1337              mSeenInLastQualifiedNetworkSelection =  seen;
1338          }
1339  
1340          /**
1341           * get whether this network is visible in latest Qualified Network Selection
1342           * @return returns true -- network is visible in latest Qualified Network Selection
1343           *         false -- network is invisible in latest Qualified Network Selection
1344           */
getSeenInLastQualifiedNetworkSelection()1345          public boolean getSeenInLastQualifiedNetworkSelection() {
1346              return mSeenInLastQualifiedNetworkSelection;
1347          }
1348          /**
1349           * set the temporary candidate of current network selection procedure
1350           * @param scanCandidate {@link ScanResult} the candidate set to mCandidate
1351           */
setCandidate(ScanResult scanCandidate)1352          public void setCandidate(ScanResult scanCandidate) {
1353              mCandidate = scanCandidate;
1354          }
1355  
1356          /**
1357           * get the temporary candidate of current network selection procedure
1358           * @return  returns {@link ScanResult} temporary candidate of current network selection
1359           * procedure
1360           */
getCandidate()1361          public ScanResult getCandidate() {
1362              return mCandidate;
1363          }
1364  
1365          /**
1366           * set the score of the temporary candidate of current network selection procedure
1367           * @param score value set to mCandidateScore
1368           */
setCandidateScore(int score)1369          public void setCandidateScore(int score) {
1370              mCandidateScore = score;
1371          }
1372  
1373          /**
1374           * get the score of the temporary candidate of current network selection procedure
1375           * @return returns score of the temporary candidate of current network selection procedure
1376           */
getCandidateScore()1377          public int getCandidateScore() {
1378              return mCandidateScore;
1379          }
1380  
1381          /**
1382           * get user preferred choice over this configuration
1383           *@return returns configKey of user preferred choice over this configuration
1384           */
getConnectChoice()1385          public String getConnectChoice() {
1386              return mConnectChoice;
1387          }
1388  
1389          /**
1390           * set user preferred choice over this configuration
1391           * @param newConnectChoice, the configKey of user preferred choice over this configuration
1392           */
setConnectChoice(String newConnectChoice)1393          public void setConnectChoice(String newConnectChoice) {
1394              mConnectChoice = newConnectChoice;
1395          }
1396  
1397          /**
1398           * get the timeStamp when user select a choice over this configuration
1399           * @return returns when current connectChoice is set (time from System.currentTimeMillis)
1400           */
getConnectChoiceTimestamp()1401          public long getConnectChoiceTimestamp() {
1402              return mConnectChoiceTimestamp;
1403          }
1404  
1405          /**
1406           * set the timeStamp when user select a choice over this configuration
1407           * @param timeStamp, the timestamp set to connectChoiceTimestamp, expected timestamp should
1408           *        be obtained from System.currentTimeMillis
1409           */
setConnectChoiceTimestamp(long timeStamp)1410          public void setConnectChoiceTimestamp(long timeStamp) {
1411              mConnectChoiceTimestamp = timeStamp;
1412          }
1413  
1414          /**
1415           * get current Quality network selection status
1416           * @return returns current Quality network selection status in String (for debug purpose)
1417           */
getNetworkStatusString()1418          public String getNetworkStatusString() {
1419              return QUALITY_NETWORK_SELECTION_STATUS[mStatus];
1420          }
1421  
setHasEverConnected(boolean value)1422          public void setHasEverConnected(boolean value) {
1423              mHasEverConnected = value;
1424          }
1425  
getHasEverConnected()1426          public boolean getHasEverConnected() {
1427              return mHasEverConnected;
1428          }
1429  
NetworkSelectionStatus()1430          public NetworkSelectionStatus() {
1431              // previously stored configs will not have this parameter, so we default to false.
1432              mHasEverConnected = false;
1433          };
1434  
1435          /**
1436           * @param reason specific error reason
1437           * @return  corresponding network disable reason String (for debug purpose)
1438           */
getNetworkDisableReasonString(int reason)1439          public static String getNetworkDisableReasonString(int reason) {
1440              if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) {
1441                  return QUALITY_NETWORK_SELECTION_DISABLE_REASON[reason];
1442              } else {
1443                  return null;
1444              }
1445          }
1446          /**
1447           * get current network disable reason
1448           * @return current network disable reason in String (for debug purpose)
1449           */
getNetworkDisableReasonString()1450          public String getNetworkDisableReasonString() {
1451              return QUALITY_NETWORK_SELECTION_DISABLE_REASON[mNetworkSelectionDisableReason];
1452          }
1453  
1454          /**
1455           * get current network network selection status
1456           * @return return current network network selection status
1457           */
getNetworkSelectionStatus()1458          public int getNetworkSelectionStatus() {
1459              return mStatus;
1460          }
1461          /**
1462           * @return whether current network is enabled to join network selection
1463           */
isNetworkEnabled()1464          public boolean isNetworkEnabled() {
1465              return mStatus == NETWORK_SELECTION_ENABLED;
1466          }
1467  
1468          /**
1469           * @return whether current network is temporary disabled
1470           */
isNetworkTemporaryDisabled()1471          public boolean isNetworkTemporaryDisabled() {
1472              return mStatus == NETWORK_SELECTION_TEMPORARY_DISABLED;
1473          }
1474  
1475          /**
1476           * @return returns whether current network is permanently disabled
1477           */
isNetworkPermanentlyDisabled()1478          public boolean isNetworkPermanentlyDisabled() {
1479              return mStatus == NETWORK_SELECTION_PERMANENTLY_DISABLED;
1480          }
1481  
1482          /**
1483           * set current networ work selection status
1484           * @param status network selection status to set
1485           */
setNetworkSelectionStatus(int status)1486          public void setNetworkSelectionStatus(int status) {
1487              if (status >= 0 && status < NETWORK_SELECTION_STATUS_MAX) {
1488                  mStatus = status;
1489              }
1490          }
1491  
1492          /**
1493           * @return returns current network's disable reason
1494           */
getNetworkSelectionDisableReason()1495          public int getNetworkSelectionDisableReason() {
1496              return mNetworkSelectionDisableReason;
1497          }
1498  
1499          /**
1500           * set Network disable reason
1501           * @param  reason Network disable reason
1502           */
setNetworkSelectionDisableReason(int reason)1503          public void setNetworkSelectionDisableReason(int reason) {
1504              if (reason >= 0 && reason < NETWORK_SELECTION_DISABLED_MAX) {
1505                  mNetworkSelectionDisableReason = reason;
1506              } else {
1507                  throw new IllegalArgumentException("Illegal reason value: " + reason);
1508              }
1509          }
1510  
1511          /**
1512           * check whether network is disabled by this reason
1513           * @param reason a specific disable reason
1514           * @return true -- network is disabled for this reason
1515           *         false -- network is not disabled for this reason
1516           */
isDisabledByReason(int reason)1517          public boolean isDisabledByReason(int reason) {
1518              return mNetworkSelectionDisableReason == reason;
1519          }
1520  
1521          /**
1522           * @param timeStamp Set when current network is disabled in millisecond since January 1,
1523           * 1970 00:00:00.0 UTC
1524           */
setDisableTime(long timeStamp)1525          public void setDisableTime(long timeStamp) {
1526              mTemporarilyDisabledTimestamp = timeStamp;
1527          }
1528  
1529          /**
1530           * @return returns when current network is disabled in millisecond since January 1,
1531           * 1970 00:00:00.0 UTC
1532           */
getDisableTime()1533          public long getDisableTime() {
1534              return mTemporarilyDisabledTimestamp;
1535          }
1536  
1537          /**
1538           * get the disable counter of a specific reason
1539           * @param  reason specific failure reason
1540           * @exception throw IllegalArgumentException for illegal input
1541           * @return counter number for specific error reason.
1542           */
getDisableReasonCounter(int reason)1543          public int getDisableReasonCounter(int reason) {
1544              if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) {
1545                  return mNetworkSeclectionDisableCounter[reason];
1546              } else {
1547                  throw new IllegalArgumentException("Illegal reason value: " + reason);
1548              }
1549          }
1550  
1551          /**
1552           * set the counter of a specific failure reason
1553           * @param reason reason for disable error
1554           * @param value the counter value for this specific reason
1555           * @exception throw IllegalArgumentException for illegal input
1556           */
setDisableReasonCounter(int reason, int value)1557          public void setDisableReasonCounter(int reason, int value) {
1558              if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) {
1559                  mNetworkSeclectionDisableCounter[reason] = value;
1560              } else {
1561                  throw new IllegalArgumentException("Illegal reason value: " + reason);
1562              }
1563          }
1564  
1565          /**
1566           * increment the counter of a specific failure reason
1567           * @param reason a specific failure reason
1568           * @exception throw IllegalArgumentException for illegal input
1569           */
incrementDisableReasonCounter(int reason)1570          public void incrementDisableReasonCounter(int reason) {
1571              if (reason >= NETWORK_SELECTION_ENABLE  && reason < NETWORK_SELECTION_DISABLED_MAX) {
1572                  mNetworkSeclectionDisableCounter[reason]++;
1573              } else {
1574                  throw new IllegalArgumentException("Illegal reason value: " + reason);
1575              }
1576          }
1577  
1578          /**
1579           * clear the counter of a specific failure reason
1580           * @hide
1581           * @param reason a specific failure reason
1582           * @exception throw IllegalArgumentException for illegal input
1583           */
clearDisableReasonCounter(int reason)1584          public void clearDisableReasonCounter(int reason) {
1585              if (reason >= NETWORK_SELECTION_ENABLE && reason < NETWORK_SELECTION_DISABLED_MAX) {
1586                  mNetworkSeclectionDisableCounter[reason] = NETWORK_SELECTION_ENABLE;
1587              } else {
1588                  throw new IllegalArgumentException("Illegal reason value: " + reason);
1589              }
1590          }
1591  
1592          /**
1593           * clear all the failure reason counters
1594           */
clearDisableReasonCounter()1595          public void clearDisableReasonCounter() {
1596              Arrays.fill(mNetworkSeclectionDisableCounter, NETWORK_SELECTION_ENABLE);
1597          }
1598  
1599          /**
1600           * BSSID for connection to this network (through network selection procedure)
1601           */
1602          private String mNetworkSelectionBSSID;
1603  
1604          /**
1605           * get current network Selection BSSID
1606           * @return current network Selection BSSID
1607           */
getNetworkSelectionBSSID()1608          public String getNetworkSelectionBSSID() {
1609              return mNetworkSelectionBSSID;
1610          }
1611  
1612          /**
1613           * set network Selection BSSID
1614           * @param bssid The target BSSID for assocaition
1615           */
setNetworkSelectionBSSID(String bssid)1616          public void setNetworkSelectionBSSID(String bssid) {
1617              mNetworkSelectionBSSID = bssid;
1618          }
1619  
copy(NetworkSelectionStatus source)1620          public void copy(NetworkSelectionStatus source) {
1621              mStatus = source.mStatus;
1622              mNetworkSelectionDisableReason = source.mNetworkSelectionDisableReason;
1623              for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX;
1624                      index++) {
1625                  mNetworkSeclectionDisableCounter[index] =
1626                          source.mNetworkSeclectionDisableCounter[index];
1627              }
1628              mTemporarilyDisabledTimestamp = source.mTemporarilyDisabledTimestamp;
1629              mNetworkSelectionBSSID = source.mNetworkSelectionBSSID;
1630              setSeenInLastQualifiedNetworkSelection(source.getSeenInLastQualifiedNetworkSelection());
1631              setCandidate(source.getCandidate());
1632              setCandidateScore(source.getCandidateScore());
1633              setConnectChoice(source.getConnectChoice());
1634              setConnectChoiceTimestamp(source.getConnectChoiceTimestamp());
1635              setHasEverConnected(source.getHasEverConnected());
1636              setNotRecommended(source.isNotRecommended());
1637          }
1638  
writeToParcel(Parcel dest)1639          public void writeToParcel(Parcel dest) {
1640              dest.writeInt(getNetworkSelectionStatus());
1641              dest.writeInt(getNetworkSelectionDisableReason());
1642              for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX;
1643                      index++) {
1644                  dest.writeInt(getDisableReasonCounter(index));
1645              }
1646              dest.writeLong(getDisableTime());
1647              dest.writeString(getNetworkSelectionBSSID());
1648              if (getConnectChoice() != null) {
1649                  dest.writeInt(CONNECT_CHOICE_EXISTS);
1650                  dest.writeString(getConnectChoice());
1651                  dest.writeLong(getConnectChoiceTimestamp());
1652              } else {
1653                  dest.writeInt(CONNECT_CHOICE_NOT_EXISTS);
1654              }
1655              dest.writeInt(getHasEverConnected() ? 1 : 0);
1656              dest.writeInt(isNotRecommended() ? 1 : 0);
1657          }
1658  
readFromParcel(Parcel in)1659          public void readFromParcel(Parcel in) {
1660              setNetworkSelectionStatus(in.readInt());
1661              setNetworkSelectionDisableReason(in.readInt());
1662              for (int index = NETWORK_SELECTION_ENABLE; index < NETWORK_SELECTION_DISABLED_MAX;
1663                      index++) {
1664                  setDisableReasonCounter(index, in.readInt());
1665              }
1666              setDisableTime(in.readLong());
1667              setNetworkSelectionBSSID(in.readString());
1668              if (in.readInt() == CONNECT_CHOICE_EXISTS) {
1669                  setConnectChoice(in.readString());
1670                  setConnectChoiceTimestamp(in.readLong());
1671              } else {
1672                  setConnectChoice(null);
1673                  setConnectChoiceTimestamp(INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP);
1674              }
1675              setHasEverConnected(in.readInt() != 0);
1676              setNotRecommended(in.readInt() != 0);
1677          }
1678      }
1679  
1680      /**
1681       * @hide
1682       * network selection related member
1683       */
1684      private NetworkSelectionStatus mNetworkSelectionStatus = new NetworkSelectionStatus();
1685  
1686      /**
1687       * @hide
1688       * This class is intended to store extra failure reason information for the most recent
1689       * connection attempt, so that it may be surfaced to the settings UI
1690       */
1691      public static class RecentFailure {
1692  
1693          /**
1694           * No recent failure, or no specific reason given for the recent connection failure
1695           */
1696          public static final int NONE = 0;
1697          /**
1698           * Connection to this network recently failed due to Association Rejection Status 17
1699           * (AP is full)
1700           */
1701          public static final int STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17;
1702          /**
1703           * Association Rejection Status code (NONE for success/non-association-rejection-fail)
1704           */
1705          private int mAssociationStatus = NONE;
1706  
1707          /**
1708           * @param status the association status code for the recent failure
1709           */
setAssociationStatus(int status)1710          public void setAssociationStatus(int status) {
1711              mAssociationStatus = status;
1712          }
1713          /**
1714           * Sets the RecentFailure to NONE
1715           */
clear()1716          public void clear() {
1717              mAssociationStatus = NONE;
1718          }
1719          /**
1720           * Get the recent failure code
1721           */
getAssociationStatus()1722          public int getAssociationStatus() {
1723              return mAssociationStatus;
1724          }
1725      }
1726  
1727      /**
1728       * @hide
1729       * RecentFailure member
1730       */
1731      final public RecentFailure recentFailure = new RecentFailure();
1732  
1733      /**
1734       * @hide
1735       * @return network selection status
1736       */
getNetworkSelectionStatus()1737      public NetworkSelectionStatus getNetworkSelectionStatus() {
1738          return mNetworkSelectionStatus;
1739      }
1740  
1741      /**
1742       * Set the network selection status
1743       * @hide
1744       */
setNetworkSelectionStatus(NetworkSelectionStatus status)1745      public void setNetworkSelectionStatus(NetworkSelectionStatus status) {
1746          mNetworkSelectionStatus = status;
1747      }
1748  
1749      /**
1750       * @hide
1751       * Linked Configurations: represent the set of Wificonfigurations that are equivalent
1752       * regarding roaming and auto-joining.
1753       * The linked configuration may or may not have same SSID, and may or may not have same
1754       * credentials.
1755       * For instance, linked configurations will have same defaultGwMacAddress or same dhcp server.
1756       */
1757      public HashMap<String, Integer>  linkedConfigurations;
1758  
WifiConfiguration()1759      public WifiConfiguration() {
1760          networkId = INVALID_NETWORK_ID;
1761          SSID = null;
1762          BSSID = null;
1763          FQDN = null;
1764          roamingConsortiumIds = new long[0];
1765          priority = 0;
1766          hiddenSSID = false;
1767          allowedKeyManagement = new BitSet();
1768          allowedProtocols = new BitSet();
1769          allowedAuthAlgorithms = new BitSet();
1770          allowedPairwiseCiphers = new BitSet();
1771          allowedGroupCiphers = new BitSet();
1772          allowedGroupManagementCiphers = new BitSet();
1773          allowedSuiteBCiphers = new BitSet();
1774          wepKeys = new String[4];
1775          for (int i = 0; i < wepKeys.length; i++) {
1776              wepKeys[i] = null;
1777          }
1778          enterpriseConfig = new WifiEnterpriseConfig();
1779          selfAdded = false;
1780          didSelfAdd = false;
1781          ephemeral = false;
1782          osu = false;
1783          trusted = true; // Networks are considered trusted by default.
1784          fromWifiNetworkSuggestion = false;
1785          fromWifiNetworkSpecifier = false;
1786          meteredHint = false;
1787          meteredOverride = METERED_OVERRIDE_NONE;
1788          useExternalScores = false;
1789          validatedInternetAccess = false;
1790          mIpConfiguration = new IpConfiguration();
1791          lastUpdateUid = -1;
1792          creatorUid = -1;
1793          shared = true;
1794          dtimInterval = 0;
1795          mRandomizedMacAddress = MacAddress.fromString(WifiInfo.DEFAULT_MAC_ADDRESS);
1796      }
1797  
1798      /**
1799       * Identify if this configuration represents a Passpoint network
1800       */
isPasspoint()1801      public boolean isPasspoint() {
1802          return !TextUtils.isEmpty(FQDN)
1803                  && !TextUtils.isEmpty(providerFriendlyName)
1804                  && enterpriseConfig != null
1805                  && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;
1806      }
1807  
1808      /**
1809       * Helper function, identify if a configuration is linked
1810       * @hide
1811       */
isLinked(WifiConfiguration config)1812      public boolean isLinked(WifiConfiguration config) {
1813          if (config != null) {
1814              if (config.linkedConfigurations != null && linkedConfigurations != null) {
1815                  if (config.linkedConfigurations.get(configKey()) != null
1816                          && linkedConfigurations.get(config.configKey()) != null) {
1817                      return true;
1818                  }
1819              }
1820          }
1821          return  false;
1822      }
1823  
1824      /**
1825       * Helper function, idenfity if a configuration should be treated as an enterprise network
1826       * @hide
1827       */
1828      @UnsupportedAppUsage
isEnterprise()1829      public boolean isEnterprise() {
1830          return (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
1831                  || allowedKeyManagement.get(KeyMgmt.IEEE8021X)
1832                  || allowedKeyManagement.get(KeyMgmt.SUITE_B_192))
1833                  && enterpriseConfig != null
1834                  && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE;
1835      }
1836  
1837      @Override
toString()1838      public String toString() {
1839          StringBuilder sbuf = new StringBuilder();
1840          if (this.status == WifiConfiguration.Status.CURRENT) {
1841              sbuf.append("* ");
1842          } else if (this.status == WifiConfiguration.Status.DISABLED) {
1843              sbuf.append("- DSBLE ");
1844          }
1845          sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
1846                  append(" PROVIDER-NAME: ").append(this.providerFriendlyName).
1847                  append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN)
1848                  .append(" PRIO: ").append(this.priority)
1849                  .append(" HIDDEN: ").append(this.hiddenSSID)
1850                  .append(" PMF: ").append(this.requirePMF)
1851                  .append('\n');
1852  
1853  
1854          sbuf.append(" NetworkSelectionStatus ")
1855                  .append(mNetworkSelectionStatus.getNetworkStatusString() + "\n");
1856          if (mNetworkSelectionStatus.getNetworkSelectionDisableReason() > 0) {
1857              sbuf.append(" mNetworkSelectionDisableReason ")
1858                      .append(mNetworkSelectionStatus.getNetworkDisableReasonString() + "\n");
1859  
1860              for (int index = mNetworkSelectionStatus.NETWORK_SELECTION_ENABLE;
1861                      index < mNetworkSelectionStatus.NETWORK_SELECTION_DISABLED_MAX; index++) {
1862                  if (mNetworkSelectionStatus.getDisableReasonCounter(index) != 0) {
1863                      sbuf.append(NetworkSelectionStatus.getNetworkDisableReasonString(index)
1864                              + " counter:" + mNetworkSelectionStatus.getDisableReasonCounter(index)
1865                              + "\n");
1866                  }
1867              }
1868          }
1869          if (mNetworkSelectionStatus.getConnectChoice() != null) {
1870              sbuf.append(" connect choice: ").append(mNetworkSelectionStatus.getConnectChoice());
1871              sbuf.append(" connect choice set time: ")
1872                      .append(TimeUtils.logTimeOfDay(
1873                              mNetworkSelectionStatus.getConnectChoiceTimestamp()));
1874          }
1875          sbuf.append(" hasEverConnected: ")
1876                  .append(mNetworkSelectionStatus.getHasEverConnected()).append("\n");
1877  
1878          if (this.numAssociation > 0) {
1879              sbuf.append(" numAssociation ").append(this.numAssociation).append("\n");
1880          }
1881          if (this.numNoInternetAccessReports > 0) {
1882              sbuf.append(" numNoInternetAccessReports ");
1883              sbuf.append(this.numNoInternetAccessReports).append("\n");
1884          }
1885          if (this.updateTime != null) {
1886              sbuf.append(" update ").append(this.updateTime).append("\n");
1887          }
1888          if (this.creationTime != null) {
1889              sbuf.append(" creation ").append(this.creationTime).append("\n");
1890          }
1891          if (this.didSelfAdd) sbuf.append(" didSelfAdd");
1892          if (this.selfAdded) sbuf.append(" selfAdded");
1893          if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess");
1894          if (this.ephemeral) sbuf.append(" ephemeral");
1895          if (this.osu) sbuf.append(" osu");
1896          if (this.trusted) sbuf.append(" trusted");
1897          if (this.fromWifiNetworkSuggestion) sbuf.append(" fromWifiNetworkSuggestion");
1898          if (this.fromWifiNetworkSpecifier) sbuf.append(" fromWifiNetworkSpecifier");
1899          if (this.meteredHint) sbuf.append(" meteredHint");
1900          if (this.useExternalScores) sbuf.append(" useExternalScores");
1901          if (this.didSelfAdd || this.selfAdded || this.validatedInternetAccess
1902                  || this.ephemeral || this.trusted || this.fromWifiNetworkSuggestion
1903                  || this.fromWifiNetworkSpecifier || this.meteredHint || this.useExternalScores) {
1904              sbuf.append("\n");
1905          }
1906          if (this.meteredOverride != METERED_OVERRIDE_NONE) {
1907              sbuf.append(" meteredOverride ").append(meteredOverride).append("\n");
1908          }
1909          sbuf.append(" macRandomizationSetting: ").append(macRandomizationSetting).append("\n");
1910          sbuf.append(" mRandomizedMacAddress: ").append(mRandomizedMacAddress).append("\n");
1911          sbuf.append(" KeyMgmt:");
1912          for (int k = 0; k < this.allowedKeyManagement.size(); k++) {
1913              if (this.allowedKeyManagement.get(k)) {
1914                  sbuf.append(" ");
1915                  if (k < KeyMgmt.strings.length) {
1916                      sbuf.append(KeyMgmt.strings[k]);
1917                  } else {
1918                      sbuf.append("??");
1919                  }
1920              }
1921          }
1922          sbuf.append(" Protocols:");
1923          for (int p = 0; p < this.allowedProtocols.size(); p++) {
1924              if (this.allowedProtocols.get(p)) {
1925                  sbuf.append(" ");
1926                  if (p < Protocol.strings.length) {
1927                      sbuf.append(Protocol.strings[p]);
1928                  } else {
1929                      sbuf.append("??");
1930                  }
1931              }
1932          }
1933          sbuf.append('\n');
1934          sbuf.append(" AuthAlgorithms:");
1935          for (int a = 0; a < this.allowedAuthAlgorithms.size(); a++) {
1936              if (this.allowedAuthAlgorithms.get(a)) {
1937                  sbuf.append(" ");
1938                  if (a < AuthAlgorithm.strings.length) {
1939                      sbuf.append(AuthAlgorithm.strings[a]);
1940                  } else {
1941                      sbuf.append("??");
1942                  }
1943              }
1944          }
1945          sbuf.append('\n');
1946          sbuf.append(" PairwiseCiphers:");
1947          for (int pc = 0; pc < this.allowedPairwiseCiphers.size(); pc++) {
1948              if (this.allowedPairwiseCiphers.get(pc)) {
1949                  sbuf.append(" ");
1950                  if (pc < PairwiseCipher.strings.length) {
1951                      sbuf.append(PairwiseCipher.strings[pc]);
1952                  } else {
1953                      sbuf.append("??");
1954                  }
1955              }
1956          }
1957          sbuf.append('\n');
1958          sbuf.append(" GroupCiphers:");
1959          for (int gc = 0; gc < this.allowedGroupCiphers.size(); gc++) {
1960              if (this.allowedGroupCiphers.get(gc)) {
1961                  sbuf.append(" ");
1962                  if (gc < GroupCipher.strings.length) {
1963                      sbuf.append(GroupCipher.strings[gc]);
1964                  } else {
1965                      sbuf.append("??");
1966                  }
1967              }
1968          }
1969          sbuf.append('\n');
1970          sbuf.append(" GroupMgmtCiphers:");
1971          for (int gmc = 0; gmc < this.allowedGroupManagementCiphers.size(); gmc++) {
1972              if (this.allowedGroupManagementCiphers.get(gmc)) {
1973                  sbuf.append(" ");
1974                  if (gmc < GroupMgmtCipher.strings.length) {
1975                      sbuf.append(GroupMgmtCipher.strings[gmc]);
1976                  } else {
1977                      sbuf.append("??");
1978                  }
1979              }
1980          }
1981          sbuf.append('\n');
1982          sbuf.append(" SuiteBCiphers:");
1983          for (int sbc = 0; sbc < this.allowedSuiteBCiphers.size(); sbc++) {
1984              if (this.allowedSuiteBCiphers.get(sbc)) {
1985                  sbuf.append(" ");
1986                  if (sbc < SuiteBCipher.strings.length) {
1987                      sbuf.append(SuiteBCipher.strings[sbc]);
1988                  } else {
1989                      sbuf.append("??");
1990                  }
1991              }
1992          }
1993          sbuf.append('\n').append(" PSK/SAE: ");
1994          if (this.preSharedKey != null) {
1995              sbuf.append('*');
1996          }
1997  
1998          sbuf.append("\nEnterprise config:\n");
1999          sbuf.append(enterpriseConfig);
2000  
2001          sbuf.append("IP config:\n");
2002          sbuf.append(mIpConfiguration.toString());
2003  
2004          if (mNetworkSelectionStatus.getNetworkSelectionBSSID() != null) {
2005              sbuf.append(" networkSelectionBSSID="
2006                      + mNetworkSelectionStatus.getNetworkSelectionBSSID());
2007          }
2008          long now_ms = SystemClock.elapsedRealtime();
2009          if (mNetworkSelectionStatus.getDisableTime() != NetworkSelectionStatus
2010                  .INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP) {
2011              sbuf.append('\n');
2012              long diff = now_ms - mNetworkSelectionStatus.getDisableTime();
2013              if (diff <= 0) {
2014                  sbuf.append(" blackListed since <incorrect>");
2015              } else {
2016                  sbuf.append(" blackListed: ").append(Long.toString(diff / 1000)).append("sec ");
2017              }
2018          }
2019          if (creatorUid != 0) sbuf.append(" cuid=" + creatorUid);
2020          if (creatorName != null) sbuf.append(" cname=" + creatorName);
2021          if (lastUpdateUid != 0) sbuf.append(" luid=" + lastUpdateUid);
2022          if (lastUpdateName != null) sbuf.append(" lname=" + lastUpdateName);
2023          if (updateIdentifier != null) sbuf.append(" updateIdentifier=" + updateIdentifier);
2024          sbuf.append(" lcuid=" + lastConnectUid);
2025          sbuf.append(" userApproved=" + userApprovedAsString(userApproved));
2026          sbuf.append(" noInternetAccessExpected=" + noInternetAccessExpected);
2027          sbuf.append(" ");
2028  
2029          if (this.lastConnected != 0) {
2030              sbuf.append('\n');
2031              sbuf.append("lastConnected: ").append(TimeUtils.logTimeOfDay(this.lastConnected));
2032              sbuf.append(" ");
2033          }
2034          sbuf.append('\n');
2035          if (this.linkedConfigurations != null) {
2036              for (String key : this.linkedConfigurations.keySet()) {
2037                  sbuf.append(" linked: ").append(key);
2038                  sbuf.append('\n');
2039              }
2040          }
2041          sbuf.append("recentFailure: ").append("Association Rejection code: ")
2042                  .append(recentFailure.getAssociationStatus()).append("\n");
2043          return sbuf.toString();
2044      }
2045  
2046      /** {@hide} */
2047      @UnsupportedAppUsage
getPrintableSsid()2048      public String getPrintableSsid() {
2049          if (SSID == null) return "";
2050          final int length = SSID.length();
2051          if (length > 2 && (SSID.charAt(0) == '"') && SSID.charAt(length - 1) == '"') {
2052              return SSID.substring(1, length - 1);
2053          }
2054  
2055          /** The ascii-encoded string format is P"<ascii-encoded-string>"
2056           * The decoding is implemented in the supplicant for a newly configured
2057           * network.
2058           */
2059          if (length > 3 && (SSID.charAt(0) == 'P') && (SSID.charAt(1) == '"') &&
2060                  (SSID.charAt(length-1) == '"')) {
2061              WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(
2062                      SSID.substring(2, length - 1));
2063              return wifiSsid.toString();
2064          }
2065          return SSID;
2066      }
2067  
2068      /** @hide **/
userApprovedAsString(int userApproved)2069      public static String userApprovedAsString(int userApproved) {
2070          switch (userApproved) {
2071              case USER_APPROVED:
2072                  return "USER_APPROVED";
2073              case USER_BANNED:
2074                  return "USER_BANNED";
2075              case USER_UNSPECIFIED:
2076                  return "USER_UNSPECIFIED";
2077              default:
2078                  return "INVALID";
2079          }
2080      }
2081  
2082      /**
2083       * Get an identifier for associating credentials with this config
2084       * @param current configuration contains values for additional fields
2085       *                that are not part of this configuration. Used
2086       *                when a config with some fields is passed by an application.
2087       * @throws IllegalStateException if config is invalid for key id generation
2088       * @hide
2089       */
getKeyIdForCredentials(WifiConfiguration current)2090      public String getKeyIdForCredentials(WifiConfiguration current) {
2091          String keyMgmt = "";
2092  
2093          try {
2094              // Get current config details for fields that are not initialized
2095              if (TextUtils.isEmpty(SSID)) SSID = current.SSID;
2096              if (allowedKeyManagement.cardinality() == 0) {
2097                  allowedKeyManagement = current.allowedKeyManagement;
2098              }
2099              if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
2100                  keyMgmt += KeyMgmt.strings[KeyMgmt.WPA_EAP];
2101              }
2102              if (allowedKeyManagement.get(KeyMgmt.OSEN)) {
2103                  keyMgmt += KeyMgmt.strings[KeyMgmt.OSEN];
2104              }
2105              if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
2106                  keyMgmt += KeyMgmt.strings[KeyMgmt.IEEE8021X];
2107              }
2108              if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
2109                  keyMgmt += KeyMgmt.strings[KeyMgmt.SUITE_B_192];
2110              }
2111  
2112              if (TextUtils.isEmpty(keyMgmt)) {
2113                  throw new IllegalStateException("Not an EAP network");
2114              }
2115  
2116              return trimStringForKeyId(SSID) + "_" + keyMgmt + "_" +
2117                      trimStringForKeyId(enterpriseConfig.getKeyId(current != null ?
2118                              current.enterpriseConfig : null));
2119          } catch (NullPointerException e) {
2120              throw new IllegalStateException("Invalid config details");
2121          }
2122      }
2123  
trimStringForKeyId(String string)2124      private String trimStringForKeyId(String string) {
2125          // Remove quotes and spaces
2126          return string.replace("\"", "").replace(" ", "");
2127      }
2128  
readBitSet(Parcel src)2129      private static BitSet readBitSet(Parcel src) {
2130          int cardinality = src.readInt();
2131  
2132          BitSet set = new BitSet();
2133          for (int i = 0; i < cardinality; i++) {
2134              set.set(src.readInt());
2135          }
2136  
2137          return set;
2138      }
2139  
writeBitSet(Parcel dest, BitSet set)2140      private static void writeBitSet(Parcel dest, BitSet set) {
2141          int nextSetBit = -1;
2142  
2143          dest.writeInt(set.cardinality());
2144  
2145          while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) {
2146              dest.writeInt(nextSetBit);
2147          }
2148      }
2149  
2150      /** @hide */
2151      @UnsupportedAppUsage
getAuthType()2152      public int getAuthType() {
2153          if (allowedKeyManagement.cardinality() > 1) {
2154              throw new IllegalStateException("More than one auth type set");
2155          }
2156          if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
2157              return KeyMgmt.WPA_PSK;
2158          } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
2159              return KeyMgmt.WPA2_PSK;
2160          } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) {
2161              return KeyMgmt.WPA_EAP;
2162          } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
2163              return KeyMgmt.IEEE8021X;
2164          } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
2165              return KeyMgmt.SAE;
2166          } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
2167              return KeyMgmt.OWE;
2168          } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
2169              return KeyMgmt.SUITE_B_192;
2170          }
2171          return KeyMgmt.NONE;
2172      }
2173  
2174      /* @hide
2175       * Cache the config key, this seems useful as a speed up since a lot of
2176       * lookups in the config store are done and based on this key.
2177       */
2178      String mCachedConfigKey;
2179  
2180      /** @hide
2181       *  return the string used to calculate the hash in WifiConfigStore
2182       *  and uniquely identify this WifiConfiguration
2183       */
configKey(boolean allowCached)2184      public String configKey(boolean allowCached) {
2185          String key;
2186          if (allowCached && mCachedConfigKey != null) {
2187              key = mCachedConfigKey;
2188          } else if (providerFriendlyName != null) {
2189              key = FQDN + KeyMgmt.strings[KeyMgmt.WPA_EAP];
2190              if (!shared) {
2191                  key += "-" + Integer.toString(UserHandle.getUserId(creatorUid));
2192              }
2193          } else {
2194              key = getSsidAndSecurityTypeString();
2195              if (!shared) {
2196                  key += "-" + Integer.toString(UserHandle.getUserId(creatorUid));
2197              }
2198              mCachedConfigKey = key;
2199          }
2200          return key;
2201      }
2202  
2203      /** @hide
2204       *  return the SSID + security type in String format.
2205       */
getSsidAndSecurityTypeString()2206      public String getSsidAndSecurityTypeString() {
2207          String key;
2208          if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
2209              key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK];
2210          } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)
2211                  || allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
2212              key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP];
2213          } else if (wepKeys[0] != null) {
2214              key = SSID + "WEP";
2215          } else if (allowedKeyManagement.get(KeyMgmt.OWE)) {
2216              key = SSID + KeyMgmt.strings[KeyMgmt.OWE];
2217          } else if (allowedKeyManagement.get(KeyMgmt.SAE)) {
2218              key = SSID + KeyMgmt.strings[KeyMgmt.SAE];
2219          } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) {
2220              key = SSID + KeyMgmt.strings[KeyMgmt.SUITE_B_192];
2221          } else {
2222              key = SSID + KeyMgmt.strings[KeyMgmt.NONE];
2223          }
2224          return key;
2225      }
2226  
2227      /** @hide
2228       * get configKey, force calculating the config string
2229       */
configKey()2230      public String configKey() {
2231          return configKey(false);
2232      }
2233  
2234      /** @hide */
2235      @UnsupportedAppUsage
getIpConfiguration()2236      public IpConfiguration getIpConfiguration() {
2237          return mIpConfiguration;
2238      }
2239  
2240      /** @hide */
2241      @UnsupportedAppUsage
setIpConfiguration(IpConfiguration ipConfiguration)2242      public void setIpConfiguration(IpConfiguration ipConfiguration) {
2243          if (ipConfiguration == null) ipConfiguration = new IpConfiguration();
2244          mIpConfiguration = ipConfiguration;
2245      }
2246  
2247      /** @hide */
2248      @UnsupportedAppUsage
getStaticIpConfiguration()2249      public StaticIpConfiguration getStaticIpConfiguration() {
2250          return mIpConfiguration.getStaticIpConfiguration();
2251      }
2252  
2253      /** @hide */
2254      @UnsupportedAppUsage
setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration)2255      public void setStaticIpConfiguration(StaticIpConfiguration staticIpConfiguration) {
2256          mIpConfiguration.setStaticIpConfiguration(staticIpConfiguration);
2257      }
2258  
2259      /** @hide */
2260      @UnsupportedAppUsage
getIpAssignment()2261      public IpConfiguration.IpAssignment getIpAssignment() {
2262          return mIpConfiguration.ipAssignment;
2263      }
2264  
2265      /** @hide */
2266      @UnsupportedAppUsage
setIpAssignment(IpConfiguration.IpAssignment ipAssignment)2267      public void setIpAssignment(IpConfiguration.IpAssignment ipAssignment) {
2268          mIpConfiguration.ipAssignment = ipAssignment;
2269      }
2270  
2271      /** @hide */
2272      @UnsupportedAppUsage
getProxySettings()2273      public IpConfiguration.ProxySettings getProxySettings() {
2274          return mIpConfiguration.proxySettings;
2275      }
2276  
2277      /** @hide */
2278      @UnsupportedAppUsage
setProxySettings(IpConfiguration.ProxySettings proxySettings)2279      public void setProxySettings(IpConfiguration.ProxySettings proxySettings) {
2280          mIpConfiguration.proxySettings = proxySettings;
2281      }
2282  
2283      /**
2284       * Returns the HTTP proxy used by this object.
2285       * @return a {@link ProxyInfo httpProxy} representing the proxy specified by this
2286       *                  WifiConfiguration, or {@code null} if no proxy is specified.
2287       */
getHttpProxy()2288      public ProxyInfo getHttpProxy() {
2289          if (mIpConfiguration.proxySettings == IpConfiguration.ProxySettings.NONE) {
2290              return null;
2291          }
2292          return new ProxyInfo(mIpConfiguration.httpProxy);
2293      }
2294  
2295      /**
2296       * Set the {@link ProxyInfo} for this WifiConfiguration. This method should only be used by a
2297       * device owner or profile owner. When other apps attempt to save a {@link WifiConfiguration}
2298       * with modified proxy settings, the methods {@link WifiManager#addNetwork} and
2299       * {@link WifiManager#updateNetwork} fail and return {@code -1}.
2300       *
2301       * @param httpProxy {@link ProxyInfo} representing the httpProxy to be used by this
2302       *                  WifiConfiguration. Setting this to {@code null} will explicitly set no
2303       *                  proxy, removing any proxy that was previously set.
2304       * @exception IllegalArgumentException for invalid httpProxy
2305       */
setHttpProxy(ProxyInfo httpProxy)2306      public void setHttpProxy(ProxyInfo httpProxy) {
2307          if (httpProxy == null) {
2308              mIpConfiguration.setProxySettings(IpConfiguration.ProxySettings.NONE);
2309              mIpConfiguration.setHttpProxy(null);
2310              return;
2311          }
2312          ProxyInfo httpProxyCopy;
2313          ProxySettings proxySettingCopy;
2314          if (!Uri.EMPTY.equals(httpProxy.getPacFileUrl())) {
2315              proxySettingCopy = IpConfiguration.ProxySettings.PAC;
2316              // Construct a new PAC URL Proxy
2317              httpProxyCopy = new ProxyInfo(httpProxy.getPacFileUrl(), httpProxy.getPort());
2318          } else {
2319              proxySettingCopy = IpConfiguration.ProxySettings.STATIC;
2320              // Construct a new HTTP Proxy
2321              httpProxyCopy = new ProxyInfo(httpProxy.getHost(), httpProxy.getPort(),
2322                      httpProxy.getExclusionListAsString());
2323          }
2324          if (!httpProxyCopy.isValid()) {
2325              throw new IllegalArgumentException("Invalid ProxyInfo: " + httpProxyCopy.toString());
2326          }
2327          mIpConfiguration.setProxySettings(proxySettingCopy);
2328          mIpConfiguration.setHttpProxy(httpProxyCopy);
2329      }
2330  
2331      /** @hide */
2332      @UnsupportedAppUsage
setProxy(ProxySettings settings, ProxyInfo proxy)2333      public void setProxy(ProxySettings settings, ProxyInfo proxy) {
2334          mIpConfiguration.proxySettings = settings;
2335          mIpConfiguration.httpProxy = proxy;
2336      }
2337  
2338      /** Implement the Parcelable interface {@hide} */
describeContents()2339      public int describeContents() {
2340          return 0;
2341      }
2342  
2343      /** @hide */
setPasspointManagementObjectTree(String passpointManagementObjectTree)2344      public void setPasspointManagementObjectTree(String passpointManagementObjectTree) {
2345          mPasspointManagementObjectTree = passpointManagementObjectTree;
2346      }
2347  
2348      /** @hide */
getMoTree()2349      public String getMoTree() {
2350          return mPasspointManagementObjectTree;
2351      }
2352  
2353      /** copy constructor {@hide} */
2354      @UnsupportedAppUsage
WifiConfiguration(WifiConfiguration source)2355      public WifiConfiguration(WifiConfiguration source) {
2356          if (source != null) {
2357              networkId = source.networkId;
2358              status = source.status;
2359              SSID = source.SSID;
2360              BSSID = source.BSSID;
2361              FQDN = source.FQDN;
2362              roamingConsortiumIds = source.roamingConsortiumIds.clone();
2363              providerFriendlyName = source.providerFriendlyName;
2364              isHomeProviderNetwork = source.isHomeProviderNetwork;
2365              preSharedKey = source.preSharedKey;
2366  
2367              mNetworkSelectionStatus.copy(source.getNetworkSelectionStatus());
2368              apBand = source.apBand;
2369              apChannel = source.apChannel;
2370  
2371              wepKeys = new String[4];
2372              for (int i = 0; i < wepKeys.length; i++) {
2373                  wepKeys[i] = source.wepKeys[i];
2374              }
2375  
2376              wepTxKeyIndex = source.wepTxKeyIndex;
2377              priority = source.priority;
2378              hiddenSSID = source.hiddenSSID;
2379              allowedKeyManagement   = (BitSet) source.allowedKeyManagement.clone();
2380              allowedProtocols       = (BitSet) source.allowedProtocols.clone();
2381              allowedAuthAlgorithms  = (BitSet) source.allowedAuthAlgorithms.clone();
2382              allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone();
2383              allowedGroupCiphers    = (BitSet) source.allowedGroupCiphers.clone();
2384              allowedGroupManagementCiphers = (BitSet) source.allowedGroupManagementCiphers.clone();
2385              allowedSuiteBCiphers    = (BitSet) source.allowedSuiteBCiphers.clone();
2386              enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig);
2387  
2388              defaultGwMacAddress = source.defaultGwMacAddress;
2389  
2390              mIpConfiguration = new IpConfiguration(source.mIpConfiguration);
2391  
2392              if ((source.linkedConfigurations != null)
2393                      && (source.linkedConfigurations.size() > 0)) {
2394                  linkedConfigurations = new HashMap<String, Integer>();
2395                  linkedConfigurations.putAll(source.linkedConfigurations);
2396              }
2397              mCachedConfigKey = null; //force null configKey
2398              selfAdded = source.selfAdded;
2399              validatedInternetAccess = source.validatedInternetAccess;
2400              isLegacyPasspointConfig = source.isLegacyPasspointConfig;
2401              ephemeral = source.ephemeral;
2402              osu = source.osu;
2403              trusted = source.trusted;
2404              fromWifiNetworkSuggestion = source.fromWifiNetworkSuggestion;
2405              fromWifiNetworkSpecifier = source.fromWifiNetworkSpecifier;
2406              meteredHint = source.meteredHint;
2407              meteredOverride = source.meteredOverride;
2408              useExternalScores = source.useExternalScores;
2409  
2410              didSelfAdd = source.didSelfAdd;
2411              lastConnectUid = source.lastConnectUid;
2412              lastUpdateUid = source.lastUpdateUid;
2413              creatorUid = source.creatorUid;
2414              creatorName = source.creatorName;
2415              lastUpdateName = source.lastUpdateName;
2416              peerWifiConfiguration = source.peerWifiConfiguration;
2417  
2418              lastConnected = source.lastConnected;
2419              lastDisconnected = source.lastDisconnected;
2420              numScorerOverride = source.numScorerOverride;
2421              numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
2422              numAssociation = source.numAssociation;
2423              userApproved = source.userApproved;
2424              numNoInternetAccessReports = source.numNoInternetAccessReports;
2425              noInternetAccessExpected = source.noInternetAccessExpected;
2426              creationTime = source.creationTime;
2427              updateTime = source.updateTime;
2428              shared = source.shared;
2429              recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus());
2430              mRandomizedMacAddress = source.mRandomizedMacAddress;
2431              macRandomizationSetting = source.macRandomizationSetting;
2432              requirePMF = source.requirePMF;
2433              updateIdentifier = source.updateIdentifier;
2434          }
2435      }
2436  
2437      /** Implement the Parcelable interface {@hide} */
2438      @Override
writeToParcel(Parcel dest, int flags)2439      public void writeToParcel(Parcel dest, int flags) {
2440          dest.writeInt(networkId);
2441          dest.writeInt(status);
2442          mNetworkSelectionStatus.writeToParcel(dest);
2443          dest.writeString(SSID);
2444          dest.writeString(BSSID);
2445          dest.writeInt(apBand);
2446          dest.writeInt(apChannel);
2447          dest.writeString(FQDN);
2448          dest.writeString(providerFriendlyName);
2449          dest.writeInt(isHomeProviderNetwork ? 1 : 0);
2450          dest.writeInt(roamingConsortiumIds.length);
2451          for (long roamingConsortiumId : roamingConsortiumIds) {
2452              dest.writeLong(roamingConsortiumId);
2453          }
2454          dest.writeString(preSharedKey);
2455          for (String wepKey : wepKeys) {
2456              dest.writeString(wepKey);
2457          }
2458          dest.writeInt(wepTxKeyIndex);
2459          dest.writeInt(priority);
2460          dest.writeInt(hiddenSSID ? 1 : 0);
2461          dest.writeInt(requirePMF ? 1 : 0);
2462          dest.writeString(updateIdentifier);
2463  
2464          writeBitSet(dest, allowedKeyManagement);
2465          writeBitSet(dest, allowedProtocols);
2466          writeBitSet(dest, allowedAuthAlgorithms);
2467          writeBitSet(dest, allowedPairwiseCiphers);
2468          writeBitSet(dest, allowedGroupCiphers);
2469          writeBitSet(dest, allowedGroupManagementCiphers);
2470          writeBitSet(dest, allowedSuiteBCiphers);
2471  
2472          dest.writeParcelable(enterpriseConfig, flags);
2473  
2474          dest.writeParcelable(mIpConfiguration, flags);
2475          dest.writeString(dhcpServer);
2476          dest.writeString(defaultGwMacAddress);
2477          dest.writeInt(selfAdded ? 1 : 0);
2478          dest.writeInt(didSelfAdd ? 1 : 0);
2479          dest.writeInt(validatedInternetAccess ? 1 : 0);
2480          dest.writeInt(isLegacyPasspointConfig ? 1 : 0);
2481          dest.writeInt(ephemeral ? 1 : 0);
2482          dest.writeInt(trusted ? 1 : 0);
2483          dest.writeInt(fromWifiNetworkSuggestion ? 1 : 0);
2484          dest.writeInt(fromWifiNetworkSpecifier ? 1 : 0);
2485          dest.writeInt(meteredHint ? 1 : 0);
2486          dest.writeInt(meteredOverride);
2487          dest.writeInt(useExternalScores ? 1 : 0);
2488          dest.writeInt(creatorUid);
2489          dest.writeInt(lastConnectUid);
2490          dest.writeInt(lastUpdateUid);
2491          dest.writeString(creatorName);
2492          dest.writeString(lastUpdateName);
2493          dest.writeInt(numScorerOverride);
2494          dest.writeInt(numScorerOverrideAndSwitchedNetwork);
2495          dest.writeInt(numAssociation);
2496          dest.writeInt(userApproved);
2497          dest.writeInt(numNoInternetAccessReports);
2498          dest.writeInt(noInternetAccessExpected ? 1 : 0);
2499          dest.writeInt(shared ? 1 : 0);
2500          dest.writeString(mPasspointManagementObjectTree);
2501          dest.writeInt(recentFailure.getAssociationStatus());
2502          dest.writeParcelable(mRandomizedMacAddress, flags);
2503          dest.writeInt(macRandomizationSetting);
2504          dest.writeInt(osu ? 1 : 0);
2505      }
2506  
2507      /** Implement the Parcelable interface {@hide} */
2508      @UnsupportedAppUsage
2509      public static final @android.annotation.NonNull Creator<WifiConfiguration> CREATOR =
2510          new Creator<WifiConfiguration>() {
2511              public WifiConfiguration createFromParcel(Parcel in) {
2512                  WifiConfiguration config = new WifiConfiguration();
2513                  config.networkId = in.readInt();
2514                  config.status = in.readInt();
2515                  config.mNetworkSelectionStatus.readFromParcel(in);
2516                  config.SSID = in.readString();
2517                  config.BSSID = in.readString();
2518                  config.apBand = in.readInt();
2519                  config.apChannel = in.readInt();
2520                  config.FQDN = in.readString();
2521                  config.providerFriendlyName = in.readString();
2522                  config.isHomeProviderNetwork = in.readInt() != 0;
2523                  int numRoamingConsortiumIds = in.readInt();
2524                  config.roamingConsortiumIds = new long[numRoamingConsortiumIds];
2525                  for (int i = 0; i < numRoamingConsortiumIds; i++) {
2526                      config.roamingConsortiumIds[i] = in.readLong();
2527                  }
2528                  config.preSharedKey = in.readString();
2529                  for (int i = 0; i < config.wepKeys.length; i++) {
2530                      config.wepKeys[i] = in.readString();
2531                  }
2532                  config.wepTxKeyIndex = in.readInt();
2533                  config.priority = in.readInt();
2534                  config.hiddenSSID = in.readInt() != 0;
2535                  config.requirePMF = in.readInt() != 0;
2536                  config.updateIdentifier = in.readString();
2537  
2538                  config.allowedKeyManagement   = readBitSet(in);
2539                  config.allowedProtocols       = readBitSet(in);
2540                  config.allowedAuthAlgorithms  = readBitSet(in);
2541                  config.allowedPairwiseCiphers = readBitSet(in);
2542                  config.allowedGroupCiphers    = readBitSet(in);
2543                  config.allowedGroupManagementCiphers = readBitSet(in);
2544                  config.allowedSuiteBCiphers   = readBitSet(in);
2545  
2546                  config.enterpriseConfig = in.readParcelable(null);
2547                  config.setIpConfiguration(in.readParcelable(null));
2548                  config.dhcpServer = in.readString();
2549                  config.defaultGwMacAddress = in.readString();
2550                  config.selfAdded = in.readInt() != 0;
2551                  config.didSelfAdd = in.readInt() != 0;
2552                  config.validatedInternetAccess = in.readInt() != 0;
2553                  config.isLegacyPasspointConfig = in.readInt() != 0;
2554                  config.ephemeral = in.readInt() != 0;
2555                  config.trusted = in.readInt() != 0;
2556                  config.fromWifiNetworkSuggestion =  in.readInt() != 0;
2557                  config.fromWifiNetworkSpecifier =  in.readInt() != 0;
2558                  config.meteredHint = in.readInt() != 0;
2559                  config.meteredOverride = in.readInt();
2560                  config.useExternalScores = in.readInt() != 0;
2561                  config.creatorUid = in.readInt();
2562                  config.lastConnectUid = in.readInt();
2563                  config.lastUpdateUid = in.readInt();
2564                  config.creatorName = in.readString();
2565                  config.lastUpdateName = in.readString();
2566                  config.numScorerOverride = in.readInt();
2567                  config.numScorerOverrideAndSwitchedNetwork = in.readInt();
2568                  config.numAssociation = in.readInt();
2569                  config.userApproved = in.readInt();
2570                  config.numNoInternetAccessReports = in.readInt();
2571                  config.noInternetAccessExpected = in.readInt() != 0;
2572                  config.shared = in.readInt() != 0;
2573                  config.mPasspointManagementObjectTree = in.readString();
2574                  config.recentFailure.setAssociationStatus(in.readInt());
2575                  config.mRandomizedMacAddress = in.readParcelable(null);
2576                  config.macRandomizationSetting = in.readInt();
2577                  config.osu = in.readInt() != 0;
2578                  return config;
2579              }
2580  
2581              public WifiConfiguration[] newArray(int size) {
2582                  return new WifiConfiguration[size];
2583              }
2584          };
2585  
2586      /**
2587       * Serializes the object for backup
2588       * @hide
2589       */
getBytesForBackup()2590      public byte[] getBytesForBackup() throws IOException {
2591          ByteArrayOutputStream baos = new ByteArrayOutputStream();
2592          DataOutputStream out = new DataOutputStream(baos);
2593  
2594          out.writeInt(BACKUP_VERSION);
2595          BackupUtils.writeString(out, SSID);
2596          out.writeInt(apBand);
2597          out.writeInt(apChannel);
2598          BackupUtils.writeString(out, preSharedKey);
2599          out.writeInt(getAuthType());
2600          out.writeBoolean(hiddenSSID);
2601          return baos.toByteArray();
2602      }
2603  
2604      /**
2605       * Deserializes a byte array into the WiFiConfiguration Object
2606       * @hide
2607       */
getWifiConfigFromBackup(DataInputStream in)2608      public static WifiConfiguration getWifiConfigFromBackup(DataInputStream in) throws IOException,
2609              BackupUtils.BadVersionException {
2610          WifiConfiguration config = new WifiConfiguration();
2611          int version = in.readInt();
2612          if (version < 1 || version > BACKUP_VERSION) {
2613              throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
2614          }
2615  
2616          if (version == 1) return null; // Version 1 is a bad dataset.
2617  
2618          config.SSID = BackupUtils.readString(in);
2619          config.apBand = in.readInt();
2620          config.apChannel = in.readInt();
2621          config.preSharedKey = BackupUtils.readString(in);
2622          config.allowedKeyManagement.set(in.readInt());
2623          if (version >= 3) {
2624              config.hiddenSSID = in.readBoolean();
2625          }
2626          return config;
2627      }
2628  }
2629