summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2017-02-10 19:37:37 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-02-10 19:37:38 +0000
commit2f74844643d30a69e77436e93ad904c7701bac5e (patch)
tree391cbc5fbfb3b59a549215c03c4ce68a36df0f73
parent1b1bafd2b0278e2079f6ece9081ddb25cdf2c254 (diff)
parent0a0b5035ce8013ed327a0802357a1b7df3061912 (diff)
Merge "Wifi configuration store data refactor"
-rw-r--r--service/java/com/android/server/wifi/DeletedEphemeralSsidsStoreData.java111
-rw-r--r--service/java/com/android/server/wifi/NetworkListStoreData.java284
-rw-r--r--service/java/com/android/server/wifi/WifiConfigManager.java41
-rw-r--r--service/java/com/android/server/wifi/WifiConfigStore.java219
-rw-r--r--service/java/com/android/server/wifi/WifiConfigStoreData.java560
-rw-r--r--service/java/com/android/server/wifi/WifiInjector.java3
-rw-r--r--tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java178
-rw-r--r--tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java414
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java220
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConfigStoreDataTest.java446
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java399
11 files changed, 1682 insertions, 1193 deletions
diff --git a/service/java/com/android/server/wifi/DeletedEphemeralSsidsStoreData.java b/service/java/com/android/server/wifi/DeletedEphemeralSsidsStoreData.java
new file mode 100644
index 000000000..201a132fb
--- /dev/null
+++ b/service/java/com/android/server/wifi/DeletedEphemeralSsidsStoreData.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 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 com.android.server.wifi.util.XmlUtil;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * This class performs serialization and parsing of XML data block that contain the list of
+ * deleted ephemeral SSIDs (XML block data inside <DeletedEphemeralSSIDList> tag).
+ */
+public class DeletedEphemeralSsidsStoreData implements WifiConfigStore.StoreData {
+ private static final String XML_TAG_SECTION_HEADER_DELETED_EPHEMERAL_SSID_LIST =
+ "DeletedEphemeralSSIDList";
+ private static final String XML_TAG_SSID_LIST = "SSIDList";
+
+ private Set<String> mSsidList;
+
+ DeletedEphemeralSsidsStoreData() {}
+
+ @Override
+ public void serializeData(XmlSerializer out, boolean shared)
+ throws XmlPullParserException, IOException {
+ if (shared) {
+ throw new XmlPullParserException("Share data not supported");
+ }
+ if (mSsidList != null) {
+ XmlUtil.writeNextValue(out, XML_TAG_SSID_LIST, mSsidList);
+ }
+ }
+
+ @Override
+ public void deserializeData(XmlPullParser in, int outerTagDepth, boolean shared)
+ throws XmlPullParserException, IOException {
+ if (shared) {
+ throw new XmlPullParserException("Share data not supported");
+ }
+
+ while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
+ String[] valueName = new String[1];
+ Object value = XmlUtil.readCurrentValue(in, valueName);
+ if (valueName[0] == null) {
+ throw new XmlPullParserException("Missing value name");
+ }
+ switch (valueName[0]) {
+ case XML_TAG_SSID_LIST:
+ mSsidList = (Set<String>) value;
+ break;
+ default:
+ throw new XmlPullParserException("Unknown tag under "
+ + XML_TAG_SECTION_HEADER_DELETED_EPHEMERAL_SSID_LIST
+ + ": " + valueName[0]);
+ }
+ }
+ }
+
+ @Override
+ public void resetData(boolean shared) {
+ if (!shared) {
+ mSsidList = null;
+ }
+ }
+
+ @Override
+ public String getName() {
+ return XML_TAG_SECTION_HEADER_DELETED_EPHEMERAL_SSID_LIST;
+ }
+
+ @Override
+ public boolean supportShareData() {
+ return false;
+ }
+
+ /**
+ * An empty set will be returned for null SSID list.
+ *
+ * @return Set of SSIDs
+ */
+ public Set<String> getSsidList() {
+ if (mSsidList == null) {
+ return new HashSet<String>();
+ }
+ return mSsidList;
+ }
+
+ public void setSsidList(Set<String> ssidList) {
+ mSsidList = ssidList;
+ }
+}
+
diff --git a/service/java/com/android/server/wifi/NetworkListStoreData.java b/service/java/com/android/server/wifi/NetworkListStoreData.java
new file mode 100644
index 000000000..f9ecab132
--- /dev/null
+++ b/service/java/com/android/server/wifi/NetworkListStoreData.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2017 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.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
+import android.net.wifi.WifiEnterpriseConfig;
+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.NetworkSelectionStatusXmlUtil;
+import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil;
+import com.android.server.wifi.util.XmlUtil.WifiEnterpriseConfigXmlUtil;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class performs serialization and parsing of XML data block that contain the list of WiFi
+ * network configurations (XML block data inside <NetworkList> tag).
+ */
+public class NetworkListStoreData implements WifiConfigStore.StoreData {
+ private static final String XML_TAG_SECTION_HEADER_NETWORK_LIST = "NetworkList";
+ private static final String XML_TAG_SECTION_HEADER_NETWORK = "Network";
+ private static final String XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION = "WifiConfiguration";
+ private static final String XML_TAG_SECTION_HEADER_NETWORK_STATUS = "NetworkStatus";
+ private static final String XML_TAG_SECTION_HEADER_IP_CONFIGURATION = "IpConfiguration";
+ private static final String XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION =
+ "WifiEnterpriseConfiguration";
+
+ /**
+ * List of saved shared networks visible to all the users to be stored in the shared store file.
+ */
+ private List<WifiConfiguration> mSharedConfigurations;
+ /**
+ * List of saved private networks only visible to the current user to be stored in the user
+ * specific store file.
+ */
+ private List<WifiConfiguration> mUserConfigurations;
+
+ NetworkListStoreData() {}
+
+ @Override
+ public void serializeData(XmlSerializer out, boolean shared)
+ throws XmlPullParserException, IOException {
+ if (shared) {
+ serializeNetworkList(out, mSharedConfigurations);
+ } else {
+ serializeNetworkList(out, mUserConfigurations);
+ }
+ }
+
+ @Override
+ public void deserializeData(XmlPullParser in, int outerTagDepth, boolean shared)
+ throws XmlPullParserException, IOException {
+ if (shared) {
+ mSharedConfigurations = parseNetworkList(in, outerTagDepth);
+ } else {
+ mUserConfigurations = parseNetworkList(in, outerTagDepth);
+ }
+ }
+
+ @Override
+ public void resetData(boolean shared) {
+ if (shared) {
+ mSharedConfigurations = null;
+ } else {
+ mUserConfigurations = null;
+ }
+ }
+
+ @Override
+ public String getName() {
+ return XML_TAG_SECTION_HEADER_NETWORK_LIST;
+ }
+
+ @Override
+ public boolean supportShareData() {
+ return true;
+ }
+
+ public void setSharedConfigurations(List<WifiConfiguration> configs) {
+ mSharedConfigurations = configs;
+ }
+
+ /**
+ * An empty list will be returned if no shared configurations.
+ *
+ * @return List of {@link WifiConfiguration}
+ */
+ public List<WifiConfiguration> getSharedConfigurations() {
+ if (mSharedConfigurations == null) {
+ return new ArrayList<WifiConfiguration>();
+ }
+ return mSharedConfigurations;
+ }
+
+ public void setUserConfigurations(List<WifiConfiguration> configs) {
+ mUserConfigurations = configs;
+ }
+
+ /**
+ * An empty list will be returned if no user configurations.
+ *
+ * @return List of {@link WifiConfiguration}
+ */
+ public List<WifiConfiguration> getUserConfigurations() {
+ if (mUserConfigurations == null) {
+ return new ArrayList<WifiConfiguration>();
+ }
+ return mUserConfigurations;
+ }
+
+ /**
+ * Serialize the list of {@link WifiConfiguration} to an output stream in XML format.
+ *
+ * @param out The output stream to serialize the data to
+ * @param networkList The network list to serialize
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ private void serializeNetworkList(XmlSerializer out, List<WifiConfiguration> networkList)
+ throws XmlPullParserException, IOException {
+ if (networkList == null) {
+ return;
+ }
+ for (WifiConfiguration network : networkList) {
+ serializeWifiConfig(out, network);
+ }
+ }
+
+ /**
+ * Serialize a {@link WifiConfiguration} to an output stream in XML format.
+ * @param out
+ * @param config
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ private void serializeWifiConfig(XmlSerializer out, WifiConfiguration config)
+ throws XmlPullParserException, IOException {
+ XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK);
+
+ // Serialize WifiConfiguration.
+ XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION);
+ WifiConfigurationXmlUtil.writeToXmlForConfigStore(out, config);
+ XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION);
+
+ // Serialize network selection status.
+ XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_STATUS);
+ NetworkSelectionStatusXmlUtil.writeToXml(out, config.getNetworkSelectionStatus());
+ XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_STATUS);
+
+ // Serialize IP configuration.
+ XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_IP_CONFIGURATION);
+ IpConfigurationXmlUtil.writeToXml(out, config.getIpConfiguration());
+ XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_IP_CONFIGURATION);
+
+ // Serialize enterprise configuration for enterprise networks.
+ if (config.enterpriseConfig != null
+ && config.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) {
+ XmlUtil.writeNextSectionStart(
+ out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION);
+ WifiEnterpriseConfigXmlUtil.writeToXml(out, config.enterpriseConfig);
+ XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION);
+ }
+
+ XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK);
+ }
+
+ /**
+ * Parse a list of {@link WifiConfiguration} from an input stream in XML format.
+ *
+ * @param in The input stream to read from
+ * @param outerTagDepth The XML tag depth of the outer XML block
+ * @return List of {@link WifiConfiguration}
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ private List<WifiConfiguration> parseNetworkList(XmlPullParser in, int outerTagDepth)
+ throws XmlPullParserException, IOException {
+ List<WifiConfiguration> networkList = new ArrayList<>();
+ while (XmlUtil.gotoNextSectionWithNameOrEnd(in, XML_TAG_SECTION_HEADER_NETWORK,
+ outerTagDepth)) {
+ WifiConfiguration config = parseWifiConfiguration(in, outerTagDepth + 1);
+ networkList.add(config);
+ }
+ return networkList;
+ }
+
+ /**
+ * Parse a {@link WifiConfiguration} from an input stream in XML format.
+ *
+ * @param in The input stream to read from
+ * @param outerTagDepth The XML tag depth of the outer XML block
+ * @return {@link WifiConfiguration}
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ private WifiConfiguration parseWifiConfiguration(XmlPullParser in, int outerTagDepth)
+ throws XmlPullParserException, IOException {
+ Pair<String, WifiConfiguration> parsedConfig = null;
+ NetworkSelectionStatus status = null;
+ IpConfiguration ipConfiguration = null;
+ WifiEnterpriseConfig enterpriseConfig = null;
+
+ String[] headerName = new String[1];
+ while (XmlUtil.gotoNextSectionOrEnd(in, headerName, outerTagDepth)) {
+ switch (headerName[0]) {
+ case XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION:
+ if (parsedConfig != null) {
+ throw new XmlPullParserException("Detected duplicate tag for: "
+ + XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION);
+ }
+ parsedConfig = WifiConfigurationXmlUtil.parseFromXml(in, outerTagDepth + 1);
+ break;
+ case XML_TAG_SECTION_HEADER_NETWORK_STATUS:
+ if (status != null) {
+ throw new XmlPullParserException("Detected duplicate tag for: "
+ + XML_TAG_SECTION_HEADER_NETWORK_STATUS);
+ }
+ status = NetworkSelectionStatusXmlUtil.parseFromXml(in, outerTagDepth + 1);
+ break;
+ case XML_TAG_SECTION_HEADER_IP_CONFIGURATION:
+ if (ipConfiguration != null) {
+ throw new XmlPullParserException("Detected duplicate tag for: "
+ + XML_TAG_SECTION_HEADER_IP_CONFIGURATION);
+ }
+ ipConfiguration = IpConfigurationXmlUtil.parseFromXml(in, outerTagDepth + 1);
+ break;
+ case XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION:
+ if (enterpriseConfig != null) {
+ throw new XmlPullParserException("Detected duplicate tag for: "
+ + XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION);
+ }
+ enterpriseConfig =
+ WifiEnterpriseConfigXmlUtil.parseFromXml(in, outerTagDepth + 1);
+ break;
+ default:
+ throw new XmlPullParserException("Unknown tag under "
+ + XML_TAG_SECTION_HEADER_NETWORK + ": " + headerName[0]);
+ }
+ }
+ if (parsedConfig == null || parsedConfig.first == null || parsedConfig.second == null) {
+ throw new XmlPullParserException("XML parsing of wifi configuration failed");
+ }
+ String configKeyParsed = parsedConfig.first;
+ WifiConfiguration configuration = parsedConfig.second;
+ String configKeyCalculated = configuration.configKey();
+ if (!configKeyParsed.equals(configKeyCalculated)) {
+ throw new XmlPullParserException(
+ "Configuration key does not match. Retrieved: " + configKeyParsed
+ + ", Calculated: " + configKeyCalculated);
+ }
+
+ configuration.setNetworkSelectionStatus(status);
+ configuration.setIpConfiguration(ipConfiguration);
+ if (enterpriseConfig != null) {
+ configuration.enterpriseConfig = enterpriseConfig;
+ }
+ return configuration;
+ }
+}
+
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index eb25711cf..7b704ad50 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -291,6 +291,11 @@ public class WifiConfigManager {
private long mLastSelectedTimeStamp =
WifiConfiguration.NetworkSelectionStatus.INVALID_NETWORK_SELECTION_DISABLE_TIMESTAMP;
+ // Store data for network list and deleted ephemeral SSID list. Used for serializing
+ // parsing data to/from the config store.
+ private final NetworkListStoreData mNetworkListStoreData;
+ private final DeletedEphemeralSsidsStoreData mDeletedEphemeralSsidsStoreData;
+
/**
* Create new instance of WifiConfigManager.
*/
@@ -298,7 +303,9 @@ public class WifiConfigManager {
Context context, FrameworkFacade facade, Clock clock, UserManager userManager,
TelephonyManager telephonyManager, WifiKeyStore wifiKeyStore,
WifiConfigStore wifiConfigStore, WifiConfigStoreLegacy wifiConfigStoreLegacy,
- WifiPermissionsWrapper wifiPermissionsWrapper) {
+ WifiPermissionsWrapper wifiPermissionsWrapper,
+ NetworkListStoreData networkListStoreData,
+ DeletedEphemeralSsidsStoreData deletedEphemeralSsidsStoreData) {
mContext = context;
mFacade = facade;
mClock = clock;
@@ -314,6 +321,12 @@ public class WifiConfigManager {
mScanDetailCaches = new HashMap<>(16, 0.75f);
mDeletedEphemeralSSIDs = new HashSet<>();
+ // Register store data for network list and deleted ephemeral SSIDs.
+ mNetworkListStoreData = networkListStoreData;
+ mDeletedEphemeralSsidsStoreData = deletedEphemeralSsidsStoreData;
+ mWifiConfigStore.registerStoreData(mNetworkListStoreData);
+ mWifiConfigStore.registerStoreData(mDeletedEphemeralSsidsStoreData);
+
mOnlyLinkSameCredentialConfigurations = mContext.getResources().getBoolean(
R.bool.config_wifi_only_link_same_credential_configurations);
mMaxNumActiveChannelsForPartialScans = mContext.getResources().getInteger(
@@ -2561,9 +2574,8 @@ public class WifiConfigManager {
}
return true;
}
- WifiConfigStoreData storeData;
try {
- storeData = mWifiConfigStore.read();
+ mWifiConfigStore.read();
} catch (IOException e) {
Log.wtf(TAG, "Reading from new store failed. All saved networks are lost!", e);
return false;
@@ -2571,8 +2583,9 @@ public class WifiConfigManager {
Log.wtf(TAG, "XML deserialization of store failed. All saved networks are lost!", e);
return false;
}
- loadInternalData(storeData.getSharedConfigurations(), storeData.getUserConfigurations(),
- storeData.getDeletedEphemeralSSIDs());
+ loadInternalData(mNetworkListStoreData.getSharedConfigurations(),
+ mNetworkListStoreData.getUserConfigurations(),
+ mDeletedEphemeralSsidsStoreData.getSsidList());
// If the user unlock comes in before we load from store, we defer the handling until
// the load from store is triggered.
if (mDeferredUserUnlockRead) {
@@ -2596,10 +2609,8 @@ public class WifiConfigManager {
* @return true on success, false otherwise.
*/
public boolean loadFromUserStoreAfterUnlockOrSwitch(int userId) {
- WifiConfigStoreData storeData;
try {
- storeData = mWifiConfigStore.switchUserStoreAndRead(
- mWifiConfigStore.createUserFile(userId));
+ mWifiConfigStore.switchUserStoreAndRead(WifiConfigStore.createUserFile(userId));
} catch (IOException e) {
Log.wtf(TAG, "Reading from new store failed. All saved private networks are lost!", e);
return false;
@@ -2608,8 +2619,8 @@ public class WifiConfigManager {
"lost!", e);
return false;
}
- loadInternalDataFromUserStore(storeData.getUserConfigurations(),
- storeData.getDeletedEphemeralSSIDs());
+ loadInternalDataFromUserStore(mNetworkListStoreData.getUserConfigurations(),
+ mDeletedEphemeralSsidsStoreData.getSsidList());
return true;
}
@@ -2640,12 +2651,14 @@ public class WifiConfigManager {
}
}
}
- WifiConfigStoreData storeData =
- new WifiConfigStoreData(
- sharedConfigurations, userConfigurations, mDeletedEphemeralSSIDs);
+
+ // Setup store data for write.
+ mNetworkListStoreData.setSharedConfigurations(sharedConfigurations);
+ mNetworkListStoreData.setUserConfigurations(userConfigurations);
+ mDeletedEphemeralSsidsStoreData.setSsidList(mDeletedEphemeralSSIDs);
try {
- mWifiConfigStore.write(forceWrite, storeData);
+ mWifiConfigStore.write(forceWrite);
} catch (IOException e) {
Log.wtf(TAG, "Writing to store failed. Saved networks maybe lost!", e);
return false;
diff --git a/service/java/com/android/server/wifi/WifiConfigStore.java b/service/java/com/android/server/wifi/WifiConfigStore.java
index 1eea9d5ca..3f1269c42 100644
--- a/service/java/com/android/server/wifi/WifiConfigStore.java
+++ b/service/java/com/android/server/wifi/WifiConfigStore.java
@@ -23,16 +23,26 @@ import android.os.FileUtils;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
+import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.AtomicFile;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.server.wifi.util.XmlUtil;
+import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
/**
* This class provides the API's to save/load/modify network configurations from a persistent
@@ -40,6 +50,18 @@ import java.io.IOException;
* NOTE: This class should only be used from WifiConfigManager and is not thread-safe!
*/
public class WifiConfigStore {
+ private static final String XML_TAG_DOCUMENT_HEADER = "WifiConfigStoreData";
+ private static final String XML_TAG_VERSION = "Version";
+ /**
+ * Current config store data version. This will be incremented for any additions.
+ */
+ private static final int CURRENT_CONFIG_STORE_DATA_VERSION = 1;
+ /** This list of older versions will be used to restore data from older config store. */
+ /**
+ * First version of the config store data format.
+ */
+ private static final int INITIAL_CONFIG_STORE_DATA_VERSION = 1;
+
/**
* Alarm tag to use for starting alarms for buffering file writes.
*/
@@ -105,6 +127,11 @@ public class WifiConfigStore {
};
/**
+ * List of data container.
+ */
+ private final Map<String, StoreData> mStoreDataList;
+
+ /**
* Create a new instance of WifiConfigStore.
* Note: The store file instances have been made inputs to this class to ease unit-testing.
*
@@ -120,6 +147,7 @@ public class WifiConfigStore {
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mEventHandler = new Handler(looper);
mClock = clock;
+ mStoreDataList = new HashMap<>();
// Initialize the store files.
mSharedStore = sharedStore;
@@ -129,6 +157,23 @@ public class WifiConfigStore {
}
/**
+ * Register a {@link StoreData} to store. A {@link StoreData} is responsible
+ * for a block of data in the store file, and provides serialization/deserialization functions
+ * for those data.
+ *
+ * @param storeData The store data to be registered to the config store
+ * @return true if succeeded
+ */
+ public boolean registerStoreData(StoreData storeData) {
+ if (storeData == null) {
+ Log.e(TAG, "Unable to register null store data");
+ return false;
+ }
+ mStoreDataList.put(storeData.getName(), storeData);
+ return true;
+ }
+
+ /**
* Helper method to create a store file instance for either the shared store or user store.
* Note: The method creates the store directory if not already present. This may be needed for
* user store files.
@@ -185,22 +230,21 @@ public class WifiConfigStore {
}
/**
- * API to write the provided store data to config stores.
+ * API to write the data provided by registered store data to config stores.
* The method writes the user specific configurations to user specific config store and the
* shared configurations to shared config store.
*
* @param forceSync boolean to force write the config stores now. if false, the writes are
* buffered and written after the configured interval.
- * @param storeData The entire data to be stored across all the config store files.
*/
- public void write(boolean forceSync, WifiConfigStoreData storeData)
+ public void write(boolean forceSync)
throws XmlPullParserException, IOException {
// Serialize the provided data and send it to the respective stores. The actual write will
// be performed later depending on the |forceSync| flag .
- byte[] sharedDataBytes = storeData.createSharedRawData();
+ byte[] sharedDataBytes = serializeData(true);
mSharedStore.storeRawDataToWrite(sharedDataBytes);
if (mUserStore != null) {
- byte[] userDataBytes = storeData.createUserRawData();
+ byte[] userDataBytes = serializeData(false);
mUserStore.storeRawDataToWrite(userDataBytes);
}
@@ -214,6 +258,39 @@ public class WifiConfigStore {
}
/**
+ * Serialize share data or user data from all store data.
+ *
+ * @param shareData Flag indicating share data
+ * @return byte[] of serialized bytes
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ private byte[] serializeData(boolean shareData) throws XmlPullParserException, IOException {
+ final XmlSerializer out = new FastXmlSerializer();
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ out.setOutput(outputStream, StandardCharsets.UTF_8.name());
+
+ XmlUtil.writeDocumentStart(out, XML_TAG_DOCUMENT_HEADER);
+ XmlUtil.writeNextValue(out, XML_TAG_VERSION, CURRENT_CONFIG_STORE_DATA_VERSION);
+
+ for (Map.Entry<String, StoreData> entry : mStoreDataList.entrySet()) {
+ String tag = entry.getKey();
+ StoreData storeData = entry.getValue();
+ // Ignore this store data if this is for share file and the store data doesn't support
+ // share store.
+ if (shareData && !storeData.supportShareData()) {
+ continue;
+ }
+ XmlUtil.writeNextSectionStart(out, tag);
+ storeData.serializeData(out, shareData);
+ XmlUtil.writeNextSectionEnd(out, tag);
+ }
+ XmlUtil.writeDocumentEnd(out, XML_TAG_DOCUMENT_HEADER);
+
+ return outputStream.toByteArray();
+ }
+
+ /**
* Helper method to start a buffered write alarm if one doesn't already exist.
*/
private void startBufferedWriteAlarm() {
@@ -256,10 +333,12 @@ public class WifiConfigStore {
* API to read the store data from the config stores.
* The method reads the user specific configurations from user specific config store and the
* shared configurations from the shared config store.
- *
- * @return storeData The entire data retrieved across all the config store files.
*/
- public WifiConfigStoreData read() throws XmlPullParserException, IOException {
+ public void read() throws XmlPullParserException, IOException {
+ // Reset both share and user store data.
+ resetStoreData(true);
+ resetStoreData(false);
+
long readStartTime = mClock.getElapsedSinceBootMillis();
byte[] sharedDataBytes = mSharedStore.readRawData();
byte[] userDataBytes = null;
@@ -268,8 +347,8 @@ public class WifiConfigStore {
}
long readTime = mClock.getElapsedSinceBootMillis() - readStartTime;
Log.d(TAG, "Reading from stores completed in " + readTime + " ms.");
-
- return WifiConfigStoreData.parseRawData(sharedDataBytes, userDataBytes);
+ deserializeData(sharedDataBytes, true);
+ deserializeData(userDataBytes, false);
}
/**
@@ -279,8 +358,11 @@ public class WifiConfigStore {
* @param userStore StoreFile instance pointing to the user specific store file. This should
* be retrieved using {@link #createUserFile(int)} method.
*/
- public WifiConfigStoreData switchUserStoreAndRead(StoreFile userStore)
+ public void switchUserStoreAndRead(StoreFile userStore)
throws XmlPullParserException, IOException {
+ // Reset user store data.
+ resetStoreData(false);
+
// Stop any pending buffered writes, if any.
stopBufferedWriteAlarm();
mUserStore = userStore;
@@ -290,8 +372,67 @@ public class WifiConfigStore {
byte[] userDataBytes = mUserStore.readRawData();
long readTime = mClock.getElapsedSinceBootMillis() - readStartTime;
Log.d(TAG, "Reading from user store completed in " + readTime + " ms.");
+ deserializeData(userDataBytes, false);
+ }
+
+ /**
+ * Reset share data or user data in all store data.
+ *
+ * @param shareData Flag indicating share data
+ */
+ private void resetStoreData(boolean shareData) {
+ for (Map.Entry<String, StoreData> entry : mStoreDataList.entrySet()) {
+ entry.getValue().resetData(shareData);
+ }
+ }
+
+ /**
+ * Deserialize share data or user data into store data.
+ *
+ * @param dataBytes The data to parse
+ * @param shareData The flag indicating share data
+ * @throws XmlPullParserException
+ * @throws IOException
+ */
+ private void deserializeData(byte[] dataBytes, boolean shareData)
+ throws XmlPullParserException, IOException {
+ if (dataBytes == null) {
+ return;
+ }
+ final XmlPullParser in = Xml.newPullParser();
+ final ByteArrayInputStream inputStream = new ByteArrayInputStream(dataBytes);
+ in.setInput(inputStream, StandardCharsets.UTF_8.name());
+
+ // Start parsing the XML stream.
+ int rootTagDepth = in.getDepth() + 1;
+ parseDocumentStartAndVersionFromXml(in);
+
+ String[] headerName = new String[1];
+ while (XmlUtil.gotoNextSectionOrEnd(in, headerName, rootTagDepth)) {
+ StoreData storeData = mStoreDataList.get(headerName[0]);
+ if (storeData == null) {
+ throw new XmlPullParserException("Unknown store data: " + headerName[0]);
+ }
+ storeData.deserializeData(in, rootTagDepth + 1, shareData);
+ }
+ }
- return WifiConfigStoreData.parseRawData(null, userDataBytes);
+ /**
+ * Parse the document start and version from the XML stream.
+ * This is used for both the shared and user config store data.
+ *
+ * @param in XmlPullParser instance pointing to the XML stream.
+ * @return version number retrieved from the Xml stream.
+ */
+ private static int parseDocumentStartAndVersionFromXml(XmlPullParser in)
+ throws XmlPullParserException, IOException {
+ XmlUtil.gotoDocumentStart(in, XML_TAG_DOCUMENT_HEADER);
+ int version = (int) XmlUtil.readNextValueWithName(in, XML_TAG_VERSION);
+ if (version < INITIAL_CONFIG_STORE_DATA_VERSION
+ || version > CURRENT_CONFIG_STORE_DATA_VERSION) {
+ throw new XmlPullParserException("Invalid version of data: " + version);
+ }
+ return version;
}
/**
@@ -386,4 +527,58 @@ public class WifiConfigStore {
mWriteData = null;
}
}
+
+ /**
+ * Interface to be implemented by a module that contained data in the config store file.
+ *
+ * The module will be responsible for serializing/deserializing their own data.
+ */
+ public interface StoreData {
+ /**
+ * Serialize a XML data block to the output stream. The |shared| flag indicates if the
+ * output stream is backed by a share store or an user store.
+ *
+ * @param out The output stream to serialize the data to
+ * @param shared Flag indicating if the output stream is backed by a share store or an
+ * user store
+ */
+ void serializeData(XmlSerializer out, boolean shared)
+ throws XmlPullParserException, IOException;
+
+ /**
+ * Deserialize a XML data block from the input stream. The |shared| flag indicates if the
+ * input stream is backed by a share store or an user store. When |shared| is set to true,
+ * the shared configuration data will be overwritten by the parsed data. Otherwise,
+ * the user configuration will be overwritten by the parsed data.
+ *
+ * @param in The input stream to read the data from
+ * @param outerTagDepth The depth of the outer tag in the XML document
+ * @Param shared Flag indicating if the input stream is backed by a share store or an
+ * user store
+ */
+ void deserializeData(XmlPullParser in, int outerTagDepth, boolean shared)
+ throws XmlPullParserException, IOException;
+
+ /**
+ * Reset configuration data. The |shared| flag indicates which configuration data to
+ * reset. When |shared| is set to true, the shared configuration data will be reset.
+ * Otherwise, the user configuration data will be reset.
+ */
+ void resetData(boolean shared);
+
+ /**
+ * Return the name of this store data. The data will be enclosed under this tag in
+ * the XML block.
+ *
+ * @return The name of the store data
+ */
+ String getName();
+
+ /**
+ * Flag indicating if shared configuration data is supported.
+ *
+ * @return true if shared configuration data is supported
+ */
+ boolean supportShareData();
+ }
}
diff --git a/service/java/com/android/server/wifi/WifiConfigStoreData.java b/service/java/com/android/server/wifi/WifiConfigStoreData.java
deleted file mode 100644
index b55e2dc06..000000000
--- a/service/java/com/android/server/wifi/WifiConfigStoreData.java
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * Copyright (C) 2016 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.wifi.WifiConfiguration;
-import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
-import android.net.wifi.WifiEnterpriseConfig;
-import android.util.Pair;
-import android.util.Xml;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FastXmlSerializer;
-import com.android.server.wifi.util.XmlUtil;
-import com.android.server.wifi.util.XmlUtil.IpConfigurationXmlUtil;
-import com.android.server.wifi.util.XmlUtil.NetworkSelectionStatusXmlUtil;
-import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil;
-import com.android.server.wifi.util.XmlUtil.WifiEnterpriseConfigXmlUtil;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Class to encapsulate all the data to be stored across all the stores. This is a snapshot
- * of all the settings passed from {@link WifiConfigManager} to persistent store.
- * Instances of this class are passed from/to WifiConfigManager and WifiConfigStore for
- * writing/parsing data to/from the store files.
- *
- * Note: Nesting of objects during serialization makes it hard to deserialize data especially
- * when we have elements added to the parent object in future revisions. So, when we serialize
- * {@link WifiConfiguration} objects (representing saved networks), we add separate sections in the
- * XML for each nested object (such as {@link IpConfiguration} and {@link NetworkSelectionStatus})
- * within WifiConfiguration object.
- */
-public class WifiConfigStoreData {
- /**
- * Current config store data version. This will be incremented for any additions.
- */
- private static final int CURRENT_CONFIG_STORE_DATA_VERSION = 1;
- /** This list of older versions will be used to restore data from older config store. */
- /**
- * First version of the config store data format.
- */
- private static final int INITIAL_CONFIG_STORE_DATA_VERSION = 1;
- /**
- * List of XML section header tags in the config store data.
- */
- 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_NETWORK_LIST = "NetworkList";
- private static final String XML_TAG_SECTION_HEADER_NETWORK = "Network";
- private static final String XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION = "WifiConfiguration";
- private static final String XML_TAG_SECTION_HEADER_NETWORK_STATUS = "NetworkStatus";
- private static final String XML_TAG_SECTION_HEADER_IP_CONFIGURATION = "IpConfiguration";
- private static final String XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION =
- "WifiEnterpriseConfiguration";
- private static final String XML_TAG_SECTION_HEADER_DELETED_EPHEMERAL_SSID_LIST =
- "DeletedEphemeralSSIDList";
- /**
- * List of saved shared networks visible to all the users to be stored in the shared store file.
- */
- private final List<WifiConfiguration> mSharedConfigurations;
- /**
- * List of saved private networks only visible to the current user to be stored in the user
- * specific store file.
- */
- private final List<WifiConfiguration> mUserConfigurations;
- /**
- * List of deleted ephemeral ssids to be stored.
- */
- private final Set<String> mDeletedEphemeralSSIDs;
-
- /**
- * Create a new instance of store data to be written to the store files.
- *
- * @param userConfigurations list of saved private networks to be stored.
- * See {@link WifiConfigManager#mConfiguredNetworks}.
- * @param sharedConfigurations list of saved shared networks to be stored.
- * See {@link WifiConfigManager#mConfiguredNetworks}.
- * @param deletedEphemeralSSIDs list of deleted ephemeral ssids to be stored.
- * See {@link WifiConfigManager#mDeletedEphemeralSSIDs}
- */
- public WifiConfigStoreData(
- List<WifiConfiguration> sharedConfigurations,
- List<WifiConfiguration> userConfigurations,
- Set<String> deletedEphemeralSSIDs) {
- this.mSharedConfigurations = sharedConfigurations;
- this.mUserConfigurations = userConfigurations;
- this.mDeletedEphemeralSSIDs = deletedEphemeralSSIDs;
- }
-
- /**
- * Returns the list of all network configurations in the store data instance. This includes both
- * the shared networks and user private networks.
- *
- * @return List of WifiConfiguration objects corresponding to the networks.
- */
- @VisibleForTesting
- public List<WifiConfiguration> getConfigurations() {
- List<WifiConfiguration> configurations = new ArrayList<>();
- configurations.addAll(mSharedConfigurations);
- configurations.addAll(mUserConfigurations);
- return configurations;
- }
-
- /**
- * Returns the list of shared network configurations in the store data instance.
- *
- * @return List of WifiConfiguration objects corresponding to the networks.
- */
- public List<WifiConfiguration> getSharedConfigurations() {
- return mSharedConfigurations;
- }
-
- /**
- * Returns the list of user network configurations in the store data instance.
- *
- * @return List of WifiConfiguration objects corresponding to the networks.
- */
- public List<WifiConfiguration> getUserConfigurations() {
- return mUserConfigurations;
- }
-
- /**
- * Returns the set of all deleted ephemeral SSIDs in the store data instance.
- *
- * @return List of Strings corresponding to the SSIDs of deleted ephemeral networks.
- */
- public Set<String> getDeletedEphemeralSSIDs() {
- return mDeletedEphemeralSSIDs;
- }
-
- /**
- * Create a new instance of the store data parsed from the store file data.
- *
- * Note: If any of the raw data is null or empty, will create an empty corresponding store data.
- * This is to handle fresh install devices where these stores are not yet created.
- *
- * @param sharedDataBytes raw data retrieved from the shared store file.
- * @param userDataBytes raw data retrieved from the user store file.
- * @return new instance of store data.
- */
- public static WifiConfigStoreData parseRawData(byte[] sharedDataBytes, byte[] userDataBytes)
- throws XmlPullParserException, IOException {
- SharedData sharedData;
- UserData userData;
- try {
- if (sharedDataBytes != null && sharedDataBytes.length > 0) {
- sharedData = SharedData.parseRawData(sharedDataBytes);
- } else {
- sharedData = new SharedData(new ArrayList<WifiConfiguration>());
- }
- if (userDataBytes != null && userDataBytes.length > 0) {
- userData = UserData.parseRawData(userDataBytes);
- } else {
- userData = new UserData(new ArrayList<WifiConfiguration>(), new HashSet<String>());
- }
- return getStoreData(sharedData, userData);
- } catch (ClassCastException e) {
- throw new XmlPullParserException("Wrong value type parsed: " + e);
- }
- }
-
- /**
- * Create a WifiConfigStoreData instance from the retrieved UserData & SharedData instance.
- */
- private static WifiConfigStoreData getStoreData(SharedData sharedData, UserData userData) {
- return new WifiConfigStoreData(
- sharedData.configurations, userData.configurations, userData.deletedEphemeralSSIDs);
- }
-
- /**
- * Write the list of networks to the XML stream.
- *
- * @param out XmlSerializer instance pointing to the XML stream.
- * @param configurations list of WifiConfiguration objects corresponding to the networks.
- */
- private static void writeNetworksToXml(
- XmlSerializer out, List<WifiConfiguration> configurations)
- throws XmlPullParserException, IOException {
- XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_LIST);
- for (WifiConfiguration configuration : configurations) {
- // Write this configuration data now.
- XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK);
- writeNetworkToXml(out, configuration);
- XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK);
- }
- XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_LIST);
- }
-
- /**
- * Write a network to the XML stream.
- * Nested objects within the provided WifiConfiguration object are written into separate XML
- * sections.
- *
- * @param out XmlSerializer instance pointing to the XML stream.
- * @param configuration WifiConfiguration object corresponding to the network.
- */
- private static void writeNetworkToXml(
- XmlSerializer out, WifiConfiguration configuration)
- throws XmlPullParserException, IOException {
- XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION);
- WifiConfigurationXmlUtil.writeToXmlForConfigStore(out, configuration);
- XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION);
-
- XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_STATUS);
- NetworkSelectionStatusXmlUtil.writeToXml(out, configuration.getNetworkSelectionStatus());
- XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_STATUS);
-
- XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_IP_CONFIGURATION);
- IpConfigurationXmlUtil.writeToXml(out, configuration.getIpConfiguration());
- XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_IP_CONFIGURATION);
-
- // Store the enterprise configuration for enterprise networks.
- if (configuration.enterpriseConfig != null
- && configuration.enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE) {
- XmlUtil.writeNextSectionStart(
- out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION);
- WifiEnterpriseConfigXmlUtil.writeToXml(out, configuration.enterpriseConfig);
- XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION);
- }
- }
-
- /**
- * Parses the list of networks from the provided XML stream.
- *
- * @param in XmlPullParser instance pointing to the XML stream.
- * @param outerTagDepth depth of the outer tag in the XML document.
- * @param dataVersion version number parsed from incoming data.
- * @return list of WifiConfiguration objects corresponding to the networks if parsing is
- * successful, null otherwise.
- */
- private static List<WifiConfiguration> parseNetworksFromXml(
- XmlPullParser in, int outerTagDepth, int dataVersion)
- throws XmlPullParserException, IOException {
- // Find the configuration list section.
- XmlUtil.gotoNextSectionWithName(in, 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, XML_TAG_SECTION_HEADER_NETWORK, networkListTagDepth)) {
- WifiConfiguration configuration =
- parseNetworkFromXml(in, networkListTagDepth, dataVersion);
- if (configuration != null) {
- configurations.add(configuration);
- }
- }
- return configurations;
- }
-
- /**
- * Helper method to parse the WifiConfiguration object and validate the configKey parsed.
- */
- private static WifiConfiguration parseWifiConfigurationFromXmlAndValidateConfigKey(
- XmlPullParser in, int outerTagDepth)
- throws XmlPullParserException, IOException {
- Pair<String, WifiConfiguration> parsedConfig =
- WifiConfigurationXmlUtil.parseFromXml(in, outerTagDepth);
- if (parsedConfig == null || parsedConfig.first == null || parsedConfig.second == null) {
- throw new XmlPullParserException("XML parsing of wifi configuration failed");
- }
- String configKeyParsed = parsedConfig.first;
- WifiConfiguration configuration = parsedConfig.second;
- String configKeyCalculated = configuration.configKey();
- if (!configKeyParsed.equals(configKeyCalculated)) {
- throw new XmlPullParserException(
- "Configuration key does not match. Retrieved: " + configKeyParsed
- + ", Calculated: " + configKeyCalculated);
- }
- return configuration;
- }
-
- /**
- * Parses a network from the provided XML stream.
- *
- * @param in XmlPullParser instance pointing to the XML stream.
- * @param outerTagDepth depth of the outer tag in the XML document.
- * @param dataVersion version number parsed from incoming data.
- * @return WifiConfiguration object corresponding to the network if parsing is successful,
- * null otherwise.
- */
- private static WifiConfiguration parseNetworkFromXml(
- XmlPullParser in, int outerTagDepth, int dataVersion)
- throws XmlPullParserException, IOException {
- // Any version migration needs to be handled here in future.
- if (dataVersion == INITIAL_CONFIG_STORE_DATA_VERSION) {
- WifiConfiguration configuration = null;
-
- int networkTagDepth = outerTagDepth + 1;
- XmlUtil.gotoNextSectionWithName(
- in, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION, networkTagDepth);
- int configTagDepth = networkTagDepth + 1;
- configuration = parseWifiConfigurationFromXmlAndValidateConfigKey(in, configTagDepth);
-
- XmlUtil.gotoNextSectionWithName(
- in, XML_TAG_SECTION_HEADER_NETWORK_STATUS, networkTagDepth);
- NetworkSelectionStatus status =
- NetworkSelectionStatusXmlUtil.parseFromXml(in, configTagDepth);
- configuration.setNetworkSelectionStatus(status);
-
- XmlUtil.gotoNextSectionWithName(
- in, XML_TAG_SECTION_HEADER_IP_CONFIGURATION, networkTagDepth);
- IpConfiguration ipConfiguration =
- IpConfigurationXmlUtil.parseFromXml(in, configTagDepth);
- configuration.setIpConfiguration(ipConfiguration);
-
- // Check if there is an enterprise configuration section.
- if (XmlUtil.gotoNextSectionWithNameOrEnd(
- in, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION, networkTagDepth)) {
- WifiEnterpriseConfig enterpriseConfig =
- WifiEnterpriseConfigXmlUtil.parseFromXml(in, configTagDepth);
- configuration.enterpriseConfig = enterpriseConfig;
- }
-
- return configuration;
- }
- return null;
- }
-
- /**
- * Write the document start and version to the XML stream.
- * This is used for both the shared and user config store data.
- *
- * @param out XmlSerializer instance pointing to the XML stream.
- */
- private static void writeDocumentStartAndVersionToXml(XmlSerializer out)
- throws XmlPullParserException, IOException {
- XmlUtil.writeDocumentStart(out, XML_TAG_DOCUMENT_HEADER);
- XmlUtil.writeNextValue(out, XML_TAG_VERSION, CURRENT_CONFIG_STORE_DATA_VERSION);
- }
-
- /**
- * Parse the document start and version from the XML stream.
- * This is used for both the shared and user config store data.
- *
- * @param in XmlPullParser instance pointing to the XML stream.
- * @return version number retrieved from the Xml stream.
- */
- private static int parseDocumentStartAndVersionFromXml(XmlPullParser in)
- throws XmlPullParserException, IOException {
- XmlUtil.gotoDocumentStart(in, XML_TAG_DOCUMENT_HEADER);
- int version = (int) XmlUtil.readNextValueWithName(in, XML_TAG_VERSION);
- if (version < INITIAL_CONFIG_STORE_DATA_VERSION
- || version > CURRENT_CONFIG_STORE_DATA_VERSION) {
- throw new XmlPullParserException("Invalid version of data: " + version);
- }
- return version;
- }
-
- /**
- * Create raw byte array to be stored in the share store file.
- * This method serializes the data to a byte array in XML format.
- *
- * @return byte array with the serialized output.
- */
- public byte[] createSharedRawData() throws XmlPullParserException, IOException {
- SharedData sharedData = getSharedData();
- return sharedData.createRawData();
- }
-
- /**
- * Create raw byte array to be stored in the user store file.
- * This method serializes the data to a byte array in XML format.
- *
- * @return byte array with the serialized output.
- */
- public byte[] createUserRawData() throws XmlPullParserException, IOException {
- UserData userData = getUserData();
- return userData.createRawData();
- }
-
- /**
- * Retrieve the shared data to be stored in the shared config store file.
- *
- * @return SharedData instance.
- */
- private SharedData getSharedData() {
- return new SharedData(mSharedConfigurations);
- }
-
- /**
- * Retrieve the user specific data to be stored in the user config store file.
- *
- * @return UserData instance.
- */
- private UserData getUserData() {
- return new UserData(mUserConfigurations, mDeletedEphemeralSSIDs);
- }
-
- /**
- * Class to encapsulate all the data to be stored in the shared store.
- */
- public static class SharedData {
- public List<WifiConfiguration> configurations;
-
- /**
- * Create a new instance of shared store data to be written to the store files.
- *
- * @param configurations list of shared saved networks to be stored.
- */
- public SharedData(List<WifiConfiguration> configurations) {
- this.configurations = configurations;
- }
-
- /**
- * Create a new instance of the shared store data parsed from the store file.
- * This method deserializes the provided byte array in XML format to a new SharedData
- * instance.
- *
- * @param sharedDataBytes raw data retrieved from the shared store file.
- * @return new instance of store data.
- */
- public static SharedData parseRawData(byte[] sharedDataBytes)
- throws XmlPullParserException, IOException {
- final XmlPullParser in = Xml.newPullParser();
- final ByteArrayInputStream inputStream = new ByteArrayInputStream(sharedDataBytes);
- in.setInput(inputStream, StandardCharsets.UTF_8.name());
-
- // Start parsing the XML stream.
- int rootTagDepth = in.getDepth() + 1;
- int version = parseDocumentStartAndVersionFromXml(in);
-
- List<WifiConfiguration> configurations =
- parseNetworksFromXml(in, rootTagDepth, version);
-
- return new SharedData(configurations);
- }
-
- /**
- * Create raw byte array to be stored in the store file.
- * This method serializes the data to a byte array in XML format.
- *
- * @return byte array with the serialized output.
- */
- public byte[] createRawData() throws XmlPullParserException, IOException {
- final XmlSerializer out = new FastXmlSerializer();
- final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- out.setOutput(outputStream, StandardCharsets.UTF_8.name());
-
- // Start writing the XML stream.
- writeDocumentStartAndVersionToXml(out);
-
- // Write all the shared network configurations.
- writeNetworksToXml(out, configurations);
-
- XmlUtil.writeDocumentEnd(out, XML_TAG_DOCUMENT_HEADER);
-
- byte[] data = outputStream.toByteArray();
-
- return data;
- }
- }
-
- /**
- * Class to encapsulate all the data to be stored in the user specific store.
- */
- public static class UserData {
- private static final String XML_TAG_SSID_LIST = "SSIDList";
-
- public List<WifiConfiguration> configurations;
- public Set<String> deletedEphemeralSSIDs;
-
- /**
- * Create a new instance of user specific store data to be written to the store files.
- *
- * @param configurations list of user specific saved networks to be stored.
- * @param deletedEphemeralSSIDs list of deleted ephemeral ssids to be stored.
- */
- public UserData(
- List<WifiConfiguration> configurations, Set<String> deletedEphemeralSSIDs) {
- this.configurations = configurations;
- this.deletedEphemeralSSIDs = deletedEphemeralSSIDs;
- }
-
- /**
- * Create a new instance of the user store data parsed from the store file.
- * This method deserializes the provided byte array in XML format to a new UserData
- * instance.
- *
- * @param userDataBytes raw data retrieved from the user store file.
- * @return new instance of store data.
- */
- public static UserData parseRawData(byte[] userDataBytes)
- throws XmlPullParserException, IOException {
- final XmlPullParser in = Xml.newPullParser();
- final ByteArrayInputStream inputStream = new ByteArrayInputStream(userDataBytes);
- in.setInput(inputStream, StandardCharsets.UTF_8.name());
-
- // Start parsing the XML stream.
- int rootTagDepth = in.getDepth() + 1;
- int version = parseDocumentStartAndVersionFromXml(in);
-
- List<WifiConfiguration> configurations =
- parseNetworksFromXml(in, rootTagDepth, version);
-
- XmlUtil.gotoNextSectionWithName(
- in, XML_TAG_SECTION_HEADER_DELETED_EPHEMERAL_SSID_LIST, rootTagDepth);
- Set<String> deletedEphemralList =
- (Set<String>) XmlUtil.readNextValueWithName(in, XML_TAG_SSID_LIST);
-
- return new UserData(configurations, deletedEphemralList);
- }
-
- /**
- * Create raw byte array to be stored in the store file.
- * This method serializes the data to a byte array in XML format.
- *
- * @return byte array with the serialized output.
- */
- public byte[] createRawData() throws XmlPullParserException, IOException {
- final XmlSerializer out = new FastXmlSerializer();
- final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
- out.setOutput(outputStream, StandardCharsets.UTF_8.name());
-
- // Start writing the XML stream.
- writeDocumentStartAndVersionToXml(out);
-
- // Write all the user network configurations.
- writeNetworksToXml(out, configurations);
-
- XmlUtil.writeNextSectionStart(
- out, XML_TAG_SECTION_HEADER_DELETED_EPHEMERAL_SSID_LIST);
- XmlUtil.writeNextValue(out, XML_TAG_SSID_LIST, deletedEphemeralSSIDs);
- XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_DELETED_EPHEMERAL_SSID_LIST);
-
- XmlUtil.writeDocumentEnd(out, XML_TAG_DOCUMENT_HEADER);
-
- byte[] data = outputStream.toByteArray();
-
- return data;
- }
- }
-}
-
-
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index 7c976cf44..a5cb95b98 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -180,7 +180,8 @@ public class WifiInjector {
// Config Manager
mWifiConfigManager = new WifiConfigManager(mContext, mFrameworkFacade, mClock,
UserManager.get(mContext), TelephonyManager.from(mContext),
- mWifiKeyStore, mWifiConfigStore, mWifiConfigStoreLegacy, mWifiPermissionsWrapper);
+ mWifiKeyStore, mWifiConfigStore, mWifiConfigStoreLegacy, mWifiPermissionsWrapper,
+ new NetworkListStoreData(), new DeletedEphemeralSsidsStoreData());
mWifiNetworkScoreCache = new WifiNetworkScoreCache(mContext);
mWifiNetworkSelector = new WifiNetworkSelector(mContext, mWifiConfigManager, mClock);
LocalLog localLog = mWifiNetworkSelector.getLocalLog();
diff --git a/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java
new file mode 100644
index 000000000..0db93f598
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/DeletedEphemeralSsidsStoreDataTest.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2017 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 static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.DeletedEphemeralSsidsStoreData}.
+ */
+@SmallTest
+public class DeletedEphemeralSsidsStoreDataTest {
+ private static final String TEST_SSID1 = "SSID 1";
+ private static final String TEST_SSID2 = "SSID 2";
+ private static final String TEST_SSID_LIST_XML_STRING =
+ "<set name=\"SSIDList\">\n"
+ + "<string>" + TEST_SSID1 + "</string>\n"
+ + "<string>" + TEST_SSID2 + "</string>\n"
+ + "</set>\n";
+ private static final byte[] TEST_SSID_LIST_XML_BYTES =
+ TEST_SSID_LIST_XML_STRING.getBytes(StandardCharsets.UTF_8);
+ private DeletedEphemeralSsidsStoreData mDeletedEphemeralSsidsStoreData;
+
+ @Before
+ public void setUp() throws Exception {
+ mDeletedEphemeralSsidsStoreData = new DeletedEphemeralSsidsStoreData();
+ }
+
+ /**
+ * Helper function for serializing configuration data to a XML block.
+ *
+ * @param shared Flag indicating serializing shared or user configurations
+ * @return byte[] of the XML data
+ * @throws Exception
+ */
+ private byte[] serializeData(boolean shared) throws Exception {
+ final XmlSerializer out = new FastXmlSerializer();
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ out.setOutput(outputStream, StandardCharsets.UTF_8.name());
+ mDeletedEphemeralSsidsStoreData.serializeData(out, shared);
+ out.flush();
+ return outputStream.toByteArray();
+ }
+
+ /**
+ * Helper function for parsing configuration data from a XML block.
+ *
+ * @param data XML data to parse from
+ * @param shared Flag indicating parsing of shared or user configurations
+ * @return SSID list
+ * @throws Exception
+ */
+ private Set<String> deserializeData(byte[] data, boolean shared) throws Exception {
+ final XmlPullParser in = Xml.newPullParser();
+ final ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
+ in.setInput(inputStream, StandardCharsets.UTF_8.name());
+ mDeletedEphemeralSsidsStoreData.deserializeData(in, in.getDepth(), shared);
+ return mDeletedEphemeralSsidsStoreData.getSsidList();
+ }
+
+ /**
+ * Verify that a XmlPullParserException will be thrown when attempting to serialize SSID list
+ * to the share store, since the deleted ephemeral SSID list should never be persist
+ * to the share store.
+ *
+ * @throws Exception
+ */
+ @Test(expected = XmlPullParserException.class)
+ public void serializeShareData() throws Exception {
+ serializeData(true /* shared */);
+ }
+
+ /**
+ * Verify that a XmlPullParserException will be thrown when attempting to parse SSID list
+ * from the share store, since the deleted ephemeral SSID list should never be persist
+ * to the share store.
+ *
+ * @throws Exception
+ */
+ @Test(expected = XmlPullParserException.class)
+ public void deserializeShareData() throws Exception {
+ deserializeData(new byte[0], true /* shared */);
+ }
+
+ /**
+ * Verify that serializing the user store data without any configuration doesn't cause any
+ * crash and no data should be serialized.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void serializeEmptyConfigs() throws Exception {
+ assertEquals(0, serializeData(false /* shared */).length);
+ }
+
+ /**
+ * Verify that parsing an empty data doesn't cause any crash and no configuration should
+ * be deserialized.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void deserializeEmptyData() throws Exception {
+ assertTrue(deserializeData(new byte[0], false /* shared */).isEmpty());
+ }
+
+ /**
+ * Verify that DeletedEphemeralSsidsStoreData does not support share data.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void supportShareData() throws Exception {
+ assertFalse(mDeletedEphemeralSsidsStoreData.supportShareData());
+ }
+
+ /**
+ * Verify that user store SSID list is serialized correctly, matches the predefined test
+ * XML data.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void serializeSsidList() throws Exception {
+ Set<String> ssidList = new HashSet<>();
+ ssidList.add(TEST_SSID1);
+ ssidList.add(TEST_SSID2);
+ mDeletedEphemeralSsidsStoreData.setSsidList(ssidList);
+ byte[] actualData = serializeData(false /* shared */);
+ assertTrue(Arrays.equals(TEST_SSID_LIST_XML_BYTES, actualData));
+ }
+
+ /**
+ * Verify that user store SSID list is deserialized correctly using the predefined test XML
+ * data.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void deserializeSsidList() throws Exception {
+ Set<String> ssidList = new HashSet<>();
+ ssidList.add(TEST_SSID1);
+ ssidList.add(TEST_SSID2);
+ assertEquals(ssidList, deserializeData(TEST_SSID_LIST_XML_BYTES, false /* shared */));
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java
new file mode 100644
index 000000000..a1f0057e2
--- /dev/null
+++ b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2017 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 static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import android.net.wifi.WifiConfiguration;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Unit tests for {@link com.android.server.wifi.NetworksListStoreData}.
+ */
+@SmallTest
+public class NetworkListStoreDataTest {
+
+ private static final String TEST_SSID = "WifiConfigStoreDataSSID_";
+ private static final String TEST_CONNECT_CHOICE = "XmlUtilConnectChoice";
+ private static final long TEST_CONNECT_CHOICE_TIMESTAMP = 0x4566;
+ private static final String SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT =
+ "<Network>\n"
+ + "<WifiConfiguration>\n"
+ + "<string name=\"ConfigKey\">%s</string>\n"
+ + "<string name=\"SSID\">%s</string>\n"
+ + "<null name=\"BSSID\" />\n"
+ + "<null name=\"PreSharedKey\" />\n"
+ + "<null name=\"WEPKeys\" />\n"
+ + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n"
+ + "<boolean name=\"HiddenSSID\" value=\"false\" />\n"
+ + "<boolean name=\"RequirePMF\" value=\"false\" />\n"
+ + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n"
+ + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n"
+ + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n"
+ + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n"
+ + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n"
+ + "<boolean name=\"Shared\" value=\"%s\" />\n"
+ + "<null name=\"FQDN\" />\n"
+ + "<null name=\"ProviderFriendlyName\" />\n"
+ + "<null name=\"LinkedNetworksList\" />\n"
+ + "<null name=\"DefaultGwMacAddress\" />\n"
+ + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n"
+ + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n"
+ + "<int name=\"UserApproved\" value=\"0\" />\n"
+ + "<boolean name=\"MeteredHint\" value=\"false\" />\n"
+ + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
+ + "<int name=\"NumAssociation\" value=\"0\" />\n"
+ + "<int name=\"CreatorUid\" value=\"%d\" />\n"
+ + "<null name=\"CreatorName\" />\n"
+ + "<null name=\"CreationTime\" />\n"
+ + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
+ + "<null name=\"LastUpdateName\" />\n"
+ + "<int name=\"LastConnectUid\" value=\"0\" />\n"
+ + "</WifiConfiguration>\n"
+ + "<NetworkStatus>\n"
+ + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n"
+ + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n"
+ + "<null name=\"ConnectChoice\" />\n"
+ + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n"
+ + "<boolean name=\"HasEverConnected\" value=\"false\" />\n"
+ + "</NetworkStatus>\n"
+ + "<IpConfiguration>\n"
+ + "<string name=\"IpAssignment\">DHCP</string>\n"
+ + "<string name=\"ProxySettings\">NONE</string>\n"
+ + "</IpConfiguration>\n"
+ + "</Network>\n";
+
+ private static final String SINGLE_EAP_NETWORK_DATA_XML_STRING_FORMAT =
+ "<Network>\n"
+ + "<WifiConfiguration>\n"
+ + "<string name=\"ConfigKey\">%s</string>\n"
+ + "<string name=\"SSID\">%s</string>\n"
+ + "<null name=\"BSSID\" />\n"
+ + "<null name=\"PreSharedKey\" />\n"
+ + "<null name=\"WEPKeys\" />\n"
+ + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n"
+ + "<boolean name=\"HiddenSSID\" value=\"false\" />\n"
+ + "<boolean name=\"RequirePMF\" value=\"false\" />\n"
+ + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">0c</byte-array>\n"
+ + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n"
+ + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n"
+ + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n"
+ + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n"
+ + "<boolean name=\"Shared\" value=\"%s\" />\n"
+ + "<null name=\"FQDN\" />\n"
+ + "<null name=\"ProviderFriendlyName\" />\n"
+ + "<null name=\"LinkedNetworksList\" />\n"
+ + "<null name=\"DefaultGwMacAddress\" />\n"
+ + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n"
+ + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n"
+ + "<int name=\"UserApproved\" value=\"0\" />\n"
+ + "<boolean name=\"MeteredHint\" value=\"false\" />\n"
+ + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
+ + "<int name=\"NumAssociation\" value=\"0\" />\n"
+ + "<int name=\"CreatorUid\" value=\"%d\" />\n"
+ + "<null name=\"CreatorName\" />\n"
+ + "<null name=\"CreationTime\" />\n"
+ + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
+ + "<null name=\"LastUpdateName\" />\n"
+ + "<int name=\"LastConnectUid\" value=\"0\" />\n"
+ + "</WifiConfiguration>\n"
+ + "<NetworkStatus>\n"
+ + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n"
+ + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n"
+ + "<null name=\"ConnectChoice\" />\n"
+ + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n"
+ + "<boolean name=\"HasEverConnected\" value=\"false\" />\n"
+ + "</NetworkStatus>\n"
+ + "<IpConfiguration>\n"
+ + "<string name=\"IpAssignment\">DHCP</string>\n"
+ + "<string name=\"ProxySettings\">NONE</string>\n"
+ + "</IpConfiguration>\n"
+ + "<WifiEnterpriseConfiguration>\n"
+ + "<string name=\"Identity\"></string>\n"
+ + "<string name=\"AnonIdentity\"></string>\n"
+ + "<string name=\"Password\"></string>\n"
+ + "<string name=\"ClientCert\"></string>\n"
+ + "<string name=\"CaCert\"></string>\n"
+ + "<string name=\"SubjectMatch\"></string>\n"
+ + "<string name=\"Engine\"></string>\n"
+ + "<string name=\"EngineId\"></string>\n"
+ + "<string name=\"PrivateKeyId\"></string>\n"
+ + "<string name=\"AltSubjectMatch\"></string>\n"
+ + "<string name=\"DomSuffixMatch\"></string>\n"
+ + "<string name=\"CaPath\"></string>\n"
+ + "<int name=\"EapMethod\" value=\"2\" />\n"
+ + "<int name=\"Phase2Method\" value=\"0\" />\n"
+ + "</WifiEnterpriseConfiguration>\n"
+ + "</Network>\n";
+
+ private NetworkListStoreData mNetworkListStoreData;
+
+ @Before
+ public void setUp() throws Exception {
+ mNetworkListStoreData = new NetworkListStoreData();
+ }
+
+ /**
+ * Helper function for serializing configuration data to a XML block.
+ *
+ * @param shared Flag indicating serializing shared or user configurations
+ * @return byte[] of the XML data
+ * @throws Exception
+ */
+ private byte[] serializeData(boolean shared) throws Exception {
+ final XmlSerializer out = new FastXmlSerializer();
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ out.setOutput(outputStream, StandardCharsets.UTF_8.name());
+ mNetworkListStoreData.serializeData(out, shared);
+ out.flush();
+ return outputStream.toByteArray();
+ }
+
+ /**
+ * Helper function for parsing configuration data from a XML block.
+ *
+ * @param data XML data to parse from
+ * @param shared Flag indicating parsing of shared or user configurations
+ * @return List of WifiConfiguration parsed
+ * @throws Exception
+ */
+ private List<WifiConfiguration> deserializeData(byte[] data, boolean shared) throws Exception {
+ final XmlPullParser in = Xml.newPullParser();
+ final ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
+ in.setInput(inputStream, StandardCharsets.UTF_8.name());
+ mNetworkListStoreData.deserializeData(in, in.getDepth(), shared);
+ if (shared) {
+ return mNetworkListStoreData.getSharedConfigurations();
+ } else {
+ return mNetworkListStoreData.getUserConfigurations();
+ }
+ }
+
+ /**
+ * Helper function for generating a network list for testing purpose. The network list
+ * will contained an open and an EAP network.
+ *
+ * @param shared Flag indicating shared network
+ * @return List of WifiConfiguration
+ */
+ private List<WifiConfiguration> getTestNetworksConfig(boolean shared) {
+ WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+ openNetwork.shared = shared;
+ openNetwork.setIpConfiguration(
+ WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
+ WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork();
+ eapNetwork.shared = shared;
+ eapNetwork.setIpConfiguration(
+ WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
+ List<WifiConfiguration> networkList = new ArrayList<>();
+ networkList.add(openNetwork);
+ networkList.add(eapNetwork);
+ return networkList;
+ }
+
+ /**
+ * Helper function for generating XML block containing two networks, an open and an EAP
+ * network.
+ *
+ * @param openNetwork The WifiConfiguration for an open network
+ * @param eapNetwork The WifiConfiguration for an EAP network
+ * @return byte[] of the XML data
+ */
+ private byte[] getTestNetworksXmlBytes(WifiConfiguration openNetwork,
+ WifiConfiguration eapNetwork) {
+ String openNetworkXml = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT,
+ openNetwork.configKey().replaceAll("\"", "&quot;"),
+ openNetwork.SSID.replaceAll("\"", "&quot;"),
+ openNetwork.shared, openNetwork.creatorUid);
+ String eapNetworkXml = String.format(SINGLE_EAP_NETWORK_DATA_XML_STRING_FORMAT,
+ eapNetwork.configKey().replaceAll("\"", "&quot;"),
+ eapNetwork.SSID.replaceAll("\"", "&quot;"),
+ eapNetwork.shared, eapNetwork.creatorUid);
+ return (openNetworkXml + eapNetworkXml).getBytes(StandardCharsets.UTF_8);
+ }
+
+ /**
+ * Verify that serializing the store data without any configuration doesn't cause any crash
+ * and no data should be serialized.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void serializeEmptyConfigs() throws Exception {
+ assertEquals(0, serializeData(true /* shared */).length);
+ assertEquals(0, serializeData(false /* shared */).length);
+ }
+
+ /**
+ * Verify that parsing an empty data doesn't cause any crash and no configuration should
+ * be parsed.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void deserializeEmptyData() throws Exception {
+ assertTrue(deserializeData(new byte[0], true /* shared */).isEmpty());
+ assertTrue(deserializeData(new byte[0], false /* shared */).isEmpty());
+ }
+
+ /**
+ * Verify that NetworkListStoreData does support share data.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void supportShareData() throws Exception {
+ assertTrue(mNetworkListStoreData.supportShareData());
+ }
+
+ /**
+ * Verify that the shared configurations (containing an open and an EAP network) are serialized
+ * correctly, matching the expected XML string.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void serializeSharedConfigurations() throws Exception {
+ List<WifiConfiguration> networkList = getTestNetworksConfig(true /* shared */);
+ mNetworkListStoreData.setSharedConfigurations(networkList);
+ byte[] expectedData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1));
+ assertTrue(Arrays.equals(expectedData, serializeData(true /* shared */)));
+ }
+
+ /**
+ * Verify that the shared configurations are parsed correctly from a XML string containing
+ * test networks (an open and an EAP network).
+ * @throws Exception
+ */
+ @Test
+ public void deserializeSharedConfigurations() throws Exception {
+ List<WifiConfiguration> networkList = getTestNetworksConfig(true /* shared */);
+ byte[] xmlData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1));
+ WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore(
+ networkList, deserializeData(xmlData, true /* shared */));
+ }
+
+ /**
+ * Verify that the user configurations (containing an open and an EAP network) are serialized
+ * correctly, matching the expected XML string.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void serializeUserConfigurations() throws Exception {
+ List<WifiConfiguration> networkList = getTestNetworksConfig(false /* shared */);
+ mNetworkListStoreData.setUserConfigurations(networkList);
+ byte[] expectedData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1));
+ assertTrue(Arrays.equals(expectedData, serializeData(false /* shared */)));
+ }
+
+ /**
+ * Verify that the user configurations are parsed correctly from a XML string containing
+ * test networks (an open and an EAP network).
+ * @throws Exception
+ */
+ @Test
+ public void deserializeUserConfigurations() throws Exception {
+ List<WifiConfiguration> networkList = getTestNetworksConfig(false /* shared */);
+ byte[] xmlData = getTestNetworksXmlBytes(networkList.get(0), networkList.get(1));
+ WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore(
+ networkList, deserializeData(xmlData, false /* shared */));
+ }
+
+ /**
+ * Verify that a XmlPullParserException will be thrown when parsing a <Network> block
+ * containing an unknown tag.
+ *
+ * @throws Exception
+ */
+ @Test(expected = XmlPullParserException.class)
+ public void parseNetworkWithUnknownTag() throws Exception {
+ String configFormat =
+ "<Network>\n"
+ + "<WifiConfiguration>\n"
+ + "<string name=\"ConfigKey\">%s</string>\n"
+ + "<string name=\"SSID\">%s</string>\n"
+ + "<null name=\"BSSID\" />\n"
+ + "<null name=\"PreSharedKey\" />\n"
+ + "<null name=\"WEPKeys\" />\n"
+ + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n"
+ + "<boolean name=\"HiddenSSID\" value=\"false\" />\n"
+ + "<boolean name=\"RequirePMF\" value=\"false\" />\n"
+ + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n"
+ + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n"
+ + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n"
+ + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n"
+ + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n"
+ + "<boolean name=\"Shared\" value=\"%s\" />\n"
+ + "<null name=\"FQDN\" />\n"
+ + "<null name=\"ProviderFriendlyName\" />\n"
+ + "<null name=\"LinkedNetworksList\" />\n"
+ + "<null name=\"DefaultGwMacAddress\" />\n"
+ + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n"
+ + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n"
+ + "<int name=\"UserApproved\" value=\"0\" />\n"
+ + "<boolean name=\"MeteredHint\" value=\"false\" />\n"
+ + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
+ + "<int name=\"NumAssociation\" value=\"0\" />\n"
+ + "<int name=\"CreatorUid\" value=\"%d\" />\n"
+ + "<null name=\"CreatorName\" />\n"
+ + "<null name=\"CreationTime\" />\n"
+ + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
+ + "<null name=\"LastUpdateName\" />\n"
+ + "<int name=\"LastConnectUid\" value=\"0\" />\n"
+ + "</WifiConfiguration>\n"
+ + "<NetworkStatus>\n"
+ + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n"
+ + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n"
+ + "<null name=\"ConnectChoice\" />\n"
+ + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n"
+ + "<boolean name=\"HasEverConnected\" value=\"false\" />\n"
+ + "</NetworkStatus>\n"
+ + "<IpConfiguration>\n"
+ + "<string name=\"IpAssignment\">DHCP</string>\n"
+ + "<string name=\"ProxySettings\">NONE</string>\n"
+ + "</IpConfiguration>\n"
+ + "<Unknown>" // Unknown tag.
+ + "<int name=\"test\" value=\"0\" />\n"
+ + "</Unknown>"
+ + "</Network>\n";
+ WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+ byte[] xmlData = String.format(configFormat,
+ openNetwork.configKey().replaceAll("\"", "&quot;"),
+ openNetwork.SSID.replaceAll("\"", "&quot;"),
+ openNetwork.shared, openNetwork.creatorUid).getBytes(StandardCharsets.UTF_8);
+ deserializeData(xmlData, true);
+ }
+
+ /**
+ * Verify that a XmlPullParseException will be thrown when parsing a network configuration
+ * containing a mismatched config key.
+ *
+ * @throws Exception
+ */
+ @Test(expected = XmlPullParserException.class)
+ public void parseNetworkWithMismatchConfigKey() throws Exception {
+ WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+ byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT,
+ "InvalidConfigKey",
+ openNetwork.SSID.replaceAll("\"", "&quot;"),
+ openNetwork.shared, openNetwork.creatorUid).getBytes(StandardCharsets.UTF_8);
+ deserializeData(xmlData, true);
+ }
+}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index 8c0163dda..892081423 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -40,6 +40,7 @@ import android.os.UserManager;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
+import android.util.Pair;
import com.android.internal.R;
import com.android.server.wifi.WifiConfigStoreLegacy.WifiConfigStoreDataLegacy;
@@ -103,9 +104,12 @@ public class WifiConfigManagerTest {
@Mock private PackageManager mPackageManager;
@Mock private DevicePolicyManagerInternal mDevicePolicyManagerInternal;
@Mock private WifiPermissionsWrapper mWifiPermissionsWrapper;
+ @Mock private NetworkListStoreData mNetworkListStoreData;
+ @Mock private DeletedEphemeralSsidsStoreData mDeletedEphemeralSsidsStoreData;
private MockResources mResources;
private InOrder mContextConfigStoreMockOrder;
+ private InOrder mNetworkListStoreDataMockOrder;
private WifiConfigManager mWifiConfigManager;
/**
@@ -118,6 +122,7 @@ public class WifiConfigManagerTest {
// Set up the inorder for verifications. This is needed to verify that the broadcasts,
// store writes for network updates followed by network additions are in the expected order.
mContextConfigStoreMockOrder = inOrder(mContext, mWifiConfigStore);
+ mNetworkListStoreDataMockOrder = inOrder(mNetworkListStoreData);
// Set up the package name stuff & permission override.
when(mContext.getPackageManager()).thenReturn(mPackageManager);
@@ -173,9 +178,6 @@ public class WifiConfigManagerTest {
.thenReturn(true);
when(mWifiConfigStore.areStoresPresent()).thenReturn(true);
- when(mWifiConfigStore.read())
- .thenReturn(new WifiConfigStoreData(new ArrayList<WifiConfiguration>(),
- new ArrayList<WifiConfiguration>(), new HashSet<String>()));
when(mDevicePolicyManagerInternal.isActiveAdminWithPolicy(anyInt(), anyInt()))
.thenReturn(false);
@@ -285,9 +287,13 @@ public class WifiConfigManagerTest {
assertTrue(addNetworkToWifiConfigManager(openNetwork).isSuccess());
// The open network addition should trigger a store write.
- WifiConfigStoreData storeData = captureWriteStoreData();
- assertFalse(isNetworkInConfigStoreData(ephemeralNetwork, storeData));
- assertTrue(isNetworkInConfigStoreData(openNetwork, storeData));
+ Pair<List<WifiConfiguration>, List<WifiConfiguration>> networkListStoreData =
+ captureWriteNetworksListStoreData();
+ List<WifiConfiguration> networkList = new ArrayList<>();
+ networkList.addAll(networkListStoreData.first);
+ networkList.addAll(networkListStoreData.second);
+ assertFalse(isNetworkInConfigStoreData(ephemeralNetwork, networkList));
+ assertTrue(isNetworkInConfigStoreData(openNetwork, networkList));
}
/**
@@ -1822,10 +1828,9 @@ public class WifiConfigManagerTest {
add(user1Network);
}
};
- WifiConfigStoreData loadStoreData =
- new WifiConfigStoreData(sharedNetworks, user1Networks, new HashSet<String>());
- when(mWifiConfigStore.read()).thenReturn(loadStoreData);
+ setupStoreDataForRead(sharedNetworks, user1Networks, new HashSet<String>());
assertTrue(mWifiConfigManager.loadFromStore());
+ verify(mWifiConfigStore).read();
// Fetch the network ID's assigned to the shared networks initially.
int sharedNetwork1Id = WifiConfiguration.INVALID_NETWORK_ID;
@@ -1848,14 +1853,11 @@ public class WifiConfigManagerTest {
add(user2Network);
}
};
- WifiConfigStoreData newUserStoreData =
- new WifiConfigStoreData(new ArrayList<WifiConfiguration>(), user2Networks,
- new HashSet<String>());
- when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)))
- .thenReturn(newUserStoreData);
+ setupStoreDataForUserRead(user2Networks, new HashSet<String>());
// Now switch the user to user 2 and ensure that shared network's IDs have not changed.
when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true);
mWifiConfigManager.handleUserSwitch(user2);
+ verify(mWifiConfigStore).switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class));
// Again fetch the network ID's assigned to the shared networks and ensure they have not
// changed.
@@ -1908,10 +1910,9 @@ public class WifiConfigManagerTest {
add(user1Network);
}
};
- WifiConfigStoreData loadStoreData =
- new WifiConfigStoreData(sharedNetworks, user1Networks, new HashSet<String>());
- when(mWifiConfigStore.read()).thenReturn(loadStoreData);
+ setupStoreDataForRead(sharedNetworks, user1Networks, new HashSet<String>());
assertTrue(mWifiConfigManager.loadFromStore());
+ verify(mWifiConfigStore).read();
// Fetch the network ID assigned to the user 1 network initially.
int user1NetworkId = WifiConfiguration.INVALID_NETWORK_ID;
@@ -1929,14 +1930,11 @@ public class WifiConfigManagerTest {
add(user2Network);
}
};
- WifiConfigStoreData newUserStoreData =
- new WifiConfigStoreData(new ArrayList<WifiConfiguration>(), user2Networks,
- new HashSet<String>());
- when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)))
- .thenReturn(newUserStoreData);
+ setupStoreDataForUserRead(user2Networks, new HashSet<String>());
// Now switch the user to user 2 and ensure that user 1's private network has been removed.
when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true);
Set<Integer> removedNetworks = mWifiConfigManager.handleUserSwitch(user2);
+ verify(mWifiConfigStore).switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class));
assertTrue((removedNetworks.size() == 1) && (removedNetworks.contains(user1NetworkId)));
// Set the expected networks to be |sharedNetwork| and |user2Network|.
@@ -1983,11 +1981,10 @@ public class WifiConfigManagerTest {
add(sharedNetwork);
}
};
- WifiConfigStoreData loadStoreData =
- new WifiConfigStoreData(sharedNetworks, new ArrayList<WifiConfiguration>(),
- new HashSet<String>());
- when(mWifiConfigStore.read()).thenReturn(loadStoreData);
+ setupStoreDataForRead(sharedNetworks, new ArrayList<WifiConfiguration>(),
+ new HashSet<String>());
assertTrue(mWifiConfigManager.loadFromStore());
+ verify(mWifiConfigStore).read();
// Set up the user 2 store data that is loaded at user switch.
List<WifiConfiguration> user2Networks = new ArrayList<WifiConfiguration>() {
@@ -1995,14 +1992,11 @@ public class WifiConfigManagerTest {
add(user2Network);
}
};
- WifiConfigStoreData newUserStoreData =
- new WifiConfigStoreData(new ArrayList<WifiConfiguration>(), user2Networks,
- new HashSet<String>());
- when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)))
- .thenReturn(newUserStoreData);
+ setupStoreDataForUserRead(user2Networks, new HashSet<String>());
// Now switch the user to user 2 and ensure that no private network has been removed.
when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true);
Set<Integer> removedNetworks = mWifiConfigManager.handleUserSwitch(user2);
+ verify(mWifiConfigStore).switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class));
assertTrue(removedNetworks.isEmpty());
}
@@ -2040,11 +2034,10 @@ public class WifiConfigManagerTest {
add(user2Network);
}
};
- WifiConfigStoreData loadStoreData =
- new WifiConfigStoreData(sharedNetworks, new ArrayList<WifiConfiguration>(),
- new HashSet<String>());
- when(mWifiConfigStore.read()).thenReturn(loadStoreData);
+ setupStoreDataForRead(sharedNetworks, new ArrayList<WifiConfiguration>(),
+ new HashSet<String>());
assertTrue(mWifiConfigManager.loadFromStore());
+ verify(mWifiConfigStore).read();
// Set up the user store data that is loaded at user unlock.
List<WifiConfiguration> userNetworks = new ArrayList<WifiConfiguration>() {
@@ -2052,19 +2045,17 @@ public class WifiConfigManagerTest {
add(user1Network);
}
};
- WifiConfigStoreData unlockLoadStoreData =
- new WifiConfigStoreData(new ArrayList<WifiConfiguration>(), userNetworks,
- new HashSet<String>());
- when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)))
- .thenReturn(unlockLoadStoreData);
+ setupStoreDataForUserRead(userNetworks, new HashSet<String>());
mWifiConfigManager.handleUserUnlock(user1);
+ verify(mWifiConfigStore).switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class));
// Capture the written data for the user 1 and ensure that it corresponds to what was
// setup.
- WifiConfigStoreData writtenStoreData = captureWriteStoreData();
+ Pair<List<WifiConfiguration>, List<WifiConfiguration>> writtenNetworkList =
+ captureWriteNetworksListStoreData();
WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate(
- sharedNetworks, writtenStoreData.getSharedConfigurations());
+ sharedNetworks, writtenNetworkList.first);
WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate(
- userNetworks, writtenStoreData.getUserConfigurations());
+ userNetworks, writtenNetworkList.second);
// Now switch the user to user2 and ensure that user 2's private network has been moved to
// the user store.
@@ -2087,19 +2078,19 @@ public class WifiConfigManagerTest {
};
// Capture the first written data triggered for saving the old user's network
// configurations.
- writtenStoreData = captureWriteStoreData();
+ writtenNetworkList = captureWriteNetworksListStoreData();
WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate(
- sharedNetworks, writtenStoreData.getSharedConfigurations());
+ sharedNetworks, writtenNetworkList.first);
WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate(
- userNetworks, writtenStoreData.getUserConfigurations());
+ userNetworks, writtenNetworkList.second);
// Now capture the next written data triggered after the switch and ensure that user 2's
// network is now in user store data.
- writtenStoreData = captureWriteStoreData();
+ writtenNetworkList = captureWriteNetworksListStoreData();
WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate(
- expectedSharedNetworks, writtenStoreData.getSharedConfigurations());
+ expectedSharedNetworks, writtenNetworkList.first);
WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate(
- expectedUserNetworks, writtenStoreData.getUserConfigurations());
+ expectedUserNetworks, writtenNetworkList.second);
}
/**
@@ -2116,11 +2107,7 @@ public class WifiConfigManagerTest {
// Set up the internal data first.
assertTrue(mWifiConfigManager.loadFromStore());
- when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)))
- .thenReturn(new WifiConfigStoreData(
- new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(),
- new HashSet<String>()));
-
+ setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
// user2 is unlocked and switched to foreground.
when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true);
mWifiConfigManager.handleUserSwitch(user2);
@@ -2155,11 +2142,7 @@ public class WifiConfigManagerTest {
mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class));
- when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)))
- .thenReturn(new WifiConfigStoreData(
- new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(),
- new HashSet<String>()));
-
+ setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
// Unlock the user2 and ensure that we read the data now.
mWifiConfigManager.handleUserUnlock(user2);
mContextConfigStoreMockOrder.verify(mWifiConfigStore)
@@ -2186,8 +2169,7 @@ public class WifiConfigManagerTest {
mWifiConfigManager.handleUserStop(user1);
mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class));
- mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(
- anyBoolean(), any(WifiConfigStoreData.class));
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(anyBoolean());
}
/**
@@ -2201,23 +2183,17 @@ public class WifiConfigManagerTest {
// Set up the internal data first.
assertTrue(mWifiConfigManager.loadFromStore());
mContextConfigStoreMockOrder.verify(mWifiConfigStore).read();
- mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
- .write(anyBoolean(), any(WifiConfigStoreData.class));
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class));
- when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)))
- .thenReturn(new WifiConfigStoreData(
- new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(),
- new HashSet<String>()));
-
+ setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
// Unlock the user1 (default user) for the first time and ensure that we read the data.
mWifiConfigManager.handleUserUnlock(user1);
mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read();
mContextConfigStoreMockOrder.verify(mWifiConfigStore)
.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class));
- mContextConfigStoreMockOrder.verify(mWifiConfigStore)
- .write(anyBoolean(), any(WifiConfigStoreData.class));
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(anyBoolean());
}
/**
@@ -2233,23 +2209,17 @@ public class WifiConfigManagerTest {
// data.
mWifiConfigManager.handleUserUnlock(user1);
mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).read();
- mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
- .write(anyBoolean(), any(WifiConfigStoreData.class));
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class));
- when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)))
- .thenReturn(new WifiConfigStoreData(
- new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(),
- new HashSet<String>()));
-
+ setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
// Read from store now.
assertTrue(mWifiConfigManager.loadFromStore());
mContextConfigStoreMockOrder.verify(mWifiConfigStore).read();
mContextConfigStoreMockOrder.verify(mWifiConfigStore)
.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class));
- mContextConfigStoreMockOrder.verify(mWifiConfigStore)
- .write(anyBoolean(), any(WifiConfigStoreData.class));
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(anyBoolean());
}
/**
@@ -2265,11 +2235,7 @@ public class WifiConfigManagerTest {
// Set up the internal data first.
assertTrue(mWifiConfigManager.loadFromStore());
- when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)))
- .thenReturn(new WifiConfigStoreData(
- new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(),
- new HashSet<String>()));
-
+ setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
// user2 is unlocked and switched to foreground.
when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true);
mWifiConfigManager.handleUserSwitch(user2);
@@ -2297,8 +2263,7 @@ public class WifiConfigManagerTest {
mWifiConfigManager.handleUserSwitch(user2);
mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class));
- mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
- .write(anyBoolean(), any(WifiConfigStoreData.class));
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
}
/**
@@ -2314,8 +2279,7 @@ public class WifiConfigManagerTest {
mWifiConfigManager.handleUserUnlock(user1);
mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class));
- mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
- .write(anyBoolean(), any(WifiConfigStoreData.class));
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
}
/**
@@ -2439,10 +2403,7 @@ public class WifiConfigManagerTest {
verify(mWifiConfigStore, never()).read();
verify(mWifiConfigStoreLegacy, never()).read();
- when(mWifiConfigStore.switchUserStoreAndRead(any(WifiConfigStore.StoreFile.class)))
- .thenReturn(new WifiConfigStoreData(
- new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(),
- new HashSet<String>()));
+ setupStoreDataForUserRead(new ArrayList<WifiConfiguration>(), new HashSet<String>());
// Now switch the user to user 2.
when(mUserManager.isUserUnlockingOrUnlocked(user2)).thenReturn(true);
mWifiConfigManager.handleUserSwitch(user2);
@@ -2563,8 +2524,7 @@ public class WifiConfigManagerTest {
// This should have triggered 2 buffered writes. 1 for setting the connect choice, 1 for
// clearing it after network removal.
- mContextConfigStoreMockOrder.verify(mWifiConfigStore, times(2))
- .write(eq(false), any(WifiConfigStoreData.class));
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, times(2)).write(eq(false));
}
/**
@@ -3147,7 +3107,8 @@ public class WifiConfigManagerTest {
new WifiConfigManager(
mContext, mFrameworkFacade, mClock, mUserManager, mTelephonyManager,
mWifiKeyStore, mWifiConfigStore, mWifiConfigStoreLegacy,
- mWifiPermissionsWrapper);
+ mWifiPermissionsWrapper, mNetworkListStoreData,
+ mDeletedEphemeralSsidsStoreData);
mWifiConfigManager.enableVerboseLogging(1);
}
@@ -3270,15 +3231,22 @@ public class WifiConfigManagerTest {
}
/**
- * Helper method to capture the store data written in WifiConfigStore.write() method.
+ * Helper method to capture the networks list store data that will be written by
+ * WifiConfigStore.write() method.
*/
- private WifiConfigStoreData captureWriteStoreData() {
+ private Pair<List<WifiConfiguration>, List<WifiConfiguration>>
+ captureWriteNetworksListStoreData() {
try {
- ArgumentCaptor<WifiConfigStoreData> storeDataCaptor =
- ArgumentCaptor.forClass(WifiConfigStoreData.class);
- mContextConfigStoreMockOrder.verify(mWifiConfigStore)
- .write(anyBoolean(), storeDataCaptor.capture());
- return storeDataCaptor.getValue();
+ ArgumentCaptor<ArrayList> sharedConfigsCaptor =
+ ArgumentCaptor.forClass(ArrayList.class);
+ ArgumentCaptor<ArrayList> userConfigsCaptor =
+ ArgumentCaptor.forClass(ArrayList.class);
+ mNetworkListStoreDataMockOrder.verify(mNetworkListStoreData)
+ .setSharedConfigurations(sharedConfigsCaptor.capture());
+ mNetworkListStoreDataMockOrder.verify(mNetworkListStoreData)
+ .setUserConfigurations(userConfigsCaptor.capture());
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore).write(anyBoolean());
+ return Pair.create(sharedConfigsCaptor.getValue(), userConfigsCaptor.getValue());
} catch (Exception e) {
fail("Exception encountered during write " + e);
}
@@ -3289,20 +3257,24 @@ public class WifiConfigManagerTest {
* Returns whether the provided network was in the store data or not.
*/
private boolean isNetworkInConfigStoreData(WifiConfiguration configuration) {
- WifiConfigStoreData storeData = captureWriteStoreData();
- if (storeData == null) {
+ Pair<List<WifiConfiguration>, List<WifiConfiguration>> networkListStoreData =
+ captureWriteNetworksListStoreData();
+ if (networkListStoreData == null) {
return false;
}
- return isNetworkInConfigStoreData(configuration, storeData);
+ List<WifiConfiguration> networkList = new ArrayList<>();
+ networkList.addAll(networkListStoreData.first);
+ networkList.addAll(networkListStoreData.second);
+ return isNetworkInConfigStoreData(configuration, networkList);
}
/**
* Returns whether the provided network was in the store data or not.
*/
private boolean isNetworkInConfigStoreData(
- WifiConfiguration configuration, WifiConfigStoreData storeData) {
+ WifiConfiguration configuration, List<WifiConfiguration> networkList) {
boolean foundNetworkInStoreData = false;
- for (WifiConfiguration retrievedConfig : storeData.getConfigurations()) {
+ for (WifiConfiguration retrievedConfig : networkList) {
if (retrievedConfig.configKey().equals(configuration.configKey())) {
foundNetworkInStoreData = true;
break;
@@ -3312,6 +3284,28 @@ public class WifiConfigManagerTest {
}
/**
+ * Setup expectations for WifiNetworksListStoreData and DeletedEphemeralSsidsStoreData
+ * after WifiConfigStore#read.
+ */
+ private void setupStoreDataForRead(List<WifiConfiguration> sharedConfigurations,
+ List<WifiConfiguration> userConfigurations, Set<String> deletedEphemeralSsids) {
+ when(mNetworkListStoreData.getSharedConfigurations())
+ .thenReturn(sharedConfigurations);
+ when(mNetworkListStoreData.getUserConfigurations()).thenReturn(userConfigurations);
+ when(mDeletedEphemeralSsidsStoreData.getSsidList()).thenReturn(deletedEphemeralSsids);
+ }
+
+ /**
+ * Setup expectations for WifiNetworksListStoreData and DeletedEphemeralSsidsStoreData
+ * after WifiConfigStore#switchUserStoreAndRead.
+ */
+ private void setupStoreDataForUserRead(List<WifiConfiguration> userConfigurations,
+ Set<String> deletedEphemeralSsids) {
+ when(mNetworkListStoreData.getUserConfigurations()).thenReturn(userConfigurations);
+ when(mDeletedEphemeralSsidsStoreData.getSsidList()).thenReturn(deletedEphemeralSsids);
+ }
+
+ /**
* Verifies that the provided network was not present in the last config store write.
*/
private void verifyNetworkNotInConfigStoreData(WifiConfiguration configuration) {
@@ -3441,8 +3435,7 @@ public class WifiConfigManagerTest {
verifyNetworkAddBroadcast(configuration);
// Ensure that the write was not invoked for ephemeral network addition.
- mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
- .write(anyBoolean(), any(WifiConfigStoreData.class));
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
return result;
}
@@ -3462,8 +3455,7 @@ public class WifiConfigManagerTest {
any(WifiConfiguration.class));
verifyNetworkAddBroadcast(configuration);
// Ensure that the write was not invoked for Passpoint network addition.
- mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
- .write(anyBoolean(), any(WifiConfigStoreData.class));
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
return result;
}
@@ -3541,8 +3533,7 @@ public class WifiConfigManagerTest {
verifyNetworkRemoveBroadcast(configuration);
// Ensure that the write was not invoked for ephemeral network remove.
- mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
- .write(anyBoolean(), any(WifiConfigStoreData.class));
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
}
/**
@@ -3556,8 +3547,7 @@ public class WifiConfigManagerTest {
verify(mWifiKeyStore, never()).removeKeys(any(WifiEnterpriseConfig.class));
verifyNetworkRemoveBroadcast(configuration);
// Ensure that the write was not invoked for Passpoint network remove.
- mContextConfigStoreMockOrder.verify(mWifiConfigStore, never())
- .write(anyBoolean(), any(WifiConfigStoreData.class));
+ mContextConfigStoreMockOrder.verify(mWifiConfigStore, never()).write(anyBoolean());
}
/**
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreDataTest.java
deleted file mode 100644
index 3fa5d3dab..000000000
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreDataTest.java
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright (C) 2016 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 static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
-
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiEnterpriseConfig;
-import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
-import android.test.suitebuilder.annotation.SmallTest;
-
-import org.junit.Test;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Random;
-import java.util.Set;
-
-/**
- * Unit tests for {@link com.android.server.wifi.WifiConfigStoreData}.
- */
-@SmallTest
-public class WifiConfigStoreDataTest {
-
- private static final String TEST_SSID = "WifiConfigStoreDataSSID_";
- private static final String TEST_CONNECT_CHOICE = "XmlUtilConnectChoice";
- private static final long TEST_CONNECT_CHOICE_TIMESTAMP = 0x4566;
- private static final Set<String> TEST_DELETED_EPHEMERAL_LIST = new HashSet<String>() {
- {
- add("\"" + TEST_SSID + "1\"");
- add("\"" + TEST_SSID + "2\"");
- }
- };
- private static final String SINGLE_OPEN_NETWORK_LIST_XML_STRING_FORMAT =
- "<NetworkList>\n"
- + "<Network>\n"
- + "<WifiConfiguration>\n"
- + "<string name=\"ConfigKey\">%s</string>\n"
- + "<string name=\"SSID\">%s</string>\n"
- + "<null name=\"BSSID\" />\n"
- + "<null name=\"PreSharedKey\" />\n"
- + "<null name=\"WEPKeys\" />\n"
- + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n"
- + "<boolean name=\"HiddenSSID\" value=\"false\" />\n"
- + "<boolean name=\"RequirePMF\" value=\"false\" />\n"
- + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n"
- + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n"
- + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n"
- + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n"
- + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n"
- + "<boolean name=\"Shared\" value=\"%s\" />\n"
- + "<null name=\"FQDN\" />\n"
- + "<null name=\"ProviderFriendlyName\" />\n"
- + "<null name=\"LinkedNetworksList\" />\n"
- + "<null name=\"DefaultGwMacAddress\" />\n"
- + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n"
- + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n"
- + "<int name=\"UserApproved\" value=\"0\" />\n"
- + "<boolean name=\"MeteredHint\" value=\"false\" />\n"
- + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
- + "<int name=\"NumAssociation\" value=\"0\" />\n"
- + "<int name=\"CreatorUid\" value=\"%d\" />\n"
- + "<null name=\"CreatorName\" />\n"
- + "<null name=\"CreationTime\" />\n"
- + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
- + "<null name=\"LastUpdateName\" />\n"
- + "<int name=\"LastConnectUid\" value=\"0\" />\n"
- + "</WifiConfiguration>\n"
- + "<NetworkStatus>\n"
- + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n"
- + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n"
- + "<null name=\"ConnectChoice\" />\n"
- + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n"
- + "<boolean name=\"HasEverConnected\" value=\"false\" />\n"
- + "</NetworkStatus>\n"
- + "<IpConfiguration>\n"
- + "<string name=\"IpAssignment\">DHCP</string>\n"
- + "<string name=\"ProxySettings\">NONE</string>\n"
- + "</IpConfiguration>\n"
- + "</Network>\n"
- + "</NetworkList>\n";
- private static final String SINGLE_OPEN_NETWORK_SHARED_DATA_XML_STRING_FORMAT =
- "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
- + "<WifiConfigStoreData>\n"
- + "<int name=\"Version\" value=\"1\" />\n"
- + SINGLE_OPEN_NETWORK_LIST_XML_STRING_FORMAT
- + "</WifiConfigStoreData>\n";
- private static final String SINGLE_OPEN_NETWORK_USER_DATA_XML_STRING_FORMAT =
- "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
- + "<WifiConfigStoreData>\n"
- + "<int name=\"Version\" value=\"1\" />\n"
- + SINGLE_OPEN_NETWORK_LIST_XML_STRING_FORMAT
- + "<DeletedEphemeralSSIDList>\n"
- + "<set name=\"SSIDList\" />\n"
- + "</DeletedEphemeralSSIDList>\n"
- + "</WifiConfigStoreData>\n";
-
- /**
- * Asserts that the 2 config store data are equal.
- */
- public static void assertConfigStoreDataEqual(
- WifiConfigStoreData expected, WifiConfigStoreData actual) {
- WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore(
- expected.getConfigurations(), actual.getConfigurations());
- assertEquals(expected.getDeletedEphemeralSSIDs(), actual.getDeletedEphemeralSSIDs());
- }
-
- /**
- * Verify that multiple shared networks with different credential types and IpConfiguration
- * types are serialized and deserialized correctly.
- */
- @Test
- public void testMultipleNetworkAllShared()
- throws XmlPullParserException, IOException {
- List<WifiConfiguration> configurations = createNetworks(true);
- serializeDeserializeConfigStoreData(configurations, new ArrayList<WifiConfiguration>());
- }
-
- /**
- * Verify that multiple user networks with different credential types and IpConfiguration
- * types are serialized and deserialized correctly.
- */
- @Test
- public void testMultipleNetworksAllUser()
- throws XmlPullParserException, IOException {
- List<WifiConfiguration> configurations = createNetworks(false);
- serializeDeserializeConfigStoreData(new ArrayList<WifiConfiguration>(), configurations);
- }
-
- /**
- * Verify that multiple networks with different credential types and IpConfiguration
- * types are serialized and deserialized correctly when both user & shared networks are present.
- */
- @Test
- public void testMultipleNetworksSharedAndUserNetworks()
- throws XmlPullParserException, IOException {
- List<WifiConfiguration> configurations = createNetworks();
- // Let's split the list of networks into 2 and make all the networks in the first list
- // shared and the second list all user networks.
- int listSize = configurations.size();
- List<WifiConfiguration> sharedConfigurations = configurations.subList(0, listSize / 2);
- List<WifiConfiguration> userConfigurations = configurations.subList(listSize / 2, listSize);
- for (WifiConfiguration config : sharedConfigurations) {
- config.shared = true;
- }
- for (WifiConfiguration config : userConfigurations) {
- config.shared = false;
- }
- serializeDeserializeConfigStoreData(sharedConfigurations, userConfigurations);
- }
-
- /**
- * Verify that multiple shared networks with different credential types and IpConfiguration
- * types are serialized and deserialized correctly when the shared data bytes are null in
- * |parseRawData| method.
- */
- @Test
- public void testMultipleNetworksSharedDataNullInParseRawData()
- throws XmlPullParserException, IOException {
- List<WifiConfiguration> configurations = createNetworks(false);
- serializeDeserializeConfigStoreData(
- new ArrayList<WifiConfiguration>(), configurations, true, false);
- }
-
- /**
- * Verify that multiple shared networks with different credential types and IpConfiguration
- * types are serialized and deserialized correctly when the user data bytes are null in
- * |parseRawData| method.
- */
- @Test
- public void testMultipleNetworksUserDataNullInParseRawData()
- throws XmlPullParserException, IOException {
- List<WifiConfiguration> configurations = createNetworks(true);
- serializeDeserializeConfigStoreData(
- configurations, new ArrayList<WifiConfiguration>(), false, true);
- }
-
- /**
- * Verify that a network with invalid entepriseConfig data is serialized/deserialized
- * correctly.
- */
- @Test
- public void testInvalidEnterpriseConfig()
- throws XmlPullParserException, IOException {
- WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork();
- eapNetwork.enterpriseConfig = new WifiEnterpriseConfig();
- List<WifiConfiguration> configurations = Arrays.asList(eapNetwork);
- serializeDeserializeConfigStoreData(
- new ArrayList<WifiConfiguration>(), configurations, false, false);
- }
-
- /**
- * Verify that the manually populated xml string for is deserialized/serialized correctly.
- * This generates a store data corresponding to the XML string and verifies that the string
- * is indeed parsed correctly to the store data.
- */
- @Test
- public void testManualConfigStoreDataParse() {
- WifiConfiguration sharedNetwork = WifiConfigurationTestUtil.createOpenNetwork();
- sharedNetwork.shared = true;
- sharedNetwork.setIpConfiguration(WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
- WifiConfiguration userNetwork = WifiConfigurationTestUtil.createOpenNetwork();
- userNetwork.setIpConfiguration(WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
- userNetwork.shared = false;
-
- // Create the store data for comparison.
- List<WifiConfiguration> sharedNetworks = new ArrayList<>();
- List<WifiConfiguration> userNetworks = new ArrayList<>();
- sharedNetworks.add(sharedNetwork);
- userNetworks.add(userNetwork);
- WifiConfigStoreData storeData =
- new WifiConfigStoreData(sharedNetworks, userNetworks, new HashSet<String>());
-
- String sharedStoreXmlString =
- String.format(SINGLE_OPEN_NETWORK_SHARED_DATA_XML_STRING_FORMAT,
- sharedNetwork.configKey().replaceAll("\"", "&quot;"),
- sharedNetwork.SSID.replaceAll("\"", "&quot;"),
- sharedNetwork.shared, sharedNetwork.creatorUid);
- String userStoreXmlString =
- String.format(SINGLE_OPEN_NETWORK_USER_DATA_XML_STRING_FORMAT,
- userNetwork.configKey().replaceAll("\"", "&quot;"),
- userNetwork.SSID.replaceAll("\"", "&quot;"),
- userNetwork.shared, userNetwork.creatorUid);
- byte[] rawSharedData = sharedStoreXmlString.getBytes();
- byte[] rawUserData = userStoreXmlString.getBytes();
- WifiConfigStoreData retrievedStoreData = null;
- try {
- retrievedStoreData = WifiConfigStoreData.parseRawData(rawSharedData, rawUserData);
- } catch (Exception e) {
- // Assert if an exception was raised.
- fail("Error in parsing the xml data: " + e
- + ". Shared data: " + sharedStoreXmlString
- + ", User data: " + userStoreXmlString);
- }
- // Compare the retrieved config store data with the original.
- assertConfigStoreDataEqual(storeData, retrievedStoreData);
-
- // Now convert the store data to XML bytes and compare the output with the expected string.
- byte[] retrievedSharedStoreXmlBytes = null;
- byte[] retrievedUserStoreXmlBytes = null;
- try {
- retrievedSharedStoreXmlBytes = retrievedStoreData.createSharedRawData();
- retrievedUserStoreXmlBytes = retrievedStoreData.createUserRawData();
- } catch (Exception e) {
- // Assert if an exception was raised.
- fail("Error in writing the xml data: " + e);
- }
- String retrievedSharedStoreXmlString =
- new String(retrievedSharedStoreXmlBytes, StandardCharsets.UTF_8);
- String retrievedUserStoreXmlString =
- new String(retrievedUserStoreXmlBytes, StandardCharsets.UTF_8);
- assertEquals("Retrieved: " + retrievedSharedStoreXmlString
- + ", Expected: " + sharedStoreXmlString,
- sharedStoreXmlString, retrievedSharedStoreXmlString);
- assertEquals("Retrieved: " + retrievedUserStoreXmlString
- + ", Expected: " + userStoreXmlString,
- userStoreXmlString, retrievedUserStoreXmlString);
- }
-
- /**
- * Verify that XML with corrupted version provided to WifiConfigStoreData is ignored correctly.
- */
- @Test
- public void testCorruptVersionConfigStoreData() {
- String storeDataAsString =
- "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
- + "<WifiConfigStoreData>\n"
- + "<int name=\"Version\" value=\"200\" />\n"
- + "</WifiConfigStoreData>\n";
- byte[] rawData = storeDataAsString.getBytes();
- try {
- WifiConfigStoreData storeData = WifiConfigStoreData.parseRawData(rawData, rawData);
- } catch (Exception e) {
- return;
- }
- // Assert if there was no exception was raised.
- fail();
- }
-
- /**
- * Verify that XML with no network list provided to WifiConfigStoreData is ignored correctly.
- */
- @Test
- public void testCorruptNetworkListConfigStoreData() {
- String storeDataAsString =
- "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
- + "<WifiConfigStoreData>\n"
- + "<int name=\"Version\" value=\"1\" />\n"
- + "</WifiConfigStoreData>\n";
- byte[] rawData = storeDataAsString.getBytes();
- try {
- WifiConfigStoreData storeData = WifiConfigStoreData.parseRawData(rawData, rawData);
- } catch (Exception e) {
- return;
- }
- // Assert if there was no exception was raised.
- fail();
- }
-
- /**
- * Verify that any corrupted data provided to WifiConfigStoreData is ignored correctly.
- */
- @Test
- public void testRandomCorruptConfigStoreData() {
- Random random = new Random();
- byte[] rawData = new byte[100];
- random.nextBytes(rawData);
- try {
- WifiConfigStoreData storeData = WifiConfigStoreData.parseRawData(rawData, rawData);
- } catch (Exception e) {
- return;
- }
- // Assert if there was no exception was raised.
- fail();
- }
-
- /**
- * Helper method to add 4 networks with different credential types, IpConfiguration
- * types for all tests in the class.
- *
- * @return
- */
- private List<WifiConfiguration> createNetworks() {
- List<WifiConfiguration> configurations = new ArrayList<>();
-
- WifiConfiguration wepNetwork = WifiConfigurationTestUtil.createWepNetwork();
- wepNetwork.setIpConfiguration(WifiConfigurationTestUtil.createDHCPIpConfigurationWithPacProxy());
- wepNetwork.getNetworkSelectionStatus().setNetworkSelectionStatus(
- NetworkSelectionStatus.NETWORK_SELECTION_ENABLED);
- configurations.add(wepNetwork);
-
- WifiConfiguration pskNetwork = WifiConfigurationTestUtil.createPskNetwork();
- pskNetwork.setIpConfiguration(WifiConfigurationTestUtil.createStaticIpConfigurationWithPacProxy());
- pskNetwork.getNetworkSelectionStatus().setNetworkSelectionStatus(
- NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
- pskNetwork.getNetworkSelectionStatus().setNetworkSelectionDisableReason(
- NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION);
- configurations.add(pskNetwork);
-
- WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
- openNetwork.setIpConfiguration(WifiConfigurationTestUtil.createStaticIpConfigurationWithStaticProxy());
- openNetwork.getNetworkSelectionStatus().setNetworkSelectionStatus(
- NetworkSelectionStatus.NETWORK_SELECTION_PERMANENTLY_DISABLED);
- openNetwork.getNetworkSelectionStatus().setNetworkSelectionDisableReason(
- NetworkSelectionStatus.DISABLED_BY_WIFI_MANAGER);
- configurations.add(openNetwork);
-
- WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork();
- eapNetwork.setIpConfiguration(WifiConfigurationTestUtil.createPartialStaticIpConfigurationWithPacProxy());
- eapNetwork.getNetworkSelectionStatus().setConnectChoice(TEST_CONNECT_CHOICE);
- eapNetwork.getNetworkSelectionStatus().setConnectChoiceTimestamp(
- TEST_CONNECT_CHOICE_TIMESTAMP);
- eapNetwork.getNetworkSelectionStatus().setHasEverConnected(true);
- configurations.add(eapNetwork);
-
- return configurations;
- }
-
- private List<WifiConfiguration> createNetworks(boolean shared) {
- List<WifiConfiguration> configurations = createNetworks();
- for (WifiConfiguration config : configurations) {
- config.shared = shared;
- }
- return configurations;
- }
-
- /**
- * Helper method to serialize/deserialize store data.
- */
- private void serializeDeserializeConfigStoreData(
- List<WifiConfiguration> sharedConfigurations,
- List<WifiConfiguration> userConfigurations)
- throws XmlPullParserException, IOException {
- serializeDeserializeConfigStoreData(sharedConfigurations, userConfigurations, false, false);
- }
-
- /**
- * Helper method to ensure the the provided config store data is serialized/deserialized
- * correctly.
- * This method serialize the provided config store data instance to raw bytes in XML format
- * and then deserialzes the raw bytes back to a config store data instance. It then
- * compares that the original config store data matches with the deserialzed instance.
- *
- * @param sharedConfigurations list of configurations to be added in the shared store data instance.
- * @param userConfigurations list of configurations to be added in the user store data instance.
- * @param setSharedDataNull whether to set the shared data to null to simulate the non-existence
- * of the shared store file.
- * @param setUserDataNull whether to set the user data to null to simulate the non-existence
- * of the user store file.
- */
- private void serializeDeserializeConfigStoreData(
- List<WifiConfiguration> sharedConfigurations,
- List<WifiConfiguration> userConfigurations,
- boolean setSharedDataNull, boolean setUserDataNull)
- throws XmlPullParserException, IOException {
- // Will not work if both the flags are set because then we need to ignore the configuration
- // list as well.
- assertFalse(setSharedDataNull & setUserDataNull);
-
- Set<String> deletedEphemeralList;
- if (setUserDataNull) {
- deletedEphemeralList = new HashSet<>();
- } else {
- deletedEphemeralList = TEST_DELETED_EPHEMERAL_LIST;
- }
-
- // Serialize the data.
- WifiConfigStoreData storeData =
- new WifiConfigStoreData(
- sharedConfigurations, userConfigurations, deletedEphemeralList);
-
- byte[] sharedDataBytes = null;
- byte[] userDataBytes = null;
- if (!setSharedDataNull) {
- sharedDataBytes = storeData.createSharedRawData();
- }
- if (!setUserDataNull) {
- userDataBytes = storeData.createUserRawData();
- }
-
- // Deserialize the data.
- WifiConfigStoreData retrievedStoreData =
- WifiConfigStoreData.parseRawData(sharedDataBytes, userDataBytes);
- assertConfigStoreDataEqual(storeData, retrievedStoreData);
- }
-}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
index f567ef6d5..b7e642c91 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
@@ -16,8 +16,6 @@
package com.android.server.wifi;
-import static com.android.server.wifi.WifiConfigStoreDataTest.assertConfigStoreDataEqual;
-
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
@@ -28,23 +26,99 @@ import android.os.test.TestLooper;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.server.wifi.WifiConfigStore.StoreFile;
+import com.android.server.wifi.util.XmlUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* Unit tests for {@link com.android.server.wifi.WifiConfigStore}.
*/
@SmallTest
public class WifiConfigStoreTest {
+ // Store file content without any data.
+ private static final String EMPTY_FILE_CONTENT =
+ "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<WifiConfigStoreData>\n"
+ + "<int name=\"Version\" value=\"1\" />\n"
+ + "</WifiConfigStoreData>\n";
+
+ private static final String TEST_USER_DATA = "UserData";
+ private static final String TEST_SHARE_DATA = "ShareData";
+
+ private static final String TEST_DATA_XML_STRING_FORMAT =
+ "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<WifiConfigStoreData>\n"
+ + "<int name=\"Version\" value=\"1\" />\n"
+ + "<NetworkList>\n"
+ + "<Network>\n"
+ + "<WifiConfiguration>\n"
+ + "<string name=\"ConfigKey\">%s</string>\n"
+ + "<string name=\"SSID\">%s</string>\n"
+ + "<null name=\"BSSID\" />\n"
+ + "<null name=\"PreSharedKey\" />\n"
+ + "<null name=\"WEPKeys\" />\n"
+ + "<int name=\"WEPTxKeyIndex\" value=\"0\" />\n"
+ + "<boolean name=\"HiddenSSID\" value=\"false\" />\n"
+ + "<boolean name=\"RequirePMF\" value=\"false\" />\n"
+ + "<byte-array name=\"AllowedKeyMgmt\" num=\"1\">01</byte-array>\n"
+ + "<byte-array name=\"AllowedProtocols\" num=\"0\"></byte-array>\n"
+ + "<byte-array name=\"AllowedAuthAlgos\" num=\"0\"></byte-array>\n"
+ + "<byte-array name=\"AllowedGroupCiphers\" num=\"0\"></byte-array>\n"
+ + "<byte-array name=\"AllowedPairwiseCiphers\" num=\"0\"></byte-array>\n"
+ + "<boolean name=\"Shared\" value=\"%s\" />\n"
+ + "<null name=\"FQDN\" />\n"
+ + "<null name=\"ProviderFriendlyName\" />\n"
+ + "<null name=\"LinkedNetworksList\" />\n"
+ + "<null name=\"DefaultGwMacAddress\" />\n"
+ + "<boolean name=\"ValidatedInternetAccess\" value=\"false\" />\n"
+ + "<boolean name=\"NoInternetAccessExpected\" value=\"false\" />\n"
+ + "<int name=\"UserApproved\" value=\"0\" />\n"
+ + "<boolean name=\"MeteredHint\" value=\"false\" />\n"
+ + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
+ + "<int name=\"NumAssociation\" value=\"0\" />\n"
+ + "<int name=\"CreatorUid\" value=\"%d\" />\n"
+ + "<null name=\"CreatorName\" />\n"
+ + "<null name=\"CreationTime\" />\n"
+ + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
+ + "<null name=\"LastUpdateName\" />\n"
+ + "<int name=\"LastConnectUid\" value=\"0\" />\n"
+ + "</WifiConfiguration>\n"
+ + "<NetworkStatus>\n"
+ + "<string name=\"SelectionStatus\">NETWORK_SELECTION_ENABLED</string>\n"
+ + "<string name=\"DisableReason\">NETWORK_SELECTION_ENABLE</string>\n"
+ + "<null name=\"ConnectChoice\" />\n"
+ + "<long name=\"ConnectChoiceTimeStamp\" value=\"-1\" />\n"
+ + "<boolean name=\"HasEverConnected\" value=\"false\" />\n"
+ + "</NetworkStatus>\n"
+ + "<IpConfiguration>\n"
+ + "<string name=\"IpAssignment\">DHCP</string>\n"
+ + "<string name=\"ProxySettings\">NONE</string>\n"
+ + "</IpConfiguration>\n"
+ + "</Network>\n"
+ + "</NetworkList>\n"
+ + "<DeletedEphemeralSSIDList>\n"
+ + "<set name=\"SSIDList\">\n"
+ + "<string>%s</string>\n"
+ + "</set>\n"
+ + "</DeletedEphemeralSSIDList>\n"
+ + "</WifiConfigStoreData>\n";
+
// Test mocks
@Mock private Context mContext;
private TestAlarmManager mAlarmManager;
@@ -52,6 +126,7 @@ public class WifiConfigStoreTest {
@Mock private Clock mClock;
private MockStoreFile mSharedStore;
private MockStoreFile mUserStore;
+ private MockStoreData mStoreData;
/**
* Test instance of WifiConfigStore.
@@ -69,6 +144,7 @@ public class WifiConfigStoreTest {
.thenReturn(mAlarmManager.getAlarmManager());
mUserStore = new MockStoreFile();
mSharedStore = new MockStoreFile();
+ mStoreData = new MockStoreData();
}
/**
@@ -79,7 +155,6 @@ public class WifiConfigStoreTest {
setupMocks();
mWifiConfigStore = new WifiConfigStore(mContext, mLooper.getLooper(), mClock, mSharedStore);
-
// Enable verbose logging before tests.
mWifiConfigStore.enableVerboseLogging(true);
}
@@ -93,6 +168,27 @@ public class WifiConfigStoreTest {
}
/**
+ * Verify the contents of the config file with empty data. The data content should be the
+ * same as {@link #EMPTY_FILE_CONTENT}.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testWriteWithEmptyData() throws Exception {
+ // Perform force write to both share and user store file.
+ mWifiConfigStore.switchUserStoreAndRead(mUserStore);
+ mWifiConfigStore.write(true);
+
+ assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
+ assertTrue(mSharedStore.isStoreWritten());
+ assertTrue(mUserStore.isStoreWritten());
+ assertTrue(Arrays.equals(EMPTY_FILE_CONTENT.getBytes(StandardCharsets.UTF_8),
+ mSharedStore.getStoreBytes()));
+ assertTrue(Arrays.equals(EMPTY_FILE_CONTENT.getBytes(StandardCharsets.UTF_8),
+ mUserStore.getStoreBytes()));
+ }
+
+ /**
* Tests the write API with the force flag set to true.
* Expected behavior: This should trigger an immediate write to the store files and no alarms
* should be started.
@@ -100,7 +196,7 @@ public class WifiConfigStoreTest {
@Test
public void testForceWrite() throws Exception {
mWifiConfigStore.switchUserStoreAndRead(mUserStore);
- mWifiConfigStore.write(true, getEmptyStoreData());
+ mWifiConfigStore.write(true);
assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
assertTrue(mSharedStore.isStoreWritten());
@@ -114,7 +210,7 @@ public class WifiConfigStoreTest {
@Test
public void testBufferedWrite() throws Exception {
mWifiConfigStore.switchUserStoreAndRead(mUserStore);
- mWifiConfigStore.write(false, getEmptyStoreData());
+ mWifiConfigStore.write(false);
assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
assertFalse(mSharedStore.isStoreWritten());
@@ -134,30 +230,33 @@ public class WifiConfigStoreTest {
*/
@Test
public void testForceWriteAfterBufferedWrite() throws Exception {
- WifiConfigStoreData bufferedStoreData = createSingleOpenNetworkStoreData();
+ // Register a test data container with bogus data.
+ mWifiConfigStore.registerStoreData(mStoreData);
+ mStoreData.setShareData("abcds");
+ mStoreData.setUserData("asdfa");
+
+ // Perform buffered write for both user and share store file.
mWifiConfigStore.switchUserStoreAndRead(mUserStore);
- mWifiConfigStore.write(false, bufferedStoreData);
+ mWifiConfigStore.write(false);
assertTrue(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
assertFalse(mSharedStore.isStoreWritten());
assertFalse(mUserStore.isStoreWritten());
- // Now send a force write and ensure that the writes have been performed and alarms have
- // been stopped.
- WifiConfigStoreData forcedStoreData = createSinglePskNetworkStoreData();
- mWifiConfigStore.write(true, forcedStoreData);
+ // Update the container with new set of data. The send a force write and ensure that the
+ // writes have been performed and alarms have been stopped and updated data are written.
+ mStoreData.setUserData(TEST_USER_DATA);
+ mStoreData.setShareData(TEST_SHARE_DATA);
+ mWifiConfigStore.write(true);
assertFalse(mAlarmManager.isPending(WifiConfigStore.BUFFERED_WRITE_ALARM_TAG));
assertTrue(mSharedStore.isStoreWritten());
assertTrue(mUserStore.isStoreWritten());
- // Now deserialize the data and ensure that the configuration retrieved matches the force
- // write data.
- WifiConfigStoreData retrievedStoreData =
- WifiConfigStoreData.parseRawData(
- mSharedStore.getStoreBytes(), mUserStore.getStoreBytes());
-
- assertConfigStoreDataEqual(forcedStoreData, retrievedStoreData);
+ // Verify correct data are loaded to the data container after a read.
+ mWifiConfigStore.read();
+ assertEquals(TEST_USER_DATA, mStoreData.getUserData());
+ assertEquals(TEST_SHARE_DATA, mStoreData.getShareData());
}
/**
@@ -166,12 +265,25 @@ public class WifiConfigStoreTest {
*/
@Test
public void testReadAfterWrite() throws Exception {
- WifiConfigStoreData writeData = createSingleOpenNetworkStoreData();
+ // Register data container.
+ mWifiConfigStore.registerStoreData(mStoreData);
+
+ // Read both share and user config store.
mWifiConfigStore.switchUserStoreAndRead(mUserStore);
- mWifiConfigStore.write(true, writeData);
- WifiConfigStoreData readData = mWifiConfigStore.read();
- assertConfigStoreDataEqual(writeData, readData);
+ // Verify no data is read.
+ assertNull(mStoreData.getUserData());
+ assertNull(mStoreData.getShareData());
+
+ // Write share and user data.
+ mStoreData.setUserData(TEST_USER_DATA);
+ mStoreData.setShareData(TEST_SHARE_DATA);
+ mWifiConfigStore.write(true);
+
+ // Read and verify the data content in the data container.
+ mWifiConfigStore.read();
+ assertEquals(TEST_USER_DATA, mStoreData.getUserData());
+ assertEquals(TEST_SHARE_DATA, mStoreData.getShareData());
}
/**
@@ -183,9 +295,13 @@ public class WifiConfigStoreTest {
public void testReadWithNoStoreFile() throws Exception {
// Reading the mock store without a write should simulate the file not found case because
// |readRawData| would return null.
+ mWifiConfigStore.registerStoreData(mStoreData);
assertFalse(mWifiConfigStore.areStoresPresent());
- WifiConfigStoreData readData = mWifiConfigStore.read();
- assertConfigStoreDataEqual(getEmptyStoreData(), readData);
+ mWifiConfigStore.read();
+
+ // Empty data.
+ assertNull(mStoreData.getUserData());
+ assertNull(mStoreData.getShareData());
}
/**
@@ -195,40 +311,164 @@ public class WifiConfigStoreTest {
*/
@Test
public void testReadAfterWriteWithNoUserStore() throws Exception {
- WifiConfigStoreData writeData = createSingleOpenNetworkStoreData();
- mWifiConfigStore.write(true, writeData);
- WifiConfigStoreData readData = mWifiConfigStore.read();
+ // Setup data container.
+ mWifiConfigStore.registerStoreData(mStoreData);
+ mStoreData.setUserData(TEST_USER_DATA);
+ mStoreData.setShareData(TEST_SHARE_DATA);
+
+ // Perform write for the share store file.
+ mWifiConfigStore.write(true);
+ mWifiConfigStore.read();
+ // Verify data content for both user and share data.
+ assertEquals(TEST_SHARE_DATA, mStoreData.getShareData());
+ assertNull(mStoreData.getUserData());
+ }
+
+ /**
+ * Verifies that a read operation will reset the data in the data container, to avoid
+ * any stale data from previous read.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testReadWillResetStoreData() throws Exception {
+ // Register and setup store data.
+ mWifiConfigStore.registerStoreData(mStoreData);
+
+ // Perform force write with empty data content to both user and share store file.
+ mWifiConfigStore.switchUserStoreAndRead(mUserStore);
+ mWifiConfigStore.write(true);
- assertConfigStoreDataEqual(writeData, readData);
+ // Setup data container with some value.
+ mStoreData.setUserData(TEST_USER_DATA);
+ mStoreData.setShareData(TEST_SHARE_DATA);
+
+ // Perform read of both user and share store file and verify data in the data container
+ // is in sync (empty) with what is in the file.
+ mWifiConfigStore.read();
+ assertNull(mStoreData.getShareData());
+ assertNull(mStoreData.getUserData());
+ }
+
+ /**
+ * Verify that a store file contained WiFi configuration store data (network list and
+ * deleted ephemeral SSID list) using the predefined test XML data is read and parsed
+ * correctly.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testReadWifiConfigStoreData() throws Exception {
+ // Setup network list.
+ NetworkListStoreData networkList = new NetworkListStoreData();
+ mWifiConfigStore.registerStoreData(networkList);
+ WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+ openNetwork.setIpConfiguration(
+ WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
+ List<WifiConfiguration> userConfigs = new ArrayList<>();
+ userConfigs.add(openNetwork);
+
+ // Setup deleted ephemeral SSID list.
+ DeletedEphemeralSsidsStoreData deletedEphemeralSsids =
+ new DeletedEphemeralSsidsStoreData();
+ mWifiConfigStore.registerStoreData(deletedEphemeralSsids);
+ String testSsid = "Test SSID";
+ Set<String> ssidList = new HashSet<>();
+ ssidList.add(testSsid);
+
+ // Setup user store XML bytes.
+ String xmlString = String.format(TEST_DATA_XML_STRING_FORMAT,
+ openNetwork.configKey().replaceAll("\"", "&quot;"),
+ openNetwork.SSID.replaceAll("\"", "&quot;"),
+ openNetwork.shared, openNetwork.creatorUid, testSsid);
+ byte[] xmlBytes = xmlString.getBytes(StandardCharsets.UTF_8);
+ mUserStore.storeRawDataToWrite(xmlBytes);
+
+ mWifiConfigStore.switchUserStoreAndRead(mUserStore);
+ WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore(
+ userConfigs, networkList.getUserConfigurations());
+ assertEquals(ssidList, deletedEphemeralSsids.getSsidList());
}
/**
- * Returns an empty store data object.
+ * Verify that the WiFi configuration store data containing network list and deleted
+ * ephemeral SSID list are serialized correctly, matches the predefined test XML data.
+ *
+ * @throws Exception
*/
- private WifiConfigStoreData getEmptyStoreData() {
- return new WifiConfigStoreData(
- new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(),
- new HashSet<String>());
+ @Test
+ public void testWriteWifiConfigStoreData() throws Exception {
+ // Setup user store.
+ mWifiConfigStore.switchUserStoreAndRead(mUserStore);
+
+ // Setup network list store data.
+ NetworkListStoreData networkList = new NetworkListStoreData();
+ mWifiConfigStore.registerStoreData(networkList);
+ WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+ openNetwork.setIpConfiguration(
+ WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
+ List<WifiConfiguration> userConfigs = new ArrayList<>();
+ userConfigs.add(openNetwork);
+ networkList.setUserConfigurations(userConfigs);
+
+ // Setup deleted ephemeral SSID list store data.
+ DeletedEphemeralSsidsStoreData deletedEphemeralSsids =
+ new DeletedEphemeralSsidsStoreData();
+ mWifiConfigStore.registerStoreData(deletedEphemeralSsids);
+ String testSsid = "Test SSID";
+ Set<String> ssidList = new HashSet<>();
+ ssidList.add(testSsid);
+ deletedEphemeralSsids.setSsidList(ssidList);
+
+ // Setup expected XML bytes.
+ String xmlString = String.format(TEST_DATA_XML_STRING_FORMAT,
+ openNetwork.configKey().replaceAll("\"", "&quot;"),
+ openNetwork.SSID.replaceAll("\"", "&quot;"),
+ openNetwork.shared, openNetwork.creatorUid, testSsid);
+ byte[] xmlBytes = xmlString.getBytes(StandardCharsets.UTF_8);
+
+ mWifiConfigStore.write(true);
+ assertEquals(xmlBytes.length, mUserStore.getStoreBytes().length);
+ // Verify the user store content.
+ assertTrue(Arrays.equals(xmlBytes, mUserStore.getStoreBytes()));
}
/**
- * Returns an store data object with a single open network.
+ * Verify that a XmlPullParserException will be thrown when reading an user store file
+ * containing unknown data.
+ *
+ * @throws Exception
*/
- private WifiConfigStoreData createSingleOpenNetworkStoreData() {
- List<WifiConfiguration> configurations = new ArrayList<>();
- configurations.add(WifiConfigurationTestUtil.createOpenNetwork());
- return new WifiConfigStoreData(
- configurations, new ArrayList<WifiConfiguration>(), new HashSet<String>());
+ @Test(expected = XmlPullParserException.class)
+ public void testReadUserStoreContainedUnknownData() throws Exception {
+ String storeFileData =
+ "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<WifiConfigStoreData>\n"
+ + "<int name=\"Version\" value=\"1\" />\n"
+ + "<UnknownTag>\n" // No StoreData registered to handle this tag.
+ + "</UnknownTag>\n"
+ + "</WifiConfigStoreData>\n";
+ mUserStore.storeRawDataToWrite(storeFileData.getBytes(StandardCharsets.UTF_8));
+ mWifiConfigStore.switchUserStoreAndRead(mUserStore);
}
/**
- * Returns an store data object with a single psk network.
+ * Verify that a XmlPullParserException will be thrown when reading the share store file
+ * containing unknown data.
+ *
+ * @throws Exception
*/
- private WifiConfigStoreData createSinglePskNetworkStoreData() {
- List<WifiConfiguration> configurations = new ArrayList<>();
- configurations.add(WifiConfigurationTestUtil.createPskNetwork());
- return new WifiConfigStoreData(
- configurations, new ArrayList<WifiConfiguration>(), new HashSet<String>());
+ @Test(expected = XmlPullParserException.class)
+ public void testReadShareStoreContainedUnknownData() throws Exception {
+ String storeFileData =
+ "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<WifiConfigStoreData>\n"
+ + "<int name=\"Version\" value=\"1\" />\n"
+ + "<UnknownTag>\n" // No StoreData registered to handle this tag.
+ + "</UnknownTag>\n"
+ + "</WifiConfigStoreData>\n";
+ mSharedStore.storeRawDataToWrite(storeFileData.getBytes(StandardCharsets.UTF_8));
+ mWifiConfigStore.read();
}
/**
@@ -259,6 +499,7 @@ public class WifiConfigStoreTest {
return (mStoreBytes != null);
}
+ @Override
public void writeBufferedRawData() {
mStoreWritten = true;
}
@@ -271,4 +512,72 @@ public class WifiConfigStoreTest {
return mStoreWritten;
}
}
+
+ /**
+ * Mock data container for providing test data for the store file.
+ */
+ private class MockStoreData implements WifiConfigStore.StoreData {
+ private static final String XML_TAG_TEST_HEADER = "TestHeader";
+ private static final String XML_TAG_TEST_DATA = "TestData";
+
+ private String mShareData;
+ private String mUserData;
+
+ MockStoreData() {}
+
+ @Override
+ public void serializeData(XmlSerializer out, boolean shared)
+ throws XmlPullParserException, IOException {
+ if (shared) {
+ XmlUtil.writeNextValue(out, XML_TAG_TEST_DATA, mShareData);
+ } else {
+ XmlUtil.writeNextValue(out, XML_TAG_TEST_DATA, mUserData);
+ }
+ }
+
+ @Override
+ public void deserializeData(XmlPullParser in, int outerTagDepth, boolean shared)
+ throws XmlPullParserException, IOException {
+ if (shared) {
+ mShareData = (String) XmlUtil.readNextValueWithName(in, XML_TAG_TEST_DATA);
+ } else {
+ mUserData = (String) XmlUtil.readNextValueWithName(in, XML_TAG_TEST_DATA);
+ }
+ }
+
+ @Override
+ public void resetData(boolean shared) {
+ if (shared) {
+ mShareData = null;
+ } else {
+ mUserData = null;
+ }
+ }
+
+ @Override
+ public String getName() {
+ return XML_TAG_TEST_HEADER;
+ }
+
+ @Override
+ public boolean supportShareData() {
+ return true;
+ }
+
+ public String getShareData() {
+ return mShareData;
+ }
+
+ public void setShareData(String shareData) {
+ mShareData = shareData;
+ }
+
+ public String getUserData() {
+ return mUserData;
+ }
+
+ public void setUserData(String userData) {
+ mUserData = userData;
+ }
+ }
}