WifiConfigManagerNew: Migration from old store (Part 1)

In the new config store design, none of the other users private
networks should even be in memory because the other user's store files
are not accessible to the current user. However as we load networks
from the old store (all networks were in a single file) and migrate to
the new store, we might have a bunch of private networks from other
users in memory. We cannot write these private networks to the
respective store file until the corresponding user logs in to the
device after upgrade. So, move all such networks to the shared store file.
When the corresponding user logs in, their private networks will be sent
from the shared store file to the specific user store file and
eventually the shared store file will not contain any user private networks.

Changes in the CL:
1. Don't split the configurations to be sent for shared vs user store file inside
|WifiConfigStoreData|. This is now accepted as 2 separate lists in the
constructor.
2. Hide the members of |WifiConfigStoreData| and add getters to retrieve
the necessaty data.
3. |WifiConfigManagerNew| will send all private networks in memory not
visible to the current user along with any shared networks to the
shared store file.
4. Changes to the existing tests to account for #1 & #2 above.

BUG: 29337176
TEST: Ran existing tests. Will add unit tests for the specific scenario in
the next CL.

Change-Id: If0507bdd5df4296cfe94e0ff5492c4f6b354021d
diff --git a/service/java/com/android/server/wifi/WifiConfigManagerNew.java b/service/java/com/android/server/wifi/WifiConfigManagerNew.java
index 2dc77cd..9c073a9 100644
--- a/service/java/com/android/server/wifi/WifiConfigManagerNew.java
+++ b/service/java/com/android/server/wifi/WifiConfigManagerNew.java
@@ -1697,14 +1697,14 @@
         mConfiguredNetworks.clear();
         mDeletedEphemeralSSIDs.clear();
         mScanDetailCaches.clear();
-        for (WifiConfiguration configuration : storeData.configurations) {
+        for (WifiConfiguration configuration : storeData.getConfigurations()) {
             configuration.networkId = mLastNetworkId++;
             if (mVerboseLoggingEnabled) {
                 Log.v(TAG, "Adding network from store " + configuration.configKey());
             }
             mConfiguredNetworks.put(configuration);
         }
-        for (String ssid : storeData.deletedEphemeralSSIDs) {
+        for (String ssid : storeData.getDeletedEphemeralSSIDs()) {
             mDeletedEphemeralSSIDs.add(ssid);
         }
         if (mConfiguredNetworks.sizeForAllUsers() == 0) {
@@ -1719,15 +1719,29 @@
      * @return Whether the write was successful or not, this is applicable only for force writes.
      */
     private boolean saveToStore(boolean forceWrite) {
-        ArrayList<WifiConfiguration> configurations = new ArrayList<>();
-        // Don't persist ephemeral networks to store.
-        for (WifiConfiguration config : mConfiguredNetworks.valuesForCurrentUser()) {
+        ArrayList<WifiConfiguration> sharedConfigurations = new ArrayList<>();
+        ArrayList<WifiConfiguration> userConfigurations = new ArrayList<>();
+        for (WifiConfiguration config : mConfiguredNetworks.valuesForAllUsers()) {
+            // Don't persist ephemeral networks to store.
             if (!config.ephemeral) {
-                configurations.add(config);
+                // We push all shared networks & private networks not belonging to the current
+                // user to the shared store. Ideally, private networks for other users should
+                // not even be in memory,
+                // But, this logic is in place to deal with store migration from N to O
+                // because all networks were previously stored in a central file. We cannot
+                // write these private networks to the user specific store until the corresponding
+                // user logs in.
+                if (config.shared || !WifiConfigurationUtil.isVisibleToAnyProfile(
+                        config, mUserManager.getProfiles(mCurrentUserId))) {
+                    sharedConfigurations.add(config);
+                } else {
+                    userConfigurations.add(config);
+                }
             }
         }
         WifiConfigStoreData storeData =
-                new WifiConfigStoreData(configurations, mDeletedEphemeralSSIDs);
+                new WifiConfigStoreData(
+                        sharedConfigurations, userConfigurations, mDeletedEphemeralSSIDs);
 
         long writeStartTime = mClock.getElapsedSinceBootMillis();
         try {
diff --git a/service/java/com/android/server/wifi/WifiConfigStoreData.java b/service/java/com/android/server/wifi/WifiConfigStoreData.java
index 4d1802f..55b3b52 100644
--- a/service/java/com/android/server/wifi/WifiConfigStoreData.java
+++ b/service/java/com/android/server/wifi/WifiConfigStoreData.java
@@ -80,26 +80,58 @@
     private static final String XML_TAG_SECTION_HEADER_DELETED_EPHEMERAL_SSID_LIST =
             "DeletedEphemeralSSIDList";
     /**
-     * List of saved networks visible to the current user to be stored (includes shared & private).
+     * List of saved shared networks visible to all the users to be stored in the shared store file.
      */
-    public List<WifiConfiguration> configurations;
+    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.
      */
-    public Set<String> deletedEphemeralSSIDs;
+    private final Set<String> mDeletedEphemeralSSIDs;
 
     /**
      * Create a new instance of store data to be written to the store files.
      *
-     * @param configurations        list of saved networks to be stored.
+     * @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> configurations, Set<String> deletedEphemeralSSIDs) {
-        this.configurations = configurations;
-        this.deletedEphemeralSSIDs = deletedEphemeralSSIDs;
+            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.
+     */
+    public List<WifiConfiguration> getConfigurations() {
+        List<WifiConfiguration> configurations = new ArrayList<>();
+        configurations.addAll(mSharedConfigurations);
+        configurations.addAll(mUserConfigurations);
+        return configurations;
+    }
+
+    /**
+     * 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;
     }
 
     /**
@@ -137,11 +169,8 @@
      * Create a WifiConfigStoreData instance from the retrieved UserData & SharedData instance.
      */
     private static WifiConfigStoreData getStoreData(SharedData sharedData, UserData userData) {
-        List<WifiConfiguration> configurations = new ArrayList<>();
-        configurations.addAll(sharedData.configurations);
-        configurations.addAll(userData.configurations);
-        return new WifiConfigStoreData(configurations, userData.deletedEphemeralSSIDs);
-
+        return new WifiConfigStoreData(
+                sharedData.configurations, userData.configurations, userData.deletedEphemeralSSIDs);
     }
 
     /**
@@ -350,13 +379,7 @@
      * @return SharedData instance.
      */
     private SharedData getSharedData() {
-        List<WifiConfiguration> sharedConfigurations = new ArrayList<>();
-        for (WifiConfiguration configuration : configurations) {
-            if (configuration.shared) {
-                sharedConfigurations.add(configuration);
-            }
-        }
-        return new SharedData(sharedConfigurations);
+        return new SharedData(mSharedConfigurations);
     }
 
     /**
@@ -365,13 +388,7 @@
      * @return UserData instance.
      */
     private UserData getUserData() {
-        List<WifiConfiguration> userConfigurations = new ArrayList<>();
-        for (WifiConfiguration configuration : configurations) {
-            if (!configuration.shared) {
-                userConfigurations.add(configuration);
-            }
-        }
-        return new UserData(userConfigurations, deletedEphemeralSSIDs);
+        return new UserData(mUserConfigurations, mDeletedEphemeralSSIDs);
     }
 
     /**
@@ -398,7 +415,7 @@
          * @return new instance of store data.
          */
         public static SharedData parseRawData(byte[] sharedDataBytes)
-                throws XmlPullParserException, IOException{
+                throws XmlPullParserException, IOException {
             final XmlPullParser in = Xml.newPullParser();
             final ByteArrayInputStream inputStream = new ByteArrayInputStream(sharedDataBytes);
             in.setInput(inputStream, StandardCharsets.UTF_8.name());
@@ -419,7 +436,7 @@
          *
          * @return byte array with the serialized output.
          */
-        public byte[] createRawData() throws XmlPullParserException, IOException  {
+        public byte[] createRawData() throws XmlPullParserException, IOException {
             final XmlSerializer out = new FastXmlSerializer();
             final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
             out.setOutput(outputStream, StandardCharsets.UTF_8.name());
@@ -453,7 +470,8 @@
          * @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) {
+        public UserData(
+                List<WifiConfiguration> configurations, Set<String> deletedEphemeralSSIDs) {
             this.configurations = configurations;
             this.deletedEphemeralSSIDs = deletedEphemeralSSIDs;
         }
@@ -467,7 +485,7 @@
          * @return new instance of store data.
          */
         public static UserData parseRawData(byte[] userDataBytes)
-            throws XmlPullParserException, IOException {
+                throws XmlPullParserException, IOException {
             final XmlPullParser in = Xml.newPullParser();
             final ByteArrayInputStream inputStream = new ByteArrayInputStream(userDataBytes);
             in.setInput(inputStream, StandardCharsets.UTF_8.name());
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerNewTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerNewTest.java
index c190ac1..88baa1e 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerNewTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerNewTest.java
@@ -1715,7 +1715,7 @@
             WifiConfigStoreData storeData = storeDataCaptor.getValue();
 
             boolean foundNetworkInStoreData = false;
-            for (WifiConfiguration retrievedConfig : storeData.configurations) {
+            for (WifiConfiguration retrievedConfig : storeData.getConfigurations()) {
                 if (retrievedConfig.configKey().equals(configuration.configKey())) {
                     foundNetworkInStoreData = true;
                 }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreDataTest.java
index 217d4aa..a718c33 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreDataTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreDataTest.java
@@ -116,8 +116,8 @@
     public static void assertConfigStoreDataEqual(
             WifiConfigStoreData expected, WifiConfigStoreData actual) {
         WifiConfigurationTestUtil.assertConfigurationsEqualForConfigStore(
-                expected.configurations, actual.configurations);
-        assertEquals(expected.deletedEphemeralSSIDs, actual.deletedEphemeralSSIDs);
+                expected.getConfigurations(), actual.getConfigurations());
+        assertEquals(expected.getDeletedEphemeralSSIDs(), actual.getDeletedEphemeralSSIDs());
     }
 
     /**
@@ -128,7 +128,7 @@
     public void testMultipleNetworkAllShared()
             throws XmlPullParserException, IOException {
         List<WifiConfiguration> configurations = createNetworks(true);
-        serializeDeserializeConfigStoreData(configurations);
+        serializeDeserializeConfigStoreData(configurations, new ArrayList<WifiConfiguration>());
     }
 
     /**
@@ -139,7 +139,7 @@
     public void testMultipleNetworksAllUser()
             throws XmlPullParserException, IOException {
         List<WifiConfiguration> configurations = createNetworks(false);
-        serializeDeserializeConfigStoreData(configurations);
+        serializeDeserializeConfigStoreData(new ArrayList<WifiConfiguration>(), configurations);
     }
 
     /**
@@ -161,7 +161,7 @@
         for (WifiConfiguration config : userConfigurations) {
             config.shared = false;
         }
-        serializeDeserializeConfigStoreData(configurations);
+        serializeDeserializeConfigStoreData(sharedConfigurations, userConfigurations);
     }
 
     /**
@@ -173,7 +173,8 @@
     public void testMultipleNetworksSharedDataNullInParseRawData()
             throws XmlPullParserException, IOException {
         List<WifiConfiguration> configurations = createNetworks(false);
-        serializeDeserializeConfigStoreData(configurations, true, false);
+        serializeDeserializeConfigStoreData(
+                new ArrayList<WifiConfiguration>(), configurations, true, false);
     }
 
     /**
@@ -185,7 +186,8 @@
     public void testMultipleNetworksUserDataNullInParseRawData()
             throws XmlPullParserException, IOException {
         List<WifiConfiguration> configurations = createNetworks(true);
-        serializeDeserializeConfigStoreData(configurations, false, true);
+        serializeDeserializeConfigStoreData(
+                configurations, new ArrayList<WifiConfiguration>(), false, true);
     }
 
     /**
@@ -203,11 +205,12 @@
         userNetwork.shared = false;
 
         // Create the store data for comparison.
-        List<WifiConfiguration> networks = new ArrayList<>();
-        networks.add(sharedNetwork);
-        networks.add(userNetwork);
+        List<WifiConfiguration> sharedNetworks = new ArrayList<>();
+        List<WifiConfiguration> userNetworks = new ArrayList<>();
+        sharedNetworks.add(sharedNetwork);
+        userNetworks.add(userNetwork);
         WifiConfigStoreData storeData =
-                new WifiConfigStoreData(networks, new HashSet<String>());
+                new WifiConfigStoreData(sharedNetworks, userNetworks, new HashSet<String>());
 
         String sharedStoreXmlString =
                 String.format(SINGLE_OPEN_NETWORK_SHARED_DATA_XML_STRING_FORMAT,
@@ -365,9 +368,11 @@
     /**
      * Helper method to serialize/deserialize store data.
      */
-    private void serializeDeserializeConfigStoreData(List<WifiConfiguration> configurations)
+    private void serializeDeserializeConfigStoreData(
+            List<WifiConfiguration> sharedConfigurations,
+            List<WifiConfiguration> userConfigurations)
             throws XmlPullParserException, IOException {
-        serializeDeserializeConfigStoreData(configurations, false, false);
+        serializeDeserializeConfigStoreData(sharedConfigurations, userConfigurations, false, false);
     }
 
     /**
@@ -377,15 +382,17 @@
      * 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 configurations list of configurations to be added in the store data 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> configurations, boolean setSharedDataNull,
-            boolean setUserDataNull)
+            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.
@@ -400,7 +407,8 @@
 
         // Serialize the data.
         WifiConfigStoreData storeData =
-                new WifiConfigStoreData(configurations, deletedEphemeralList);
+                new WifiConfigStoreData(
+                        sharedConfigurations, userConfigurations, deletedEphemeralList);
 
         byte[] sharedDataBytes = null;
         byte[] userDataBytes = null;
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreNewTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreNewTest.java
index 462a229..b00c700 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreNewTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreNewTest.java
@@ -17,6 +17,7 @@
 package com.android.server.wifi;
 
 import static com.android.server.wifi.WifiConfigStoreDataTest.assertConfigStoreDataEqual;
+
 import static org.junit.Assert.*;
 import static org.mockito.Mockito.*;
 
@@ -188,7 +189,9 @@
      * Returns an empty store data object.
      */
     private WifiConfigStoreData getEmptyStoreData() {
-        return new WifiConfigStoreData(new ArrayList<WifiConfiguration>(), new HashSet<String>());
+        return new WifiConfigStoreData(
+                new ArrayList<WifiConfiguration>(), new ArrayList<WifiConfiguration>(),
+                new HashSet<String>());
     }
 
     /**
@@ -197,7 +200,8 @@
     private WifiConfigStoreData createSingleOpenNetworkStoreData() {
         List<WifiConfiguration> configurations = new ArrayList<>();
         configurations.add(WifiConfigurationTestUtil.createOpenNetwork());
-        return new WifiConfigStoreData(configurations, new HashSet<String>());
+        return new WifiConfigStoreData(
+                configurations, new ArrayList<WifiConfiguration>(), new HashSet<String>());
     }
 
     /**
@@ -206,7 +210,8 @@
     private WifiConfigStoreData createSinglePskNetworkStoreData() {
         List<WifiConfiguration> configurations = new ArrayList<>();
         configurations.add(WifiConfigurationTestUtil.createPskNetwork());
-        return new WifiConfigStoreData(configurations, new HashSet<String>());
+        return new WifiConfigStoreData(
+                configurations, new ArrayList<WifiConfiguration>(), new HashSet<String>());
     }
 
     /**