diff options
author | Jaewan Kim <jaewan@google.com> | 2014-03-10 17:10:51 +0900 |
---|---|---|
committer | Jaewan Kim <jaewan@google.com> | 2014-04-07 11:35:35 +0900 |
commit | 1284767ceb1affa6d5af77fd26ccf7322df48a6d (patch) | |
tree | ea9d4fd6e31d3c7693af1d01466c9c2bac9a4540 | |
parent | 59f0258a27ebaf8468919a9d2855c41f0429238d (diff) | |
download | frameworks_base-1284767ceb1affa6d5af77fd26ccf7322df48a6d.zip frameworks_base-1284767ceb1affa6d5af77fd26ccf7322df48a6d.tar.gz frameworks_base-1284767ceb1affa6d5af77fd26ccf7322df48a6d.tar.bz2 |
Refactor IpConfiguration from WifiConfiguration
Bug: 7606609, Bug: 8687763
Change-Id: I736eb3c73a8ffc8f137a04a5ea66ee564dc2b530
5 files changed, 551 insertions, 81 deletions
diff --git a/core/java/android/net/IpConfigStore.java b/core/java/android/net/IpConfigStore.java new file mode 100644 index 0000000..4215826 --- /dev/null +++ b/core/java/android/net/IpConfigStore.java @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.net.IpConfiguration.IpAssignment; +import android.net.IpConfiguration.ProxySettings; +import android.os.Handler; +import android.os.HandlerThread; +import android.text.TextUtils; +import android.util.Log; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.EOFException; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.util.HashMap; +import java.util.Map; + +public class IpConfigStore { + private static final String TAG = "IpConfigStore"; + private static final boolean DBG = true; + + /* IP and proxy configuration keys */ + protected static final String ID_KEY = "id"; + protected static final String IP_ASSIGNMENT_KEY = "ipAssignment"; + protected static final String LINK_ADDRESS_KEY = "linkAddress"; + protected static final String GATEWAY_KEY = "gateway"; + protected static final String DNS_KEY = "dns"; + protected static final String PROXY_SETTINGS_KEY = "proxySettings"; + protected static final String PROXY_HOST_KEY = "proxyHost"; + protected static final String PROXY_PORT_KEY = "proxyPort"; + protected static final String PROXY_PAC_FILE = "proxyPac"; + protected static final String EXCLUSION_LIST_KEY = "exclusionList"; + protected static final String EOS = "eos"; + + private static final int IPCONFIG_FILE_VERSION = 2; + + public IpConfigStore() { + } + + public void writeIpAndProxyConfigurations( + String configFilePath, Map<Integer, IpConfiguration> networks) { + DelayedDiskWrite.write(configFilePath, networks); + } + + private static class DelayedDiskWrite { + private static HandlerThread sDiskWriteHandlerThread; + private static Handler sDiskWriteHandler; + /* Tracks multiple writes on the same thread */ + private static int sWriteSequence = 0; + private static final String TAG = "DelayedDiskWrite"; + + static void write (final String configFilePath, + final Map<Integer, IpConfiguration> networks) { + if (TextUtils.isEmpty(configFilePath)) { + return; + } + + /* Do a delayed write to disk on a separate handler thread */ + synchronized (DelayedDiskWrite.class) { + if (++sWriteSequence == 1) { + sDiskWriteHandlerThread = new HandlerThread("IpConfigStoreThread"); + sDiskWriteHandlerThread.start(); + sDiskWriteHandler = new Handler(sDiskWriteHandlerThread.getLooper()); + } + } + + sDiskWriteHandler.post(new Runnable() { + @Override + public void run() { + onWriteCalled(configFilePath, networks); + } + }); + } + + private static void onWriteCalled( + final String configFilePath, Map<Integer, IpConfiguration> networks) { + + DataOutputStream out = null; + try { + out = new DataOutputStream(new BufferedOutputStream( + new FileOutputStream(configFilePath))); + + out.writeInt(IPCONFIG_FILE_VERSION); + + for (Integer id : networks.keySet()) { + IpConfiguration config = networks.get(id); + boolean writeToFile = false; + + try { + LinkProperties linkProperties = config.linkProperties; + switch (config.ipAssignment) { + case STATIC: + out.writeUTF(IP_ASSIGNMENT_KEY); + out.writeUTF(config.ipAssignment.toString()); + for (LinkAddress linkAddr : linkProperties.getLinkAddresses()) { + out.writeUTF(LINK_ADDRESS_KEY); + out.writeUTF(linkAddr.getAddress().getHostAddress()); + out.writeInt(linkAddr.getNetworkPrefixLength()); + } + for (RouteInfo route : linkProperties.getRoutes()) { + out.writeUTF(GATEWAY_KEY); + LinkAddress dest = route.getDestination(); + if (dest != null) { + out.writeInt(1); + out.writeUTF(dest.getAddress().getHostAddress()); + out.writeInt(dest.getNetworkPrefixLength()); + } else { + out.writeInt(0); + } + if (route.getGateway() != null) { + out.writeInt(1); + out.writeUTF(route.getGateway().getHostAddress()); + } else { + out.writeInt(0); + } + } + for (InetAddress inetAddr : linkProperties.getDnses()) { + out.writeUTF(DNS_KEY); + out.writeUTF(inetAddr.getHostAddress()); + } + writeToFile = true; + break; + case DHCP: + out.writeUTF(IP_ASSIGNMENT_KEY); + out.writeUTF(config.ipAssignment.toString()); + writeToFile = true; + break; + case UNASSIGNED: + /* Ignore */ + break; + default: + loge("Ignore invalid ip assignment while writing"); + break; + } + + switch (config.proxySettings) { + case STATIC: + ProxyProperties proxyProperties = linkProperties.getHttpProxy(); + String exclusionList = proxyProperties.getExclusionList(); + out.writeUTF(PROXY_SETTINGS_KEY); + out.writeUTF(config.proxySettings.toString()); + out.writeUTF(PROXY_HOST_KEY); + out.writeUTF(proxyProperties.getHost()); + out.writeUTF(PROXY_PORT_KEY); + out.writeInt(proxyProperties.getPort()); + out.writeUTF(EXCLUSION_LIST_KEY); + out.writeUTF(exclusionList); + writeToFile = true; + break; + case PAC: + ProxyProperties proxyPacProperties = linkProperties.getHttpProxy(); + out.writeUTF(PROXY_SETTINGS_KEY); + out.writeUTF(config.proxySettings.toString()); + out.writeUTF(PROXY_PAC_FILE); + out.writeUTF(proxyPacProperties.getPacFileUrl()); + writeToFile = true; + break; + case NONE: + out.writeUTF(PROXY_SETTINGS_KEY); + out.writeUTF(config.proxySettings.toString()); + writeToFile = true; + break; + case UNASSIGNED: + /* Ignore */ + break; + default: + loge("Ignore invalid proxy settings while writing"); + break; + } + if (writeToFile) { + out.writeUTF(ID_KEY); + out.writeInt(id); + } + } catch (NullPointerException e) { + loge("Failure in writing " + config.linkProperties + e); + } + out.writeUTF(EOS); + } + + } catch (IOException e) { + loge("Error writing data file " + configFilePath); + } finally { + if (out != null) { + try { + out.close(); + } catch (Exception e) {} + } + + //Quit if no more writes sent + synchronized (DelayedDiskWrite.class) { + if (--sWriteSequence == 0) { + sDiskWriteHandler.getLooper().quit(); + sDiskWriteHandler = null; + sDiskWriteHandlerThread = null; + } + } + } + } + + private static void loge(String s) { + Log.e(TAG, s); + } + } + + public Map<Integer, IpConfiguration> readIpAndProxyConfigurations( + final String configFilePath) { + Map<Integer, IpConfiguration> networks = new HashMap<Integer, IpConfiguration>(); + + DataInputStream in = null; + try { + in = new DataInputStream(new BufferedInputStream(new FileInputStream( + configFilePath))); + + int version = in.readInt(); + if (version != 2 && version != 1) { + loge("Bad version on IP configuration file, ignore read"); + return null; + } + + while (true) { + int id = -1; + // Default is DHCP with no proxy + IpAssignment ipAssignment = IpAssignment.DHCP; + ProxySettings proxySettings = ProxySettings.NONE; + LinkProperties linkProperties = new LinkProperties(); + String proxyHost = null; + String pacFileUrl = null; + int proxyPort = -1; + String exclusionList = null; + String key; + + do { + key = in.readUTF(); + try { + if (key.equals(ID_KEY)) { + id = in.readInt(); + } else if (key.equals(IP_ASSIGNMENT_KEY)) { + ipAssignment = IpAssignment.valueOf(in.readUTF()); + } else if (key.equals(LINK_ADDRESS_KEY)) { + LinkAddress linkAddr = new LinkAddress( + NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt()); + linkProperties.addLinkAddress(linkAddr); + } else if (key.equals(GATEWAY_KEY)) { + LinkAddress dest = null; + InetAddress gateway = null; + if (version == 1) { + // only supported default gateways - leave the dest/prefix empty + gateway = NetworkUtils.numericToInetAddress(in.readUTF()); + } else { + if (in.readInt() == 1) { + dest = new LinkAddress( + NetworkUtils.numericToInetAddress(in.readUTF()), + in.readInt()); + } + if (in.readInt() == 1) { + gateway = NetworkUtils.numericToInetAddress(in.readUTF()); + } + } + linkProperties.addRoute(new RouteInfo(dest, gateway)); + } else if (key.equals(DNS_KEY)) { + linkProperties.addDns( + NetworkUtils.numericToInetAddress(in.readUTF())); + } else if (key.equals(PROXY_SETTINGS_KEY)) { + proxySettings = ProxySettings.valueOf(in.readUTF()); + } else if (key.equals(PROXY_HOST_KEY)) { + proxyHost = in.readUTF(); + } else if (key.equals(PROXY_PORT_KEY)) { + proxyPort = in.readInt(); + } else if (key.equals(PROXY_PAC_FILE)) { + pacFileUrl = in.readUTF(); + } else if (key.equals(EXCLUSION_LIST_KEY)) { + exclusionList = in.readUTF(); + } else if (key.equals(EOS)) { + break; + } else { + loge("Ignore unknown key " + key + "while reading"); + } + } catch (IllegalArgumentException e) { + loge("Ignore invalid address while reading" + e); + } + } while (true); + + if (id != -1) { + IpConfiguration config = new IpConfiguration(); + networks.put(id, config); + + config.linkProperties = linkProperties; + switch (ipAssignment) { + case STATIC: + case DHCP: + config.ipAssignment = ipAssignment; + break; + case UNASSIGNED: + loge("BUG: Found UNASSIGNED IP on file, use DHCP"); + config.ipAssignment = IpAssignment.DHCP; + break; + default: + loge("Ignore invalid ip assignment while reading."); + config.ipAssignment = IpAssignment.UNASSIGNED; + break; + } + + switch (proxySettings) { + case STATIC: + config.proxySettings = proxySettings; + ProxyProperties proxyProperties = + new ProxyProperties(proxyHost, proxyPort, exclusionList); + linkProperties.setHttpProxy(proxyProperties); + break; + case PAC: + config.proxySettings = proxySettings; + ProxyProperties proxyPacProperties = + new ProxyProperties(pacFileUrl); + linkProperties.setHttpProxy(proxyPacProperties); + break; + case NONE: + config.proxySettings = proxySettings; + break; + case UNASSIGNED: + loge("BUG: Found UNASSIGNED proxy on file, use NONE"); + config.proxySettings = ProxySettings.NONE; + break; + default: + loge("Ignore invalid proxy settings while reading"); + config.proxySettings = ProxySettings.UNASSIGNED; + break; + } + } else { + if (DBG) log("Missing id while parsing configuration"); + } + } + } catch (EOFException ignore) { + } catch (IOException e) { + loge("Error parsing configuration" + e); + } finally { + if (in != null) { + try { + in.close(); + } catch (Exception e) {} + } + } + + return networks; + } + + protected void loge(String s) { + Log.e(TAG, s); + } + + protected void log(String s) { + Log.d(TAG, s); + } +} diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java new file mode 100644 index 0000000..7f835e4 --- /dev/null +++ b/core/java/android/net/IpConfiguration.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net; + +import android.net.LinkProperties; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +/** + * A class representing a configured network. + */ +public class IpConfiguration implements Parcelable { + private static final String TAG = "IpConfiguration"; + + /** + * @hide + */ + public enum IpAssignment { + /* Use statically configured IP settings. Configuration can be accessed + * with linkProperties */ + STATIC, + /* Use dynamically configured IP settigns */ + DHCP, + /* no IP details are assigned, this is used to indicate + * that any existing IP settings should be retained */ + UNASSIGNED + } + + /** + * @hide + */ + public IpAssignment ipAssignment; + + /** + * @hide + */ + public enum ProxySettings { + /* No proxy is to be used. Any existing proxy settings + * should be cleared. */ + NONE, + /* Use statically configured proxy. Configuration can be accessed + * with linkProperties */ + STATIC, + /* no proxy details are assigned, this is used to indicate + * that any existing proxy settings should be retained */ + UNASSIGNED, + /* Use a Pac based proxy. + */ + PAC + } + + /** + * @hide + */ + public ProxySettings proxySettings; + + /** + * @hide + */ + public LinkProperties linkProperties; + + public IpConfiguration() { + ipAssignment = IpAssignment.UNASSIGNED; + proxySettings = ProxySettings.UNASSIGNED; + linkProperties = new LinkProperties(); + } + + /** copy constructor {@hide} */ + public IpConfiguration(IpConfiguration source) { + if (source != null) { + ipAssignment = source.ipAssignment; + proxySettings = source.proxySettings; + linkProperties = new LinkProperties(source.linkProperties); + } + } + + public static IpConfiguration createDefaultConfiguration() { + IpConfiguration config = new IpConfiguration(); + config.ipAssignment = IpAssignment.DHCP; + config.proxySettings = ProxySettings.NONE; + return config; + } + + public void mergeFrom(IpConfiguration source) { + if (source == null) { + Log.e(TAG, "source is null"); + return; + } + + linkProperties = source.linkProperties; + if (source.ipAssignment != IpAssignment.UNASSIGNED) { + ipAssignment = source.ipAssignment; + } + if (source.proxySettings != ProxySettings.UNASSIGNED) { + proxySettings = source.proxySettings; + } + } + + @Override + public String toString() { + StringBuilder sbuf = new StringBuilder(); + sbuf.append("IP assignment: " + ipAssignment.toString()); + sbuf.append("\n"); + sbuf.append("Proxy settings: " + proxySettings.toString()); + sbuf.append("\n"); + sbuf.append(linkProperties.toString()); + sbuf.append("\n"); + + return sbuf.toString(); + } + + /** Implement the Parcelable interface {@hide} */ + public int describeContents() { + return 0; + } + + /** Implement the Parcelable interface {@hide} */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(ipAssignment.name()); + dest.writeString(proxySettings.name()); + dest.writeParcelable(linkProperties, flags); + } + + /** Implement the Parcelable interface {@hide} */ + public static final Creator<IpConfiguration> CREATOR = + new Creator<IpConfiguration>() { + public IpConfiguration createFromParcel(Parcel in) { + IpConfiguration config = new IpConfiguration(); + config.setFromParcel(in); + return config; + } + + public IpConfiguration[] newArray(int size) { + return new IpConfiguration[size]; + } + }; + + protected void setFromParcel(Parcel in) { + ipAssignment = IpAssignment.valueOf(in.readString()); + proxySettings = ProxySettings.valueOf(in.readString()); + linkProperties = in.readParcelable(null); + } +} diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java index cad030a..2ce87eb 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java @@ -23,15 +23,15 @@ import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; +import android.net.IpConfiguration.IpAssignment; +import android.net.IpConfiguration.ProxySettings; +import android.net.LinkAddress; +import android.net.LinkProperties; +import android.net.RouteInfo; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.AuthAlgorithm; -import android.net.wifi.WifiConfiguration.IpAssignment; import android.net.wifi.WifiConfiguration.KeyMgmt; -import android.net.wifi.WifiConfiguration.ProxySettings; import android.net.wifi.WifiEnterpriseConfig; -import android.net.LinkAddress; -import android.net.LinkProperties; -import android.net.RouteInfo; import java.io.InputStream; import java.net.InetAddress; diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java index 91c3093..9692ec0 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java @@ -18,12 +18,12 @@ package com.android.connectivitymanagertest.stress; import android.content.Context; import android.net.ConnectivityManager; +import android.net.IpConfiguration.IpAssignment; +import android.net.IpConfiguration.ProxySettings; import android.net.NetworkInfo.State; import android.net.wifi.ScanResult; -import android.net.wifi.WifiConfiguration; -import android.net.wifi.WifiConfiguration.IpAssignment; import android.net.wifi.WifiConfiguration.KeyMgmt; -import android.net.wifi.WifiConfiguration.ProxySettings; +import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.os.Environment; import android.os.PowerManager; diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 6562462..9b5a0a4 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -16,8 +16,7 @@ package android.net.wifi; -import android.net.LinkProperties; -import android.os.Parcelable; +import android.net.IpConfiguration; import android.os.Parcel; import android.text.TextUtils; @@ -27,7 +26,7 @@ import java.util.BitSet; * A class representing a configured Wi-Fi network, including the * security configuration. */ -public class WifiConfiguration implements Parcelable { +public class WifiConfiguration extends IpConfiguration { private static final String TAG = "WifiConfiguration"; /** {@hide} */ public static final String ssidVarName = "ssid"; @@ -282,50 +281,6 @@ public class WifiConfiguration implements Parcelable { */ public WifiEnterpriseConfig enterpriseConfig; - /** - * @hide - */ - public enum IpAssignment { - /* Use statically configured IP settings. Configuration can be accessed - * with linkProperties */ - STATIC, - /* Use dynamically configured IP settigns */ - DHCP, - /* no IP details are assigned, this is used to indicate - * that any existing IP settings should be retained */ - UNASSIGNED - } - /** - * @hide - */ - public IpAssignment ipAssignment; - - /** - * @hide - */ - public enum ProxySettings { - /* No proxy is to be used. Any existing proxy settings - * should be cleared. */ - NONE, - /* Use statically configured proxy. Configuration can be accessed - * with linkProperties */ - STATIC, - /* no proxy details are assigned, this is used to indicate - * that any existing proxy settings should be retained */ - UNASSIGNED, - /* Use a Pac based proxy. - */ - PAC - } - /** - * @hide - */ - public ProxySettings proxySettings; - /** - * @hide - */ - public LinkProperties linkProperties; - public WifiConfiguration() { networkId = INVALID_NETWORK_ID; SSID = null; @@ -343,9 +298,6 @@ public class WifiConfiguration implements Parcelable { wepKeys[i] = null; } enterpriseConfig = new WifiEnterpriseConfig(); - ipAssignment = IpAssignment.UNASSIGNED; - proxySettings = ProxySettings.UNASSIGNED; - linkProperties = new LinkProperties(); } /** @@ -374,6 +326,7 @@ public class WifiConfiguration implements Parcelable { @Override public String toString() { StringBuilder sbuf = new StringBuilder(); + if (this.status == WifiConfiguration.Status.CURRENT) { sbuf.append("* "); } else if (this.status == WifiConfiguration.Status.DISABLED) { @@ -448,12 +401,8 @@ public class WifiConfiguration implements Parcelable { sbuf.append(enterpriseConfig); sbuf.append('\n'); - sbuf.append("IP assignment: " + ipAssignment.toString()); - sbuf.append("\n"); - sbuf.append("Proxy settings: " + proxySettings.toString()); - sbuf.append("\n"); - sbuf.append(linkProperties.toString()); - sbuf.append("\n"); + // Append IpConfiguration info here to keep old behavior. + sbuf.append(super.toString()); return sbuf.toString(); } @@ -570,13 +519,10 @@ public class WifiConfiguration implements Parcelable { return KeyMgmt.NONE; } - /** Implement the Parcelable interface {@hide} */ - public int describeContents() { - return 0; - } - /** copy constructor {@hide} */ public WifiConfiguration(WifiConfiguration source) { + super(source); + if (source != null) { networkId = source.networkId; status = source.status; @@ -600,15 +546,14 @@ public class WifiConfiguration implements Parcelable { allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); - - ipAssignment = source.ipAssignment; - proxySettings = source.proxySettings; - linkProperties = new LinkProperties(source.linkProperties); } } /** Implement the Parcelable interface {@hide} */ + @Override public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeInt(networkId); dest.writeInt(status); dest.writeInt(disableReason); @@ -629,10 +574,6 @@ public class WifiConfiguration implements Parcelable { writeBitSet(dest, allowedGroupCiphers); dest.writeParcelable(enterpriseConfig, flags); - - dest.writeString(ipAssignment.name()); - dest.writeString(proxySettings.name()); - dest.writeParcelable(linkProperties, flags); } /** Implement the Parcelable interface {@hide} */ @@ -640,6 +581,8 @@ public class WifiConfiguration implements Parcelable { new Creator<WifiConfiguration>() { public WifiConfiguration createFromParcel(Parcel in) { WifiConfiguration config = new WifiConfiguration(); + config.setFromParcel(in); + config.networkId = in.readInt(); config.status = in.readInt(); config.disableReason = in.readInt(); @@ -660,10 +603,6 @@ public class WifiConfiguration implements Parcelable { config.enterpriseConfig = in.readParcelable(null); - config.ipAssignment = IpAssignment.valueOf(in.readString()); - config.proxySettings = ProxySettings.valueOf(in.readString()); - config.linkProperties = in.readParcelable(null); - return config; } |