summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--wifi/Android.bp1
-rwxr-xr-xwifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java284
-rwxr-xr-xwifi/java/android/net/wifi/WifiMigration.java27
-rw-r--r--wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java199
4 files changed, 508 insertions, 3 deletions
diff --git a/wifi/Android.bp b/wifi/Android.bp
index 70c274128266..fbafa07fbce7 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -46,6 +46,7 @@ filegroup {
// TODO(b/146011398) package android.net.wifi is now split amongst 2 jars: framework.jar and
// framework-wifi.jar. This is not a good idea, should move WifiNetworkScoreCache
// to a separate package.
+ "java/android/net/wifi/SoftApConfToXmlMigrationUtil.java",
"java/android/net/wifi/WifiNetworkScoreCache.java",
"java/android/net/wifi/WifiMigration.java",
"java/android/net/wifi/nl80211/*.java",
diff --git a/wifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java b/wifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java
new file mode 100755
index 000000000000..c5472ce34478
--- /dev/null
+++ b/wifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2020 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.wifi;
+
+import static android.os.Environment.getDataMiscDirectory;
+
+import android.annotation.Nullable;
+import android.net.MacAddress;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Utility class to convert the legacy softap.conf file format to the new XML format.
+ * Note:
+ * <li>This should be modified by the OEM if they want to migrate configuration for existing
+ * devices for new softap features supported by AOSP in Android 11.
+ * For ex: client allowlist/blocklist feature was already supported by some OEM's before Android 10
+ * while AOSP only supported it in Android 11. </li>
+ * <li>Most of this class was copied over from WifiApConfigStore class in Android 10 and
+ * SoftApStoreData class in Android 11</li>
+ * @hide
+ */
+public final class SoftApConfToXmlMigrationUtil {
+ private static final String TAG = "SoftApConfToXmlMigrationUtil";
+
+ /**
+ * Directory to read the wifi config store files from under.
+ */
+ private static final String LEGACY_WIFI_STORE_DIRECTORY_NAME = "wifi";
+ /**
+ * The legacy Softap config file which contained key/value pairs.
+ */
+ private static final String LEGACY_AP_CONFIG_FILE = "softap.conf";
+
+ /**
+ * Pre-apex wifi shared folder.
+ */
+ private static File getLegacyWifiSharedDirectory() {
+ return new File(getDataMiscDirectory(), LEGACY_WIFI_STORE_DIRECTORY_NAME);
+ }
+
+ /* @hide constants copied from WifiConfiguration */
+ /**
+ * 2GHz band.
+ */
+ private static final int WIFICONFIG_AP_BAND_2GHZ = 0;
+ /**
+ * 5GHz band.
+ */
+ private static final int WIFICONFIG_AP_BAND_5GHZ = 1;
+ /**
+ * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability,
+ * operating country code and current radio conditions.
+ */
+ private static final int WIFICONFIG_AP_BAND_ANY = -1;
+ /**
+ * Convert band from WifiConfiguration into SoftApConfiguration
+ *
+ * @param wifiConfigBand band encoded as WIFICONFIG_AP_BAND_xxxx
+ * @return band as encoded as SoftApConfiguration.BAND_xxx
+ */
+ @VisibleForTesting
+ public static int convertWifiConfigBandToSoftApConfigBand(int wifiConfigBand) {
+ switch (wifiConfigBand) {
+ case WIFICONFIG_AP_BAND_2GHZ:
+ return SoftApConfiguration.BAND_2GHZ;
+ case WIFICONFIG_AP_BAND_5GHZ:
+ return SoftApConfiguration.BAND_5GHZ;
+ case WIFICONFIG_AP_BAND_ANY:
+ return SoftApConfiguration.BAND_2GHZ | SoftApConfiguration.BAND_5GHZ;
+ default:
+ return SoftApConfiguration.BAND_2GHZ;
+ }
+ }
+
+ /**
+ * Load AP configuration from legacy persistent storage.
+ * Note: This is deprecated and only used for migrating data once on reboot.
+ */
+ private static SoftApConfiguration loadFromLegacyFile(InputStream fis) {
+ SoftApConfiguration config = null;
+ DataInputStream in = null;
+ try {
+ SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
+ in = new DataInputStream(new BufferedInputStream(fis));
+
+ int version = in.readInt();
+ if (version < 1 || version > 3) {
+ Log.e(TAG, "Bad version on hotspot configuration file");
+ return null;
+ }
+ configBuilder.setSsid(in.readUTF());
+
+ if (version >= 2) {
+ int band = in.readInt();
+ int channel = in.readInt();
+ if (channel == 0) {
+ configBuilder.setBand(
+ convertWifiConfigBandToSoftApConfigBand(band));
+ } else {
+ configBuilder.setChannel(channel,
+ convertWifiConfigBandToSoftApConfigBand(band));
+ }
+ }
+ if (version >= 3) {
+ configBuilder.setHiddenSsid(in.readBoolean());
+ }
+ int authType = in.readInt();
+ if (authType == WifiConfiguration.KeyMgmt.WPA2_PSK) {
+ configBuilder.setPassphrase(in.readUTF(),
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+ }
+ config = configBuilder.build();
+ } catch (IOException e) {
+ Log.e(TAG, "Error reading hotspot configuration ", e);
+ config = null;
+ } catch (IllegalArgumentException ie) {
+ Log.e(TAG, "Invalid hotspot configuration ", ie);
+ config = null;
+ } finally {
+ if (in != null) {
+ try {
+ in.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Error closing hotspot configuration during read", e);
+ }
+ }
+ }
+ // NOTE: OEM's should add their customized parsing code here.
+ return config;
+ }
+
+ // This is the version that Android 11 released with.
+ private static final int CONFIG_STORE_DATA_VERSION = 3;
+
+ private static final String XML_TAG_DOCUMENT_HEADER = "WifiConfigStoreData";
+ private static final String XML_TAG_VERSION = "Version";
+ private static final String XML_TAG_SECTION_HEADER_SOFTAP = "SoftAp";
+ private static final String XML_TAG_SSID = "SSID";
+ private static final String XML_TAG_BSSID = "Bssid";
+ private static final String XML_TAG_CHANNEL = "Channel";
+ private static final String XML_TAG_HIDDEN_SSID = "HiddenSSID";
+ private static final String XML_TAG_SECURITY_TYPE = "SecurityType";
+ private static final String XML_TAG_AP_BAND = "ApBand";
+ private static final String XML_TAG_PASSPHRASE = "Passphrase";
+ private static final String XML_TAG_MAX_NUMBER_OF_CLIENTS = "MaxNumberOfClients";
+ private static final String XML_TAG_AUTO_SHUTDOWN_ENABLED = "AutoShutdownEnabled";
+ private static final String XML_TAG_SHUTDOWN_TIMEOUT_MILLIS = "ShutdownTimeoutMillis";
+ private static final String XML_TAG_CLIENT_CONTROL_BY_USER = "ClientControlByUser";
+ private static final String XML_TAG_BLOCKED_CLIENT_LIST = "BlockedClientList";
+ private static final String XML_TAG_ALLOWED_CLIENT_LIST = "AllowedClientList";
+ public static final String XML_TAG_CLIENT_MACADDRESS = "ClientMacAddress";
+
+ private static byte[] convertConfToXml(SoftApConfiguration softApConf) {
+ try {
+ final XmlSerializer out = new FastXmlSerializer();
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ out.setOutput(outputStream, StandardCharsets.UTF_8.name());
+
+ // Header for the XML file.
+ out.startDocument(null, true);
+ out.startTag(null, XML_TAG_DOCUMENT_HEADER);
+ XmlUtils.writeValueXml(CONFIG_STORE_DATA_VERSION, XML_TAG_VERSION, out);
+ out.startTag(null, XML_TAG_SECTION_HEADER_SOFTAP);
+
+ // SoftAp conf
+ XmlUtils.writeValueXml(softApConf.getSsid(), XML_TAG_SSID, out);
+ if (softApConf.getBssid() != null) {
+ XmlUtils.writeValueXml(softApConf.getBssid().toString(), XML_TAG_BSSID, out);
+ }
+ XmlUtils.writeValueXml(softApConf.getBand(), XML_TAG_AP_BAND, out);
+ XmlUtils.writeValueXml(softApConf.getChannel(), XML_TAG_CHANNEL, out);
+ XmlUtils.writeValueXml(softApConf.isHiddenSsid(), XML_TAG_HIDDEN_SSID, out);
+ XmlUtils.writeValueXml(softApConf.getSecurityType(), XML_TAG_SECURITY_TYPE, out);
+ if (softApConf.getSecurityType() != SoftApConfiguration.SECURITY_TYPE_OPEN) {
+ XmlUtils.writeValueXml(softApConf.getPassphrase(), XML_TAG_PASSPHRASE, out);
+ }
+ XmlUtils.writeValueXml(softApConf.getMaxNumberOfClients(),
+ XML_TAG_MAX_NUMBER_OF_CLIENTS, out);
+ XmlUtils.writeValueXml(softApConf.isClientControlByUserEnabled(),
+ XML_TAG_CLIENT_CONTROL_BY_USER, out);
+ XmlUtils.writeValueXml(softApConf.isAutoShutdownEnabled(),
+ XML_TAG_AUTO_SHUTDOWN_ENABLED, out);
+ XmlUtils.writeValueXml(softApConf.getShutdownTimeoutMillis(),
+ XML_TAG_SHUTDOWN_TIMEOUT_MILLIS, out);
+ out.startTag(null, XML_TAG_BLOCKED_CLIENT_LIST);
+ for (MacAddress mac: softApConf.getBlockedClientList()) {
+ XmlUtils.writeValueXml(mac.toString(), XML_TAG_CLIENT_MACADDRESS, out);
+ }
+ out.endTag(null, XML_TAG_BLOCKED_CLIENT_LIST);
+ out.startTag(null, XML_TAG_ALLOWED_CLIENT_LIST);
+ for (MacAddress mac: softApConf.getAllowedClientList()) {
+ XmlUtils.writeValueXml(mac.toString(), XML_TAG_CLIENT_MACADDRESS, out);
+ }
+ out.endTag(null, XML_TAG_ALLOWED_CLIENT_LIST);
+
+ // Footer for the XML file.
+ out.endTag(null, XML_TAG_SECTION_HEADER_SOFTAP);
+ out.endTag(null, XML_TAG_DOCUMENT_HEADER);
+ out.endDocument();
+
+ return outputStream.toByteArray();
+ } catch (IOException | XmlPullParserException e) {
+ Log.e(TAG, "Failed to convert softap conf to XML", e);
+ return null;
+ }
+ }
+
+ private SoftApConfToXmlMigrationUtil() { }
+
+ /**
+ * Read the legacy /data/misc/wifi/softap.conf file format and convert to the new XML
+ * format understood by WifiConfigStore.
+ * Note: Used for unit testing.
+ */
+ @VisibleForTesting
+ @Nullable
+ public static InputStream convert(InputStream fis) {
+ SoftApConfiguration softApConf = loadFromLegacyFile(fis);
+ if (softApConf == null) return null;
+
+ byte[] xmlBytes = convertConfToXml(softApConf);
+ if (xmlBytes == null) return null;
+
+ return new ByteArrayInputStream(xmlBytes);
+ }
+
+ /**
+ * Read the legacy /data/misc/wifi/softap.conf file format and convert to the new XML
+ * format understood by WifiConfigStore.
+ */
+ @Nullable
+ public static InputStream convert() {
+ File file = new File(getLegacyWifiSharedDirectory(), LEGACY_AP_CONFIG_FILE);
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ return null;
+ }
+ if (fis == null) return null;
+ return convert(fis);
+ }
+
+ /**
+ * Remove the legacy /data/misc/wifi/softap.conf file.
+ */
+ @Nullable
+ public static void remove() {
+ File file = new File(getLegacyWifiSharedDirectory(), LEGACY_AP_CONFIG_FILE);
+ file.delete();
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiMigration.java b/wifi/java/android/net/wifi/WifiMigration.java
index f2a1aec550b1..666d72d32ac7 100755
--- a/wifi/java/android/net/wifi/WifiMigration.java
+++ b/wifi/java/android/net/wifi/WifiMigration.java
@@ -95,7 +95,7 @@ public final class WifiMigration {
private static final SparseArray<String> STORE_ID_TO_FILE_NAME =
new SparseArray<String>() {{
put(STORE_FILE_SHARED_GENERAL, "WifiConfigStore.xml");
- put(STORE_FILE_SHARED_SOFTAP, "softap.conf");
+ put(STORE_FILE_SHARED_SOFTAP, "WifiConfigStoreSoftAp.xml");
put(STORE_FILE_USER_GENERAL, "WifiConfigStore.xml");
put(STORE_FILE_USER_NETWORK_SUGGESTIONS, "WifiConfigStoreNetworkSuggestions.xml");
}};
@@ -176,6 +176,13 @@ public final class WifiMigration {
// OEMs should do conversions necessary here before returning the stream.
return getSharedAtomicFile(storeFileId).openRead();
} catch (FileNotFoundException e) {
+ // Special handling for softap.conf.
+ // Note: OEM devices upgrading from Q -> R will only have the softap.conf file.
+ // Test devices running previous R builds however may have already migrated to the
+ // XML format. So, check for that above before falling back to check for legacy file.
+ if (storeFileId == STORE_FILE_SHARED_SOFTAP) {
+ return SoftApConfToXmlMigrationUtil.convert();
+ }
return null;
}
}
@@ -191,7 +198,18 @@ public final class WifiMigration {
if (storeFileId != STORE_FILE_SHARED_GENERAL && storeFileId != STORE_FILE_SHARED_SOFTAP) {
throw new IllegalArgumentException("Invalid shared store file id");
}
- getSharedAtomicFile(storeFileId).delete();
+ AtomicFile file = getSharedAtomicFile(storeFileId);
+ if (file.exists()) {
+ file.delete();
+ return;
+ }
+ // Special handling for softap.conf.
+ // Note: OEM devices upgrading from Q -> R will only have the softap.conf file.
+ // Test devices running previous R builds however may have already migrated to the
+ // XML format. So, check for that above before falling back to check for legacy file.
+ if (storeFileId == STORE_FILE_SHARED_SOFTAP) {
+ SoftApConfToXmlMigrationUtil.remove();
+ }
}
/**
@@ -258,7 +276,10 @@ public final class WifiMigration {
throw new IllegalArgumentException("Invalid user store file id");
}
Objects.requireNonNull(userHandle);
- getUserAtomicFile(storeFileId, userHandle.getIdentifier()).delete();
+ AtomicFile file = getUserAtomicFile(storeFileId, userHandle.getIdentifier());
+ if (file.exists()) {
+ file.delete();
+ }
}
/**
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java b/wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java
new file mode 100644
index 000000000000..f49f387cbc6b
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2019 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.wifi;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Unit tests for {@link android.net.wifi.SoftApConfToXmlMigrationUtilTest}.
+ */
+@SmallTest
+public class SoftApConfToXmlMigrationUtilTest {
+ private static final String TEST_SSID = "SSID";
+ private static final String TEST_PASSPHRASE = "TestPassphrase";
+ private static final int TEST_CHANNEL = 0;
+ private static final boolean TEST_HIDDEN = false;
+ private static final int TEST_BAND = SoftApConfiguration.BAND_5GHZ;
+ private static final int TEST_SECURITY = SoftApConfiguration.SECURITY_TYPE_WPA2_PSK;
+
+ private static final String TEST_EXPECTED_XML_STRING =
+ "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<WifiConfigStoreData>\n"
+ + "<int name=\"Version\" value=\"3\" />\n"
+ + "<SoftAp>\n"
+ + "<string name=\"SSID\">" + TEST_SSID + "</string>\n"
+ + "<int name=\"ApBand\" value=\"" + TEST_BAND + "\" />\n"
+ + "<int name=\"Channel\" value=\"" + TEST_CHANNEL + "\" />\n"
+ + "<boolean name=\"HiddenSSID\" value=\"" + TEST_HIDDEN + "\" />\n"
+ + "<int name=\"SecurityType\" value=\"" + TEST_SECURITY + "\" />\n"
+ + "<string name=\"Passphrase\">" + TEST_PASSPHRASE + "</string>\n"
+ + "<int name=\"MaxNumberOfClients\" value=\"0\" />\n"
+ + "<boolean name=\"ClientControlByUser\" value=\"false\" />\n"
+ + "<boolean name=\"AutoShutdownEnabled\" value=\"true\" />\n"
+ + "<long name=\"ShutdownTimeoutMillis\" value=\"0\" />\n"
+ + "<BlockedClientList />\n"
+ + "<AllowedClientList />\n"
+ + "</SoftAp>\n"
+ + "</WifiConfigStoreData>\n";
+
+ private byte[] createLegacyApConfFile(WifiConfiguration config) throws Exception {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ DataOutputStream out = new DataOutputStream(outputStream);
+ out.writeInt(3);
+ out.writeUTF(config.SSID);
+ out.writeInt(config.apBand);
+ out.writeInt(config.apChannel);
+ out.writeBoolean(config.hiddenSSID);
+ int authType = config.getAuthType();
+ out.writeInt(authType);
+ if (authType != WifiConfiguration.KeyMgmt.NONE) {
+ out.writeUTF(config.preSharedKey);
+ }
+ out.close();
+ return outputStream.toByteArray();
+ }
+
+ /**
+ * Generate a SoftApConfiguration based on the specified parameters.
+ */
+ private SoftApConfiguration setupApConfig(
+ String ssid, String preSharedKey, int keyManagement, int band, int channel,
+ boolean hiddenSSID) {
+ SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
+ configBuilder.setSsid(ssid);
+ configBuilder.setPassphrase(preSharedKey, SoftApConfiguration.SECURITY_TYPE_WPA2_PSK);
+ if (channel == 0) {
+ configBuilder.setBand(band);
+ } else {
+ configBuilder.setChannel(channel, band);
+ }
+ configBuilder.setHiddenSsid(hiddenSSID);
+ return configBuilder.build();
+ }
+
+ /**
+ * Generate a WifiConfiguration based on the specified parameters.
+ */
+ private WifiConfiguration setupWifiConfigurationApConfig(
+ String ssid, String preSharedKey, int keyManagement, int band, int channel,
+ boolean hiddenSSID) {
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = ssid;
+ config.preSharedKey = preSharedKey;
+ config.allowedKeyManagement.set(keyManagement);
+ config.apBand = band;
+ config.apChannel = channel;
+ config.hiddenSSID = hiddenSSID;
+ return config;
+ }
+
+ /**
+ * Asserts that the WifiConfigurations equal to SoftApConfiguration.
+ * This only compares the elements saved
+ * for softAp used.
+ */
+ public static void assertWifiConfigurationEqualSoftApConfiguration(
+ WifiConfiguration backup, SoftApConfiguration restore) {
+ assertEquals(backup.SSID, restore.getSsid());
+ assertEquals(backup.BSSID, restore.getBssid());
+ assertEquals(SoftApConfToXmlMigrationUtil.convertWifiConfigBandToSoftApConfigBand(
+ backup.apBand),
+ restore.getBand());
+ assertEquals(backup.apChannel, restore.getChannel());
+ assertEquals(backup.preSharedKey, restore.getPassphrase());
+ if (backup.getAuthType() == WifiConfiguration.KeyMgmt.WPA2_PSK) {
+ assertEquals(SoftApConfiguration.SECURITY_TYPE_WPA2_PSK, restore.getSecurityType());
+ } else {
+ assertEquals(SoftApConfiguration.SECURITY_TYPE_OPEN, restore.getSecurityType());
+ }
+ assertEquals(backup.hiddenSSID, restore.isHiddenSsid());
+ }
+
+ /**
+ * Note: This is a copy of {@link AtomicFile#readFully()} modified to use the passed in
+ * {@link InputStream} which was returned using {@link AtomicFile#openRead()}.
+ */
+ private static byte[] readFully(InputStream stream) throws IOException {
+ try {
+ int pos = 0;
+ int avail = stream.available();
+ byte[] data = new byte[avail];
+ while (true) {
+ int amt = stream.read(data, pos, data.length - pos);
+ if (amt <= 0) {
+ return data;
+ }
+ pos += amt;
+ avail = stream.available();
+ if (avail > data.length - pos) {
+ byte[] newData = new byte[pos + avail];
+ System.arraycopy(data, 0, newData, 0, pos);
+ data = newData;
+ }
+ }
+ } finally {
+ stream.close();
+ }
+ }
+
+ /**
+ * Tests conversion from legacy .conf file to XML file format.
+ */
+ @Test
+ public void testConversion() throws Exception {
+ WifiConfiguration backupConfig = setupWifiConfigurationApConfig(
+ TEST_SSID, /* SSID */
+ TEST_PASSPHRASE, /* preshared key */
+ WifiConfiguration.KeyMgmt.WPA2_PSK, /* key management */
+ 1, /* AP band (5GHz) */
+ TEST_CHANNEL, /* AP channel */
+ TEST_HIDDEN /* Hidden SSID */);
+ SoftApConfiguration expectedConfig = setupApConfig(
+ TEST_SSID, /* SSID */
+ TEST_PASSPHRASE, /* preshared key */
+ SoftApConfiguration.SECURITY_TYPE_WPA2_PSK, /* security type */
+ SoftApConfiguration.BAND_5GHZ, /* AP band (5GHz) */
+ TEST_CHANNEL, /* AP channel */
+ TEST_HIDDEN /* Hidden SSID */);
+
+ assertWifiConfigurationEqualSoftApConfiguration(backupConfig, expectedConfig);
+
+ byte[] confBytes = createLegacyApConfFile(backupConfig);
+ assertNotNull(confBytes);
+
+ InputStream xmlStream = SoftApConfToXmlMigrationUtil.convert(
+ new ByteArrayInputStream(confBytes));
+
+ byte[] xmlBytes = readFully(xmlStream);
+ assertNotNull(xmlBytes);
+
+ assertEquals(TEST_EXPECTED_XML_STRING, new String(xmlBytes));
+ }
+
+}