Home | History | Annotate | Download | only in flow
      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 
     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 
     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 
    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 
    204     public KeyStore getKeyStore() {
    205         return mKeyStore;
    206     }
    207 
    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      */
    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      */
    272     public KeyManager getKeyManager(HomeSP homeSP) throws IOException {
    273         return homeSP != null
    274                 ? new ClientKeyManager(homeSP, mKeyStore) : new WiFiKeyManager(mKeyStore);
    275     }
    276 
    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 
    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 
    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 
    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 
    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 
    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 
    442     public void provisioningFailed(String spName, String message) {
    443         notifyUser(OSUOperationStatus.ProvisioningFailure, message, spName);
    444     }
    445 
    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 
    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 
    497     private WifiConfiguration getWifiConfig(HomeSP homeSP) {
    498         PasspointConfig passpointConfig = mPasspointConfigs.get(homeSP.getFQDN());
    499         return passpointConfig != null ? passpointConfig.getWifiConfiguration() : null;
    500     }
    501 
    502     public MOTree getMOTree(HomeSP homeSP) {
    503         PasspointConfig config = mPasspointConfigs.get(homeSP.getFQDN());
    504         return config != null ? config.getmMOTree() : null;
    505     }
    506 
    507     public HomeSP getHomeSP(String fqdn) {
    508         PasspointConfig passpointConfig = mPasspointConfigs.get(fqdn);
    509         return passpointConfig != null ? passpointConfig.getHomeSP() : null;
    510     }
    511 
    512     public HomeSP getCurrentSP() {
    513         PasspointConfig passpointConfig = getActivePasspointConfig();
    514         return passpointConfig != null ? passpointConfig.getHomeSP() : null;
    515     }
    516 
    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 
    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 
    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 
    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 
    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 
    564     public WifiInfo getConnectionInfo() {
    565         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
    566         return wifiManager.getConnectionInfo();
    567     }
    568 
    569     public Network getCurrentNetwork() {
    570         WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
    571         return wifiManager.getCurrentNetwork();
    572     }
    573 
    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 
    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 
    608         public WifiConfiguration getWifiConfiguration() {
    609             return mWifiConfiguration;
    610         }
    611 
    612         public HomeSP getHomeSP() {
    613             return mHomeSP;
    614         }
    615 
    616         public MOTree getmMOTree() {
    617             return mMOTree;
    618         }
    619     }
    620 }
    621