• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.hotspot2.flow;
2 
3 import android.content.Context;
4 import android.content.Intent;
5 import android.net.Network;
6 import android.net.wifi.PasspointManagementObjectDefinition;
7 import android.net.wifi.WifiConfiguration;
8 import android.net.wifi.WifiEnterpriseConfig;
9 import android.net.wifi.WifiInfo;
10 import android.net.wifi.WifiManager;
11 import android.util.Log;
12 
13 import com.android.configparse.ConfigBuilder;
14 import com.android.hotspot2.AppBridge;
15 import com.android.hotspot2.Utils;
16 import com.android.hotspot2.app.OSUService;
17 import com.android.hotspot2.omadm.MOManager;
18 import com.android.hotspot2.omadm.MOTree;
19 import com.android.hotspot2.omadm.OMAConstants;
20 import com.android.hotspot2.omadm.OMAException;
21 import com.android.hotspot2.omadm.OMAParser;
22 import com.android.hotspot2.osu.ClientKeyManager;
23 import com.android.hotspot2.osu.OSUCertType;
24 import com.android.hotspot2.osu.OSUManager;
25 import com.android.hotspot2.osu.OSUOperationStatus;
26 import com.android.hotspot2.osu.OSUSocketFactory;
27 import com.android.hotspot2.osu.WiFiKeyManager;
28 import com.android.hotspot2.osu.commands.MOData;
29 import com.android.hotspot2.pps.HomeSP;
30 
31 import org.xml.sax.SAXException;
32 
33 import java.io.File;
34 import java.io.FileInputStream;
35 import java.io.FileOutputStream;
36 import java.io.IOException;
37 import java.security.GeneralSecurityException;
38 import java.security.KeyStore;
39 import java.security.KeyStoreException;
40 import java.security.PrivateKey;
41 import java.security.cert.Certificate;
42 import java.security.cert.X509Certificate;
43 import java.util.ArrayList;
44 import java.util.Collection;
45 import java.util.Enumeration;
46 import java.util.HashMap;
47 import java.util.Iterator;
48 import java.util.List;
49 import java.util.Locale;
50 import java.util.Map;
51 import java.util.Set;
52 
53 import javax.net.ssl.KeyManager;
54 
55 public class PlatformAdapter {
56     private static final String TAG = "OSUFLOW";
57 
58     public static final Locale LOCALE = Locale.getDefault();
59 
60     public static final String CERT_WFA_ALIAS = "wfa-root-";
61     public static final String CERT_REM_ALIAS = "rem-";
62     public static final String CERT_POLICY_ALIAS = "pol-";
63     public static final String CERT_SHARED_ALIAS = "shr-";
64     public static final String CERT_CLT_CERT_ALIAS = "clt-";
65     public static final String CERT_CLT_KEY_ALIAS = "prv-";
66     public static final String CERT_CLT_CA_ALIAS = "aaa-";
67 
68     private static final String KEYSTORE_FILE = "passpoint.ks";
69 
70     private final Context mContext;
71     private final File mKeyStoreFile;
72     private final KeyStore mKeyStore;
73     private final AppBridge mAppBridge;
74     private final Map<String, PasspointConfig> mPasspointConfigs;
75 
PlatformAdapter(Context context)76     public PlatformAdapter(Context context) {
77         mContext = context;
78         mAppBridge = new AppBridge(context);
79 
80         File appFolder = context.getFilesDir();
81         mKeyStoreFile = new File(appFolder, KEYSTORE_FILE);
82         Log.d(TAG, "KS file: " + mKeyStoreFile.getPath());
83         KeyStore ks = null;
84         try {
85             //ks = loadKeyStore(KEYSTORE_FILE, readCertsFromDisk(WFA_CA_LOC));
86             ks = loadKeyStore(mKeyStoreFile, OSUSocketFactory.buildCertSet());
87         } catch (IOException e) {
88             Log.e(TAG, "Failed to initialize Passpoint keystore, OSU disabled", e);
89         }
90         mKeyStore = ks;
91 
92         mPasspointConfigs = loadAllSps(context);
93     }
94 
loadKeyStore(File ksFile, Set<X509Certificate> diskCerts)95     private static KeyStore loadKeyStore(File ksFile, Set<X509Certificate> diskCerts)
96             throws IOException {
97         try {
98             KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
99             if (ksFile.exists()) {
100                 try (FileInputStream in = new FileInputStream(ksFile)) {
101                     keyStore.load(in, null);
102                 }
103 
104                 // Note: comparing two sets of certs does not work.
105                 boolean mismatch = false;
106                 int loadCount = 0;
107                 for (int n = 0; n < 1000; n++) {
108                     String alias = String.format("%s%d", CERT_WFA_ALIAS, n);
109                     Certificate cert = keyStore.getCertificate(alias);
110                     if (cert == null) {
111                         break;
112                     }
113 
114                     loadCount++;
115                     boolean matched = false;
116                     Iterator<X509Certificate> iter = diskCerts.iterator();
117                     while (iter.hasNext()) {
118                         X509Certificate diskCert = iter.next();
119                         if (cert.equals(diskCert)) {
120                             iter.remove();
121                             matched = true;
122                             break;
123                         }
124                     }
125                     if (!matched) {
126                         mismatch = true;
127                         break;
128                     }
129                 }
130                 if (mismatch || !diskCerts.isEmpty()) {
131                     Log.d(TAG, "Re-seeding Passpoint key store with " +
132                             diskCerts.size() + " WFA certs");
133                     for (int n = 0; n < 1000; n++) {
134                         String alias = String.format("%s%d", CERT_WFA_ALIAS, n);
135                         Certificate cert = keyStore.getCertificate(alias);
136                         if (cert == null) {
137                             break;
138                         } else {
139                             keyStore.deleteEntry(alias);
140                         }
141                     }
142                     int index = 0;
143                     for (X509Certificate caCert : diskCerts) {
144                         keyStore.setCertificateEntry(
145                                 String.format("%s%d", CERT_WFA_ALIAS, index), caCert);
146                         index++;
147                     }
148 
149                     try (FileOutputStream out = new FileOutputStream(ksFile)) {
150                         keyStore.store(out, null);
151                     }
152                 } else {
153                     Log.d(TAG, "Loaded Passpoint key store with " + loadCount + " CA certs");
154                     Enumeration<String> aliases = keyStore.aliases();
155                     while (aliases.hasMoreElements()) {
156                         Log.d("ZXC", "KS Alias '" + aliases.nextElement() + "'");
157                     }
158                 }
159             } else {
160                 keyStore.load(null, null);
161                 int index = 0;
162                 for (X509Certificate caCert : diskCerts) {
163                     keyStore.setCertificateEntry(
164                             String.format("%s%d", CERT_WFA_ALIAS, index), caCert);
165                     index++;
166                 }
167 
168                 try (FileOutputStream out = new FileOutputStream(ksFile)) {
169                     keyStore.store(out, null);
170                 }
171                 Log.d(TAG, "Initialized Passpoint key store with " +
172                         diskCerts.size() + " CA certs");
173             }
174             return keyStore;
175         } catch (GeneralSecurityException gse) {
176             throw new IOException(gse);
177         }
178     }
179 
loadAllSps(Context context)180     private static Map<String, PasspointConfig> loadAllSps(Context context) {
181         Map<String, PasspointConfig> passpointConfigs = new HashMap<>();
182 
183         WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
184         List<WifiConfiguration> configs = wifiManager.getPrivilegedConfiguredNetworks();
185         if (configs == null) {
186             return passpointConfigs;
187         }
188         int count = 0;
189         for (WifiConfiguration config : configs) {
190             String moTree = config.getMoTree();
191             if (moTree != null) {
192                 try {
193                     passpointConfigs.put(config.FQDN, new PasspointConfig(config));
194                     count++;
195                 } catch (IOException | SAXException e) {
196                     Log.w(OSUManager.TAG, "Failed to parse MO: " + e);
197                 }
198             }
199         }
200         Log.d(OSUManager.TAG, "Loaded " + count + " SPs");
201         return passpointConfigs;
202     }
203 
getKeyStore()204     public KeyStore getKeyStore() {
205         return mKeyStore;
206     }
207 
getContext()208     public Context getContext() {
209         return mContext;
210     }
211 
212     /**
213      * Connect to an OSU provisioning network. The connection should not bring down other existing
214      * connection and the network should not be made the default network since the connection
215      * is solely for sign up and is neither intended for nor likely provides access to any
216      * generic resources.
217      *
218      * @param osuInfo The OSU info object that defines the parameters for the network. An OSU
219      *                network is either an open network, or, if the OSU NAI is set, an "OSEN"
220      *                network, which is an anonymous EAP-TLS network with special keys.
221      * @return an Integer holding the network-id of the just added network configuration, or null
222      * if the network existed prior to this call (was not added by the OSU infrastructure).
223      * The value will be used at the end of the OSU flow to delete the network as applicable.
224      * @throws IOException Issues:
225      *                     1. The network id is not returned. addNetwork cannot be called from here since the method
226      *                     runs in the context of the app and doesn't have the appropriate permission.
227      *                     2. The connection is not immediately usable if the network was not previously selected
228      *                     manually.
229      */
connect(OSUInfo osuInfo)230     public Integer connect(OSUInfo osuInfo) throws IOException {
231         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
232 
233         WifiConfiguration config = new WifiConfiguration();
234         config.SSID = '"' + osuInfo.getOsuSsid() + '"';
235         if (osuInfo.getOSUBssid() != 0) {
236             config.BSSID = Utils.macToString(osuInfo.getOSUBssid());
237             Log.d(OSUManager.TAG, String.format("Setting BSSID of '%s' to %012x",
238                     osuInfo.getOsuSsid(), osuInfo.getOSUBssid()));
239         }
240 
241         if (osuInfo.getOSUProvider().getOsuNai() == null) {
242             config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
243         } else {
244             config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OSEN);
245             config.allowedProtocols.set(WifiConfiguration.Protocol.OSEN);
246             config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
247             config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GTK_NOT_USED);
248             config.enterpriseConfig = new WifiEnterpriseConfig();
249             config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.UNAUTH_TLS);
250             config.enterpriseConfig.setIdentity(osuInfo.getOSUProvider().getOsuNai());
251             Set<X509Certificate> cas = OSUSocketFactory.buildCertSet();
252             config.enterpriseConfig.setCaCertificates(cas.toArray(new X509Certificate[cas.size()]));
253         }
254 
255         int networkId = wifiManager.addNetwork(config);
256         if (networkId < 0) {
257             throw new IOException("Failed to add OSU network");
258         }
259         if (wifiManager.enableNetwork(networkId, true)) {
260             return networkId;
261         } else {
262             throw new IOException("Failed to enable OSU network");
263         }
264     }
265 
266     /**
267      * @param homeSP The Home SP associated with the keying material in question. Passing
268      *               null returns a "system wide" KeyManager to support pre-provisioned certs based
269      *               on names retrieved from the ClientCertInfo request.
270      * @return A key manager suitable for the given configuration (or pre-provisioned keys).
271      */
getKeyManager(HomeSP homeSP)272     public KeyManager getKeyManager(HomeSP homeSP) throws IOException {
273         return homeSP != null
274                 ? new ClientKeyManager(homeSP, mKeyStore) : new WiFiKeyManager(mKeyStore);
275     }
276 
provisioningComplete(OSUInfo osuInfo, MOData moData, Map<OSUCertType, List<X509Certificate>> certs, PrivateKey privateKey, Network osuNetwork)277     public void provisioningComplete(OSUInfo osuInfo,
278                                      MOData moData, Map<OSUCertType, List<X509Certificate>> certs,
279                                      PrivateKey privateKey, Network osuNetwork) {
280         try {
281             String xml = moData.getMOTree().toXml();
282             HomeSP homeSP = MOManager.buildSP(xml);
283 
284             Integer spNwk = addNetwork(homeSP, certs, privateKey, osuNetwork);
285             if (spNwk == null) {
286                 notifyUser(OSUOperationStatus.ProvisioningFailure,
287                         "Failed to save network configuration", osuInfo.getName(LOCALE));
288             } else {
289                 if (addSP(xml) < 0) {
290                     deleteNetwork(spNwk);
291                     Log.e(TAG, "Failed to provision: " + homeSP.getFQDN());
292                     notifyUser(OSUOperationStatus.ProvisioningFailure, "Failed to add MO",
293                             osuInfo.getName(LOCALE));
294                     return;
295                 }
296                 Set<X509Certificate> rootCerts = OSUSocketFactory.getRootCerts(mKeyStore);
297                 X509Certificate remCert = getCert(certs, OSUCertType.Remediation);
298                 X509Certificate polCert = getCert(certs, OSUCertType.Policy);
299                 int newCerts = 0;
300                 if (privateKey != null) {
301                     X509Certificate cltCert = getCert(certs, OSUCertType.Client);
302                     mKeyStore.setKeyEntry(CERT_CLT_KEY_ALIAS + homeSP.getFQDN(),
303                             privateKey, null, new X509Certificate[]{cltCert});
304                     mKeyStore.setCertificateEntry(CERT_CLT_CERT_ALIAS + homeSP.getFQDN(), cltCert);
305                     newCerts++;
306                 }
307                 boolean usingShared = false;
308                 if (remCert != null) {
309                     if (!rootCerts.contains(remCert)) {
310                         if (remCert.equals(polCert)) {
311                             mKeyStore.setCertificateEntry(CERT_SHARED_ALIAS + homeSP.getFQDN(),
312                                     remCert);
313                             usingShared = true;
314                             newCerts++;
315                         } else {
316                             mKeyStore.setCertificateEntry(CERT_REM_ALIAS + homeSP.getFQDN(),
317                                     remCert);
318                             newCerts++;
319                         }
320                     }
321                 }
322                 if (!usingShared && polCert != null) {
323                     if (!rootCerts.contains(polCert)) {
324                         mKeyStore.setCertificateEntry(CERT_POLICY_ALIAS + homeSP.getFQDN(),
325                                 remCert);
326                         newCerts++;
327                     }
328                 }
329 
330 
331                 if (newCerts > 0) {
332                     try (FileOutputStream out = new FileOutputStream(mKeyStoreFile)) {
333                         mKeyStore.store(out, null);
334                     }
335                 }
336                 notifyUser(OSUOperationStatus.ProvisioningSuccess, null, osuInfo.getName(LOCALE));
337                 Log.d(TAG, "Provisioning complete.");
338             }
339         } catch (IOException | GeneralSecurityException | SAXException e) {
340             Log.e(TAG, "Failed to provision: " + e, e);
341             notifyUser(OSUOperationStatus.ProvisioningFailure, e.toString(),
342                     osuInfo.getName(LOCALE));
343         }
344     }
345 
remediationComplete(HomeSP homeSP, Collection<MOData> mods, Map<OSUCertType, List<X509Certificate>> certs, PrivateKey privateKey, boolean policy)346     public void remediationComplete(HomeSP homeSP, Collection<MOData> mods,
347                                     Map<OSUCertType, List<X509Certificate>> certs,
348                                     PrivateKey privateKey, boolean policy)
349             throws IOException, GeneralSecurityException {
350 
351         HomeSP altSP = null;
352         if (modifySP(homeSP, mods) > 0) {
353             altSP = MOManager.modifySP(homeSP, getMOTree(homeSP), mods);
354         }
355 
356         X509Certificate caCert = null;
357         List<X509Certificate> clientCerts = null;
358         if (certs != null) {
359             List<X509Certificate> certList = certs.get(OSUCertType.AAA);
360             caCert = certList != null && !certList.isEmpty() ? certList.iterator().next() : null;
361             clientCerts = certs.get(OSUCertType.Client);
362         }
363         if (altSP != null || certs != null) {
364             if (altSP == null) {
365                 altSP = homeSP;
366             }
367             updateNetwork(altSP, caCert, clientCerts, privateKey);
368 
369             if (privateKey != null) {
370                 X509Certificate cltCert = getCert(certs, OSUCertType.Client);
371                 mKeyStore.setKeyEntry(CERT_CLT_KEY_ALIAS + homeSP.getFQDN(),
372                         privateKey, null, new X509Certificate[]{cltCert});
373                 mKeyStore.setCertificateEntry(CERT_CLT_CERT_ALIAS + homeSP.getFQDN(), cltCert);
374             }
375         }
376 
377         Intent intent = new Intent(OSUService.REMEDIATION_DONE_ACTION);
378         intent.putExtra(OSUService.REMEDIATION_FQDN_EXTRA, homeSP.getFQDN());
379         intent.putExtra(OSUService.REMEDIATION_POLICY_EXTRA, policy);
380         mContext.sendBroadcast(intent);
381 
382         notifyUser(OSUOperationStatus.ProvisioningSuccess, null, homeSP.getFriendlyName());
383     }
384 
serviceProviderDeleted(String fqdn)385     public void serviceProviderDeleted(String fqdn) {
386         int count = deleteCerts(mKeyStore, fqdn,
387                 CERT_REM_ALIAS, CERT_POLICY_ALIAS, CERT_SHARED_ALIAS, CERT_CLT_CERT_ALIAS);
388 
389         Log.d(TAG, "Passpoint network deleted, removing " + count + " key store entries");
390 
391         try {
392             if (mKeyStore.getKey(CERT_CLT_KEY_ALIAS + fqdn, null) != null) {
393                 mKeyStore.deleteEntry(CERT_CLT_KEY_ALIAS + fqdn);
394             }
395         } catch (GeneralSecurityException e) {
396                 /**/
397         }
398 
399         if (count > 0) {
400             try (FileOutputStream out = new FileOutputStream(mKeyStoreFile)) {
401                 mKeyStore.store(out, null);
402             } catch (IOException | GeneralSecurityException e) {
403                 Log.w(TAG, "Failed to remove certs from key store: " + e);
404             }
405         }
406     }
407 
deleteCerts(KeyStore keyStore, String fqdn, String... prefixes)408     private static int deleteCerts(KeyStore keyStore, String fqdn, String... prefixes) {
409         int count = 0;
410         for (String prefix : prefixes) {
411             try {
412                 String alias = prefix + fqdn;
413                 Certificate cert = keyStore.getCertificate(alias);
414                 if (cert != null) {
415                     keyStore.deleteEntry(alias);
416                     count++;
417                 }
418             } catch (KeyStoreException kse) {
419                 /**/
420             }
421         }
422         return count;
423     }
424 
getCert(Map<OSUCertType, List<X509Certificate>> certMap, OSUCertType certType)425     private static X509Certificate getCert(Map<OSUCertType, List<X509Certificate>> certMap,
426                                            OSUCertType certType) {
427         List<X509Certificate> certs = certMap.get(certType);
428         if (certs == null || certs.isEmpty()) {
429             return null;
430         }
431         return certs.iterator().next();
432     }
433 
notifyUser(OSUOperationStatus status, String message, String spName)434     public String notifyUser(OSUOperationStatus status, String message, String spName) {
435         if (status == OSUOperationStatus.UserInputComplete) {
436             return null;
437         }
438         mAppBridge.showStatus(status, spName, message, null);
439         return null;
440     }
441 
provisioningFailed(String spName, String message)442     public void provisioningFailed(String spName, String message) {
443         notifyUser(OSUOperationStatus.ProvisioningFailure, message, spName);
444     }
445 
addNetwork(HomeSP homeSP, Map<OSUCertType, List<X509Certificate>> certs, PrivateKey privateKey, Network osuNetwork)446     private Integer addNetwork(HomeSP homeSP, Map<OSUCertType, List<X509Certificate>> certs,
447                               PrivateKey privateKey, Network osuNetwork)
448             throws IOException, GeneralSecurityException {
449 
450         List<X509Certificate> aaaTrust = certs.get(OSUCertType.AAA);
451         if (aaaTrust.isEmpty()) {
452             aaaTrust = certs.get(OSUCertType.CA);   // Get the CAs from the EST flow.
453         }
454 
455         WifiConfiguration config = ConfigBuilder.buildConfig(homeSP,
456                 aaaTrust.iterator().next(),
457                 certs.get(OSUCertType.Client), privateKey);
458 
459         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
460         int nwkId = wifiManager.addNetwork(config);
461         boolean saved = false;
462         if (nwkId >= 0) {
463             saved = wifiManager.saveConfiguration();
464         }
465         Log.d(OSUManager.TAG, "Wifi configuration " + nwkId +
466                 " " + (saved ? "saved" : "not saved"));
467 
468         if (saved) {
469             reconnect(osuNetwork, nwkId);
470             return nwkId;
471         } else {
472             return null;
473         }
474     }
475 
updateNetwork(HomeSP homeSP, X509Certificate caCert, List<X509Certificate> clientCerts, PrivateKey privateKey)476     private void updateNetwork(HomeSP homeSP, X509Certificate caCert,
477                               List<X509Certificate> clientCerts, PrivateKey privateKey)
478             throws IOException, GeneralSecurityException {
479 
480         WifiConfiguration config = getWifiConfig(homeSP);
481         if (config == null) {
482             throw new IOException("Failed to find matching network config");
483         }
484         Log.d(OSUManager.TAG, "Found matching config " + config.networkId + ", updating");
485 
486         WifiEnterpriseConfig enterpriseConfig = config.enterpriseConfig;
487         WifiConfiguration newConfig = ConfigBuilder.buildConfig(homeSP,
488                 caCert != null ? caCert : enterpriseConfig.getCaCertificate(),
489                 clientCerts, privateKey);
490         newConfig.networkId = config.networkId;
491 
492         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
493         wifiManager.save(newConfig, null);
494         wifiManager.saveConfiguration();
495     }
496 
getWifiConfig(HomeSP homeSP)497     private WifiConfiguration getWifiConfig(HomeSP homeSP) {
498         PasspointConfig passpointConfig = mPasspointConfigs.get(homeSP.getFQDN());
499         return passpointConfig != null ? passpointConfig.getWifiConfiguration() : null;
500     }
501 
getMOTree(HomeSP homeSP)502     public MOTree getMOTree(HomeSP homeSP) {
503         PasspointConfig config = mPasspointConfigs.get(homeSP.getFQDN());
504         return config != null ? config.getmMOTree() : null;
505     }
506 
getHomeSP(String fqdn)507     public HomeSP getHomeSP(String fqdn) {
508         PasspointConfig passpointConfig = mPasspointConfigs.get(fqdn);
509         return passpointConfig != null ? passpointConfig.getHomeSP() : null;
510     }
511 
getCurrentSP()512     public HomeSP getCurrentSP() {
513         PasspointConfig passpointConfig = getActivePasspointConfig();
514         return passpointConfig != null ? passpointConfig.getHomeSP() : null;
515     }
516 
getActivePasspointConfig()517     private PasspointConfig getActivePasspointConfig() {
518         WifiInfo wifiInfo = getConnectionInfo();
519         if (wifiInfo == null) {
520             return null;
521         }
522 
523         for (PasspointConfig passpointConfig : mPasspointConfigs.values()) {
524             if (passpointConfig.getWifiConfiguration().networkId == wifiInfo.getNetworkId()) {
525                 return passpointConfig;
526             }
527         }
528         return null;
529     }
530 
addSP(String xml)531     private int addSP(String xml) throws IOException, SAXException {
532         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
533         // TODO(b/32883320): use the new API for adding Passpoint configuration.
534         return 0;
535     }
536 
modifySP(HomeSP homeSP, Collection<MOData> mods)537     private int modifySP(HomeSP homeSP, Collection<MOData> mods) throws IOException {
538         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
539         List<PasspointManagementObjectDefinition> defMods = new ArrayList<>(mods.size());
540         for (MOData mod : mods) {
541             defMods.add(new PasspointManagementObjectDefinition(mod.getBaseURI(),
542                     mod.getURN(), mod.getMOTree().toXml()));
543         }
544         // TODO(b/32883320): use the new API to update Passpoint configuration.
545         return 0;
546     }
547 
reconnect(Network osuNetwork, int newNwkId)548     private void reconnect(Network osuNetwork, int newNwkId) {
549         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
550         if (osuNetwork != null) {
551             wifiManager.disableNetwork(osuNetwork.netId);
552         }
553         if (newNwkId != WifiConfiguration.INVALID_NETWORK_ID) {
554             wifiManager.enableNetwork(newNwkId, true);
555         }
556     }
557 
deleteNetwork(int id)558     public void deleteNetwork(int id) {
559         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
560         wifiManager.disableNetwork(id);
561         wifiManager.forget(id, null);
562     }
563 
getConnectionInfo()564     public WifiInfo getConnectionInfo() {
565         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
566         return wifiManager.getConnectionInfo();
567     }
568 
getCurrentNetwork()569     public Network getCurrentNetwork() {
570         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
571         return wifiManager.getCurrentNetwork();
572     }
573 
getActiveWifiConfig()574     public WifiConfiguration getActiveWifiConfig() {
575         WifiInfo wifiInfo = getConnectionInfo();
576         if (wifiInfo == null) {
577             return null;
578         }
579         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
580         List<WifiConfiguration> configs = wifiManager.getConfiguredNetworks();
581         if (configs == null) {
582             return null;
583         }
584         for (WifiConfiguration config : configs) {
585             if (config.networkId == wifiInfo.getNetworkId()) {
586                 return config;
587             }
588         }
589         return null;
590     }
591 
592     private static class PasspointConfig {
593         private final WifiConfiguration mWifiConfiguration;
594         private final MOTree mMOTree;
595         private final HomeSP mHomeSP;
596 
PasspointConfig(WifiConfiguration config)597         private PasspointConfig(WifiConfiguration config) throws IOException, SAXException {
598             mWifiConfiguration = config;
599             OMAParser omaParser = new OMAParser();
600             mMOTree = omaParser.parse(config.getMoTree(), OMAConstants.PPS_URN);
601             List<HomeSP> spList = MOManager.buildSPs(mMOTree);
602             if (spList.size() != 1) {
603                 throw new OMAException("Expected exactly one HomeSP, got " + spList.size());
604             }
605             mHomeSP = spList.iterator().next();
606         }
607 
getWifiConfiguration()608         public WifiConfiguration getWifiConfiguration() {
609             return mWifiConfiguration;
610         }
611 
getHomeSP()612         public HomeSP getHomeSP() {
613             return mHomeSP;
614         }
615 
getmMOTree()616         public MOTree getmMOTree() {
617             return mMOTree;
618         }
619     }
620 }
621