summaryrefslogtreecommitdiff
path: root/com/android/server/wifi/WifiBackupDataV1Parser.java
diff options
context:
space:
mode:
Diffstat (limited to 'com/android/server/wifi/WifiBackupDataV1Parser.java')
-rw-r--r--com/android/server/wifi/WifiBackupDataV1Parser.java533
1 files changed, 533 insertions, 0 deletions
diff --git a/com/android/server/wifi/WifiBackupDataV1Parser.java b/com/android/server/wifi/WifiBackupDataV1Parser.java
new file mode 100644
index 00000000..57573213
--- /dev/null
+++ b/com/android/server/wifi/WifiBackupDataV1Parser.java
@@ -0,0 +1,533 @@
+/*
+ * Copyright (C) 2018 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 com.android.server.wifi;
+
+import android.net.IpConfiguration;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
+import android.net.LinkAddress;
+import android.net.NetworkUtils;
+import android.net.ProxyInfo;
+import android.net.RouteInfo;
+import android.net.StaticIpConfiguration;
+import android.net.wifi.WifiConfiguration;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.server.wifi.util.XmlUtil;
+import com.android.server.wifi.util.XmlUtil.IpConfigurationXmlUtil;
+import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Parser for major version 1 of WiFi backup data.
+ * Contains whitelists of tags for WifiConfiguration and IpConfiguration sections for each of
+ * the minor versions.
+ *
+ * Overall structure of the major version 1 XML schema:
+ * <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
+ * <WifiConfigStore>
+ * <float name="Version" value="1.0" />
+ * <NetworkList>
+ * <Network>
+ * <WifiConfiguration>
+ * <string name="ConfigKey">value</string>
+ * <string name="SSID">value</string>
+ * <string name="BSSID" />value</string>
+ * <string name="PreSharedKey" />value</string>
+ * <string-array name="WEPKeys" num="4">
+ * <item value="WifiConfigStoreWep1" />
+ * <item value="WifiConfigStoreWep2" />
+ * <item value="WifiConfigStoreWep3" />
+ * <item value="WifiConfigStoreWep3" />
+ * </string-array>
+ * ... (other supported tag names in minor version 1: "WEPTxKeyIndex", "HiddenSSID",
+ * "RequirePMF", "AllowedKeyMgmt", "AllowedProtocols", "AllowedAuthAlgos",
+ * "AllowedGroupCiphers", "AllowedPairwiseCiphers", "Shared")
+ * </WifiConfiguration>
+ * <IpConfiguration>
+ * <string name="IpAssignment">value</string>
+ * <string name="ProxySettings">value</string>
+ * ... (other supported tag names in minor version 1: "LinkAddress", "LinkPrefixLength",
+ * "GatewayAddress", "DNSServers", "ProxyHost", "ProxyPort", "ProxyPac",
+ * "ProxyExclusionList")
+ * </IpConfiguration>
+ * </Network>
+ * <Network>
+ * ... (format as above)
+ * </Network>
+ * </NetworkList>
+ * </WifiConfigStore>
+ */
+class WifiBackupDataV1Parser implements WifiBackupDataParser {
+
+ private static final String TAG = "WifiBackupDataV1Parser";
+
+ private static final int HIGHEST_SUPPORTED_MINOR_VERSION = 0;
+
+ // List of tags supported for <WifiConfiguration> section in minor version 0
+ private static final Set<String> WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS =
+ new HashSet<String>(Arrays.asList(new String[] {
+ WifiConfigurationXmlUtil.XML_TAG_CONFIG_KEY,
+ WifiConfigurationXmlUtil.XML_TAG_SSID,
+ WifiConfigurationXmlUtil.XML_TAG_BSSID,
+ WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY,
+ WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS,
+ WifiConfigurationXmlUtil.XML_TAG_WEP_TX_KEY_INDEX,
+ WifiConfigurationXmlUtil.XML_TAG_HIDDEN_SSID,
+ WifiConfigurationXmlUtil.XML_TAG_REQUIRE_PMF,
+ WifiConfigurationXmlUtil.XML_TAG_ALLOWED_KEY_MGMT,
+ WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PROTOCOLS,
+ WifiConfigurationXmlUtil.XML_TAG_ALLOWED_AUTH_ALGOS,
+ WifiConfigurationXmlUtil.XML_TAG_ALLOWED_GROUP_CIPHERS,
+ WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PAIRWISE_CIPHERS,
+ WifiConfigurationXmlUtil.XML_TAG_SHARED,
+ }));
+
+ // List of tags supported for <IpConfiguration> section in minor version 0
+ private static final Set<String> IP_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS =
+ new HashSet<String>(Arrays.asList(new String[] {
+ IpConfigurationXmlUtil.XML_TAG_IP_ASSIGNMENT,
+ IpConfigurationXmlUtil.XML_TAG_LINK_ADDRESS,
+ IpConfigurationXmlUtil.XML_TAG_LINK_PREFIX_LENGTH,
+ IpConfigurationXmlUtil.XML_TAG_GATEWAY_ADDRESS,
+ IpConfigurationXmlUtil.XML_TAG_DNS_SERVER_ADDRESSES,
+ IpConfigurationXmlUtil.XML_TAG_PROXY_SETTINGS,
+ IpConfigurationXmlUtil.XML_TAG_PROXY_HOST,
+ IpConfigurationXmlUtil.XML_TAG_PROXY_PORT,
+ IpConfigurationXmlUtil.XML_TAG_PROXY_EXCLUSION_LIST,
+ IpConfigurationXmlUtil.XML_TAG_PROXY_PAC_FILE,
+ }));
+
+ public List<WifiConfiguration> parseNetworkConfigurationsFromXml(XmlPullParser in,
+ int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException {
+ // clamp down the minorVersion to the highest one that this parser version supports
+ if (minorVersion > HIGHEST_SUPPORTED_MINOR_VERSION) {
+ minorVersion = HIGHEST_SUPPORTED_MINOR_VERSION;
+ }
+ // Find the configuration list section.
+ XmlUtil.gotoNextSectionWithName(in, WifiBackupRestore.XML_TAG_SECTION_HEADER_NETWORK_LIST,
+ outerTagDepth);
+ // Find all the configurations within the configuration list section.
+ int networkListTagDepth = outerTagDepth + 1;
+ List<WifiConfiguration> configurations = new ArrayList<>();
+ while (XmlUtil.gotoNextSectionWithNameOrEnd(
+ in, WifiBackupRestore.XML_TAG_SECTION_HEADER_NETWORK, networkListTagDepth)) {
+ WifiConfiguration configuration =
+ parseNetworkConfigurationFromXml(in, minorVersion, networkListTagDepth);
+ if (configuration != null) {
+ Log.v(TAG, "Parsed Configuration: " + configuration.configKey());
+ configurations.add(configuration);
+ }
+ }
+ return configurations;
+ }
+
+ /**
+ * Parses the configuration data elements from the provided XML stream to a Configuration.
+ *
+ * @param in XmlPullParser instance pointing to the XML stream.
+ * @param minorVersion minor version number parsed from incoming data.
+ * @param outerTagDepth depth of the outer tag in the XML document.
+ * @return WifiConfiguration object if parsing is successful, null otherwise.
+ */
+ private WifiConfiguration parseNetworkConfigurationFromXml(XmlPullParser in, int minorVersion,
+ int outerTagDepth) throws XmlPullParserException, IOException {
+ WifiConfiguration configuration = null;
+ int networkTagDepth = outerTagDepth + 1;
+ // Retrieve WifiConfiguration object first.
+ XmlUtil.gotoNextSectionWithName(
+ in, WifiBackupRestore.XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION,
+ networkTagDepth);
+ int configTagDepth = networkTagDepth + 1;
+ configuration = parseWifiConfigurationFromXmlAndValidateConfigKey(in, configTagDepth,
+ minorVersion);
+ if (configuration == null) {
+ return null;
+ }
+ // Now retrieve any IP configuration info.
+ XmlUtil.gotoNextSectionWithName(
+ in, WifiBackupRestore.XML_TAG_SECTION_HEADER_IP_CONFIGURATION, networkTagDepth);
+ IpConfiguration ipConfiguration = parseIpConfigurationFromXml(in, configTagDepth,
+ minorVersion);
+ configuration.setIpConfiguration(ipConfiguration);
+ return configuration;
+ }
+
+ /**
+ * Helper method to parse the WifiConfiguration object and validate the configKey parsed.
+ */
+ private WifiConfiguration parseWifiConfigurationFromXmlAndValidateConfigKey(XmlPullParser in,
+ int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException {
+ Pair<String, WifiConfiguration> parsedConfig =
+ parseWifiConfigurationFromXml(in, outerTagDepth, minorVersion);
+ if (parsedConfig == null || parsedConfig.first == null || parsedConfig.second == null) {
+ return null;
+ }
+ String configKeyParsed = parsedConfig.first;
+ WifiConfiguration configuration = parsedConfig.second;
+ String configKeyCalculated = configuration.configKey();
+ if (!configKeyParsed.equals(configKeyCalculated)) {
+ String configKeyMismatchLog =
+ "Configuration key does not match. Retrieved: " + configKeyParsed
+ + ", Calculated: " + configKeyCalculated;
+ if (configuration.shared) {
+ Log.e(TAG, configKeyMismatchLog);
+ return null;
+ } else {
+ // ConfigKey mismatches are expected for private networks because the
+ // UID is not preserved across backup/restore.
+ Log.w(TAG, configKeyMismatchLog);
+ }
+ }
+ return configuration;
+ }
+
+ /**
+ * Parses the configuration data elements from the provided XML stream to a
+ * WifiConfiguration object.
+ * Looping through the tags makes it easy to add elements in the future minor versions if
+ * needed. Unsupported elements will be ignored.
+ *
+ * @param in XmlPullParser instance pointing to the XML stream.
+ * @param outerTagDepth depth of the outer tag in the XML document.
+ * @param minorVersion minor version number parsed from incoming data.
+ * @return Pair<Config key, WifiConfiguration object> if parsing is successful, null otherwise.
+ */
+ private static Pair<String, WifiConfiguration> parseWifiConfigurationFromXml(XmlPullParser in,
+ int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException {
+ WifiConfiguration configuration = new WifiConfiguration();
+ String configKeyInData = null;
+ Set<String> supportedTags = getSupportedWifiConfigurationTags(minorVersion);
+
+ // Loop through and parse out all the elements from the stream within this section.
+ while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
+ String[] valueName = new String[1];
+ Object value = XmlUtil.readCurrentValue(in, valueName);
+ String tagName = valueName[0];
+ if (tagName == null) {
+ throw new XmlPullParserException("Missing value name");
+ }
+
+ // ignore the tags that are not supported up until the current minor version
+ if (!supportedTags.contains(tagName)) {
+ Log.w(TAG, "Unsupported tag + \"" + tagName + "\" found in <WifiConfiguration>"
+ + " section, ignoring.");
+ continue;
+ }
+
+ // note: the below switch case list should contain all tags supported up until the
+ // highest minor version supported by this parser
+ switch (tagName) {
+ case WifiConfigurationXmlUtil.XML_TAG_CONFIG_KEY:
+ configKeyInData = (String) value;
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_SSID:
+ configuration.SSID = (String) value;
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_BSSID:
+ configuration.BSSID = (String) value;
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_PRE_SHARED_KEY:
+ configuration.preSharedKey = (String) value;
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_WEP_KEYS:
+ populateWepKeysFromXmlValue(value, configuration.wepKeys);
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_WEP_TX_KEY_INDEX:
+ configuration.wepTxKeyIndex = (int) value;
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_HIDDEN_SSID:
+ configuration.hiddenSSID = (boolean) value;
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_REQUIRE_PMF:
+ configuration.requirePMF = (boolean) value;
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_KEY_MGMT:
+ byte[] allowedKeyMgmt = (byte[]) value;
+ configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt);
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PROTOCOLS:
+ byte[] allowedProtocols = (byte[]) value;
+ configuration.allowedProtocols = BitSet.valueOf(allowedProtocols);
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_AUTH_ALGOS:
+ byte[] allowedAuthAlgorithms = (byte[]) value;
+ configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms);
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_GROUP_CIPHERS:
+ byte[] allowedGroupCiphers = (byte[]) value;
+ configuration.allowedGroupCiphers = BitSet.valueOf(allowedGroupCiphers);
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_ALLOWED_PAIRWISE_CIPHERS:
+ byte[] allowedPairwiseCiphers = (byte[]) value;
+ configuration.allowedPairwiseCiphers =
+ BitSet.valueOf(allowedPairwiseCiphers);
+ break;
+ case WifiConfigurationXmlUtil.XML_TAG_SHARED:
+ configuration.shared = (boolean) value;
+ break;
+ default:
+ // should never happen, since other tags are filtered out earlier
+ throw new XmlPullParserException(
+ "Unknown value name found: " + valueName[0]);
+ }
+ }
+ return Pair.create(configKeyInData, configuration);
+ }
+
+ /**
+ * Returns a set of supported tags of <WifiConfiguration> element for all minor versions of
+ * this major version up to and including the specified minorVersion (only adding tags is
+ * supported in minor versions, removal or changing the meaning of tags requires bumping
+ * the major version and reseting the minor to 0).
+ *
+ * @param minorVersion minor version number parsed from incoming data.
+ */
+ private static Set<String> getSupportedWifiConfigurationTags(int minorVersion) {
+ switch (minorVersion) {
+ case 0: return WIFI_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS;
+ default:
+ Log.e(TAG, "Invalid minorVersion: " + minorVersion);
+ return Collections.<String>emptySet();
+ }
+ }
+
+ /**
+ * Populate wepKeys array elements only if they were non-empty in the backup data.
+ *
+ * @throws XmlPullParserException if parsing errors occur.
+ */
+ private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys)
+ throws XmlPullParserException, IOException {
+ String[] wepKeysInData = (String[]) value;
+ if (wepKeysInData == null) {
+ return;
+ }
+ if (wepKeysInData.length != wepKeys.length) {
+ throw new XmlPullParserException(
+ "Invalid Wep Keys length: " + wepKeysInData.length);
+ }
+ for (int i = 0; i < wepKeys.length; i++) {
+ if (wepKeysInData[i].isEmpty()) {
+ wepKeys[i] = null;
+ } else {
+ wepKeys[i] = wepKeysInData[i];
+ }
+ }
+ }
+
+ /**
+ * Parses the IP configuration data elements from the provided XML stream to an
+ * IpConfiguration object.
+ *
+ * @param in XmlPullParser instance pointing to the XML stream.
+ * @param outerTagDepth depth of the outer tag in the XML document.
+ * @param minorVersion minor version number parsed from incoming data.
+ * @return IpConfiguration object if parsing is successful, null otherwise.
+ */
+ private static IpConfiguration parseIpConfigurationFromXml(XmlPullParser in,
+ int outerTagDepth, int minorVersion) throws XmlPullParserException, IOException {
+ // First parse *all* of the tags in <IpConfiguration> section
+ Set<String> supportedTags = getSupportedIpConfigurationTags(minorVersion);
+
+ String ipAssignmentString = null;
+ String linkAddressString = null;
+ Integer linkPrefixLength = null;
+ String gatewayAddressString = null;
+ String[] dnsServerAddressesString = null;
+ String proxySettingsString = null;
+ String proxyHost = null;
+ int proxyPort = -1;
+ String proxyExclusionList = null;
+ String proxyPacFile = null;
+
+ // Loop through and parse out all the elements from the stream within this section.
+ while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
+ String[] valueName = new String[1];
+ Object value = XmlUtil.readCurrentValue(in, valueName);
+ String tagName = valueName[0];
+ if (tagName == null) {
+ throw new XmlPullParserException("Missing value name");
+ }
+
+ // ignore the tags that are not supported up until the current minor version
+ if (!supportedTags.contains(tagName)) {
+ Log.w(TAG, "Unsupported tag + \"" + tagName + "\" found in <IpConfiguration>"
+ + " section, ignoring.");
+ continue;
+ }
+
+ // note: the below switch case list should contain all tags supported up until the
+ // highest minor version supported by this parser
+ // should any tags be added in next minor versions, conditional processing of them
+ // also needs to be added in the below code (processing into IpConfiguration object)
+ switch (tagName) {
+ case IpConfigurationXmlUtil.XML_TAG_IP_ASSIGNMENT:
+ ipAssignmentString = (String) value;
+ break;
+ case IpConfigurationXmlUtil.XML_TAG_LINK_ADDRESS:
+ linkAddressString = (String) value;
+ break;
+ case IpConfigurationXmlUtil.XML_TAG_LINK_PREFIX_LENGTH:
+ linkPrefixLength = (Integer) value;
+ break;
+ case IpConfigurationXmlUtil.XML_TAG_GATEWAY_ADDRESS:
+ gatewayAddressString = (String) value;
+ break;
+ case IpConfigurationXmlUtil.XML_TAG_DNS_SERVER_ADDRESSES:
+ dnsServerAddressesString = (String[]) value;
+ break;
+ case IpConfigurationXmlUtil.XML_TAG_PROXY_SETTINGS:
+ proxySettingsString = (String) value;
+ break;
+ case IpConfigurationXmlUtil.XML_TAG_PROXY_HOST:
+ proxyHost = (String) value;
+ break;
+ case IpConfigurationXmlUtil.XML_TAG_PROXY_PORT:
+ proxyPort = (int) value;
+ break;
+ case IpConfigurationXmlUtil.XML_TAG_PROXY_EXCLUSION_LIST:
+ proxyExclusionList = (String) value;
+ break;
+ case IpConfigurationXmlUtil.XML_TAG_PROXY_PAC_FILE:
+ proxyPacFile = (String) value;
+ break;
+ default:
+ // should never happen, since other tags are filtered out earlier
+ throw new XmlPullParserException(
+ "Unknown value name found: " + valueName[0]);
+ }
+ }
+
+ // Now process the values into IpConfiguration object
+ IpConfiguration ipConfiguration = new IpConfiguration();
+ if (ipAssignmentString == null) {
+ throw new XmlPullParserException("IpAssignment was missing in IpConfiguration section");
+ }
+ IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString);
+ ipConfiguration.setIpAssignment(ipAssignment);
+ switch (ipAssignment) {
+ case STATIC:
+ StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration();
+ if (linkAddressString != null && linkPrefixLength != null) {
+ LinkAddress linkAddress = new LinkAddress(
+ NetworkUtils.numericToInetAddress(linkAddressString), linkPrefixLength);
+ if (linkAddress.getAddress() instanceof Inet4Address) {
+ staticIpConfiguration.ipAddress = linkAddress;
+ } else {
+ Log.w(TAG, "Non-IPv4 address: " + linkAddress);
+ }
+ }
+ if (gatewayAddressString != null) {
+ LinkAddress dest = null;
+ InetAddress gateway = NetworkUtils.numericToInetAddress(gatewayAddressString);
+ RouteInfo route = new RouteInfo(dest, gateway);
+ if (route.isIPv4Default()) {
+ staticIpConfiguration.gateway = gateway;
+ } else {
+ Log.w(TAG, "Non-IPv4 default route: " + route);
+ }
+ }
+ if (dnsServerAddressesString != null) {
+ for (String dnsServerAddressString : dnsServerAddressesString) {
+ InetAddress dnsServerAddress =
+ NetworkUtils.numericToInetAddress(dnsServerAddressString);
+ staticIpConfiguration.dnsServers.add(dnsServerAddress);
+ }
+ }
+ ipConfiguration.setStaticIpConfiguration(staticIpConfiguration);
+ break;
+ case DHCP:
+ case UNASSIGNED:
+ break;
+ default:
+ throw new XmlPullParserException("Unknown ip assignment type: " + ipAssignment);
+ }
+
+ // Process the proxy settings next
+ if (proxySettingsString == null) {
+ throw new XmlPullParserException("ProxySettings was missing in"
+ + " IpConfiguration section");
+ }
+ ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString);
+ ipConfiguration.setProxySettings(proxySettings);
+ switch (proxySettings) {
+ case STATIC:
+ if (proxyHost == null) {
+ throw new XmlPullParserException("ProxyHost was missing in"
+ + " IpConfiguration section");
+ }
+ if (proxyPort == -1) {
+ throw new XmlPullParserException("ProxyPort was missing in"
+ + " IpConfiguration section");
+ }
+ if (proxyExclusionList == null) {
+ throw new XmlPullParserException("ProxyExclusionList was missing in"
+ + " IpConfiguration section");
+ }
+ ipConfiguration.setHttpProxy(
+ new ProxyInfo(proxyHost, proxyPort, proxyExclusionList));
+ break;
+ case PAC:
+ if (proxyPacFile == null) {
+ throw new XmlPullParserException("ProxyPac was missing in"
+ + " IpConfiguration section");
+ }
+ ipConfiguration.setHttpProxy(new ProxyInfo(proxyPacFile));
+ break;
+ case NONE:
+ case UNASSIGNED:
+ break;
+ default:
+ throw new XmlPullParserException(
+ "Unknown proxy settings type: " + proxySettings);
+ }
+
+ return ipConfiguration;
+ }
+
+ /**
+ * Returns a set of supported tags of <IpConfiguration> element for all minor versions of
+ * this major version up to and including the specified minorVersion (only adding tags is
+ * supported in minor versions, removal or changing the meaning of tags requires bumping
+ * the major version and reseting the minor to 0).
+ *
+ * @param minorVersion minor version number parsed from incoming data.
+ */
+ private static Set<String> getSupportedIpConfigurationTags(int minorVersion) {
+ switch (minorVersion) {
+ case 0: return IP_CONFIGURATION_MINOR_V0_SUPPORTED_TAGS;
+ default:
+ Log.e(TAG, "Invalid minorVersion: " + minorVersion);
+ return Collections.<String>emptySet();
+ }
+ }
+}