NetworkListStoreData: Set creatorUid for all networks on load

Some network configurations saved during N have the creatorUid set to -1.
(Not sure what was the root cause in N which introduced this issue in
saved networks)
Ensure that we set |creatorUid| for such networks with invalid uid to
SYSTEM_UID on loading. The networks with invalid creatorUid can
anyway only be modified only by settings/sysui (because they possess
NETWORK_SETTINGS permission).

Bug: 65623732
Test: Unit tests
Change-Id: Ib6f61b81e19877cdf0c42d29c9f5ae3869725517
diff --git a/service/java/com/android/server/wifi/NetworkListStoreData.java b/service/java/com/android/server/wifi/NetworkListStoreData.java
index 5ddfd4d..f287d4b 100644
--- a/service/java/com/android/server/wifi/NetworkListStoreData.java
+++ b/service/java/com/android/server/wifi/NetworkListStoreData.java
@@ -16,10 +16,12 @@
 
 package com.android.server.wifi;
 
+import android.content.Context;
 import android.net.IpConfiguration;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
 import android.net.wifi.WifiEnterpriseConfig;
+import android.os.Process;
 import android.util.Log;
 import android.util.Pair;
 
@@ -52,6 +54,8 @@
     private static final String XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION =
             "WifiEnterpriseConfiguration";
 
+    private final Context mContext;
+
     /**
      * List of saved shared networks visible to all the users to be stored in the shared store file.
      */
@@ -62,7 +66,9 @@
      */
     private List<WifiConfiguration> mUserConfigurations;
 
-    NetworkListStoreData() {}
+    NetworkListStoreData(Context context) {
+        mContext = context;
+    }
 
     @Override
     public void serializeData(XmlSerializer out, boolean shared)
@@ -282,6 +288,19 @@
                     "Configuration key does not match. Retrieved: " + configKeyParsed
                             + ", Calculated: " + configKeyCalculated);
         }
+        // Set creatorUid/creatorName for networks which don't have it set to valid value.
+        String creatorName = mContext.getPackageManager().getNameForUid(configuration.creatorUid);
+        if (creatorName == null) {
+            Log.e(TAG, "Invalid creatorUid for saved network " + configuration.configKey()
+                    + ", creatorUid=" + configuration.creatorUid);
+            configuration.creatorUid = Process.SYSTEM_UID;
+            configuration.creatorName = creatorName;
+        } else if (!creatorName.equals(configuration.creatorName)) {
+            Log.w(TAG, "Invalid creatorName for saved network " + configuration.configKey()
+                    + ", creatorUid=" + configuration.creatorUid
+                    + ", creatorName=" + configuration.creatorName);
+            configuration.creatorName = creatorName;
+        }
 
         configuration.setNetworkSelectionStatus(status);
         configuration.setIpConfiguration(ipConfiguration);
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index fc3af83..9239839 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -197,7 +197,7 @@
         mWifiConfigManager = new WifiConfigManager(mContext, mClock,
                 UserManager.get(mContext), TelephonyManager.from(mContext),
                 mWifiKeyStore, mWifiConfigStore, mWifiPermissionsUtil,
-                mWifiPermissionsWrapper, new NetworkListStoreData(),
+                mWifiPermissionsWrapper, new NetworkListStoreData(mContext),
                 new DeletedEphemeralSsidsStoreData());
         mWifiMetrics.setWifiConfigManager(mWifiConfigManager);
         mWifiConnectivityHelper = new WifiConnectivityHelper(mWifiNative);
diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java
index cbad3bb..19a92b8 100644
--- a/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/NetworkListStoreDataTest.java
@@ -16,9 +16,13 @@
 
 package com.android.server.wifi;
 
+import static android.os.Process.SYSTEM_UID;
+
 import static org.junit.Assert.*;
 import static org.mockito.Mockito.*;
 
+import android.content.Context;
+import android.content.pm.PackageManager;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiEnterpriseConfig;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -29,6 +33,8 @@
 
 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;
@@ -49,6 +55,7 @@
     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 TEST_CREATOR_NAME = "CreatorName";
     private static final String SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT =
             "<Network>\n"
                     + "<WifiConfiguration>\n"
@@ -79,7 +86,7 @@
                     + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
                     + "<int name=\"NumAssociation\" value=\"0\" />\n"
                     + "<int name=\"CreatorUid\" value=\"%d\" />\n"
-                    + "<null name=\"CreatorName\" />\n"
+                    + "<string name=\"CreatorName\">%s</string>\n"
                     + "<null name=\"CreationTime\" />\n"
                     + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
                     + "<null name=\"LastUpdateName\" />\n"
@@ -130,7 +137,7 @@
                     + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
                     + "<int name=\"NumAssociation\" value=\"0\" />\n"
                     + "<int name=\"CreatorUid\" value=\"%d\" />\n"
-                    + "<null name=\"CreatorName\" />\n"
+                    + "<string name=\"CreatorName\">%s</string>\n"
                     + "<null name=\"CreationTime\" />\n"
                     + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
                     + "<null name=\"LastUpdateName\" />\n"
@@ -170,10 +177,15 @@
                     + "</Network>\n";
 
     private NetworkListStoreData mNetworkListStoreData;
+    @Mock private Context mContext;
+    @Mock private PackageManager mPackageManager;
 
     @Before
     public void setUp() throws Exception {
-        mNetworkListStoreData = new NetworkListStoreData();
+        MockitoAnnotations.initMocks(this);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mPackageManager.getNameForUid(anyInt())).thenReturn(TEST_CREATOR_NAME);
+        mNetworkListStoreData = new NetworkListStoreData(mContext);
     }
 
     /**
@@ -221,11 +233,13 @@
      */
     private List<WifiConfiguration> getTestNetworksConfig(boolean shared) {
         WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+        openNetwork.creatorName = TEST_CREATOR_NAME;
         openNetwork.shared = shared;
         openNetwork.setIpConfiguration(
                 WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
         WifiConfiguration eapNetwork = WifiConfigurationTestUtil.createEapNetwork();
         eapNetwork.shared = shared;
+        eapNetwork.creatorName = TEST_CREATOR_NAME;
         eapNetwork.setIpConfiguration(
                 WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
         List<WifiConfiguration> networkList = new ArrayList<>();
@@ -247,11 +261,11 @@
         String openNetworkXml = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT,
                 openNetwork.configKey().replaceAll("\"", "&quot;"),
                 openNetwork.SSID.replaceAll("\"", "&quot;"),
-                openNetwork.shared, openNetwork.creatorUid);
+                openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName);
         String eapNetworkXml = String.format(SINGLE_EAP_NETWORK_DATA_XML_STRING_FORMAT,
                 eapNetwork.configKey().replaceAll("\"", "&quot;"),
                 eapNetwork.SSID.replaceAll("\"", "&quot;"),
-                eapNetwork.shared, eapNetwork.creatorUid);
+                eapNetwork.shared, eapNetwork.creatorUid, openNetwork.creatorName);
         return (openNetworkXml + eapNetworkXml).getBytes(StandardCharsets.UTF_8);
     }
 
@@ -420,7 +434,8 @@
         byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT,
                 "InvalidConfigKey",
                 openNetwork.SSID.replaceAll("\"", "&quot;"),
-                openNetwork.shared, openNetwork.creatorUid).getBytes(StandardCharsets.UTF_8);
+                openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName)
+            .getBytes(StandardCharsets.UTF_8);
         deserializeData(xmlData, true);
     }
 
@@ -448,4 +463,96 @@
             assertNotEquals(eapNetwork.SSID, network.SSID);
         }
     }
+
+    /**
+     * Verify that a saved network config with invalid creatorUid resets it to
+     * {@link android.os.Process#SYSTEM_UID}.
+     */
+    public void parseNetworkWithInvalidCreatorUidResetsToSystem() throws Exception {
+        WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+        openNetwork.creatorUid = -1;
+        // Return null for invalid uid.
+        when(mPackageManager.getNameForUid(eq(openNetwork.creatorUid))).thenReturn(null);
+
+        byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT,
+                openNetwork.configKey().replaceAll("\"", "&quot;"),
+                openNetwork.SSID.replaceAll("\"", "&quot;"),
+                openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName)
+            .getBytes(StandardCharsets.UTF_8);
+        List<WifiConfiguration> deserializedNetworks = deserializeData(xmlData, true);
+        assertEquals(1, deserializedNetworks.size());
+        assertEquals(openNetwork.configKey(), deserializedNetworks.get(0).configKey());
+        assertEquals(SYSTEM_UID, deserializedNetworks.get(0).creatorUid);
+        assertEquals(TEST_CREATOR_NAME, deserializedNetworks.get(0).creatorName);
+    }
+
+    /**
+     * Verify that a saved network config with invalid creatorName resets it to the package name
+     * provided {@link PackageManager} for the creatorUid.
+     */
+    public void parseNetworkWithInvalidCreatorNameResetsToPackageNameForCreatorUid()
+            throws Exception {
+        String badCreatorName = "bad";
+        String correctCreatorName = "correct";
+        WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+        openNetwork.creatorUid = 1324422;
+        openNetwork.creatorName = badCreatorName;
+        when(mPackageManager.getNameForUid(eq(openNetwork.creatorUid)))
+            .thenReturn(correctCreatorName);
+
+        byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT,
+                openNetwork.configKey().replaceAll("\"", "&quot;"),
+                openNetwork.SSID.replaceAll("\"", "&quot;"),
+                openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName)
+            .getBytes(StandardCharsets.UTF_8);
+        List<WifiConfiguration> deserializedNetworks = deserializeData(xmlData, true);
+        assertEquals(1, deserializedNetworks.size());
+        assertEquals(openNetwork.configKey(), deserializedNetworks.get(0).configKey());
+        assertEquals(openNetwork.creatorUid, deserializedNetworks.get(0).creatorUid);
+        assertEquals(correctCreatorName, deserializedNetworks.get(0).creatorName);
+    }
+
+    /**
+     * Verify that a saved network config with invalid creatorName resets it to the package name
+     * provided {@link PackageManager} for the creatorUid.
+     */
+    public void parseNetworkWithNullCreatorNameResetsToPackageNameForCreatorUid()
+            throws Exception {
+        String correctCreatorName = "correct";
+        WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+        openNetwork.creatorUid = 1324422;
+        openNetwork.creatorName = null;
+        when(mPackageManager.getNameForUid(eq(openNetwork.creatorUid)))
+            .thenReturn(correctCreatorName);
+
+        byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT,
+                openNetwork.configKey().replaceAll("\"", "&quot;"),
+                openNetwork.SSID.replaceAll("\"", "&quot;"),
+                openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName)
+            .getBytes(StandardCharsets.UTF_8);
+        List<WifiConfiguration> deserializedNetworks = deserializeData(xmlData, true);
+        assertEquals(1, deserializedNetworks.size());
+        assertEquals(openNetwork.configKey(), deserializedNetworks.get(0).configKey());
+        assertEquals(openNetwork.creatorUid, deserializedNetworks.get(0).creatorUid);
+        assertEquals(correctCreatorName, deserializedNetworks.get(0).creatorName);
+    }
+
+    /**
+     * Verify that a saved network config with valid creatorUid is preserved.
+     */
+    public void parseNetworkWithValidCreatorUid() throws Exception {
+        WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+        openNetwork.creatorUid = 1324422;
+
+        byte[] xmlData = String.format(SINGLE_OPEN_NETWORK_DATA_XML_STRING_FORMAT,
+                openNetwork.configKey().replaceAll("\"", "&quot;"),
+                openNetwork.SSID.replaceAll("\"", "&quot;"),
+                openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName)
+            .getBytes(StandardCharsets.UTF_8);
+        List<WifiConfiguration> deserializedNetworks = deserializeData(xmlData, true);
+        assertEquals(1, deserializedNetworks.size());
+        assertEquals(openNetwork.configKey(), deserializedNetworks.get(0).configKey());
+        assertEquals(openNetwork.creatorUid, deserializedNetworks.get(0).creatorUid);
+        assertEquals(TEST_CREATOR_NAME, deserializedNetworks.get(0).creatorName);
+    }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
index 86d6e11..0958fea 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigStoreTest.java
@@ -21,6 +21,7 @@
 
 import android.app.test.TestAlarmManager;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.net.wifi.WifiConfiguration;
 import android.os.test.TestLooper;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -60,6 +61,7 @@
 
     private static final String TEST_USER_DATA = "UserData";
     private static final String TEST_SHARE_DATA = "ShareData";
+    private static final String TEST_CREATOR_NAME = "CreatorName";
 
     private static final String TEST_DATA_XML_STRING_FORMAT =
             "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
@@ -95,7 +97,7 @@
                     + "<boolean name=\"UseExternalScores\" value=\"false\" />\n"
                     + "<int name=\"NumAssociation\" value=\"0\" />\n"
                     + "<int name=\"CreatorUid\" value=\"%d\" />\n"
-                    + "<null name=\"CreatorName\" />\n"
+                    + "<string name=\"CreatorName\">%s</string>\n"
                     + "<null name=\"CreationTime\" />\n"
                     + "<int name=\"LastUpdateUid\" value=\"-1\" />\n"
                     + "<null name=\"LastUpdateName\" />\n"
@@ -125,6 +127,7 @@
 
     // Test mocks
     @Mock private Context mContext;
+    @Mock private PackageManager mPackageManager;
     private TestAlarmManager mAlarmManager;
     private TestLooper mLooper;
     @Mock private Clock mClock;
@@ -146,6 +149,8 @@
         mLooper = new TestLooper();
         when(mContext.getSystemService(Context.ALARM_SERVICE))
                 .thenReturn(mAlarmManager.getAlarmManager());
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
+        when(mPackageManager.getNameForUid(anyInt())).thenReturn(TEST_CREATOR_NAME);
         mUserStore = new MockStoreFile();
         mSharedStore = new MockStoreFile();
         mStoreData = new MockStoreData();
@@ -364,9 +369,10 @@
     @Test
     public void testReadWifiConfigStoreData() throws Exception {
         // Setup network list.
-        NetworkListStoreData networkList = new NetworkListStoreData();
+        NetworkListStoreData networkList = new NetworkListStoreData(mContext);
         mWifiConfigStore.registerStoreData(networkList);
         WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+        openNetwork.creatorName = TEST_CREATOR_NAME;
         openNetwork.setIpConfiguration(
                 WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
         List<WifiConfiguration> userConfigs = new ArrayList<>();
@@ -384,7 +390,7 @@
         String xmlString = String.format(TEST_DATA_XML_STRING_FORMAT,
                 openNetwork.configKey().replaceAll("\"", "&quot;"),
                 openNetwork.SSID.replaceAll("\"", "&quot;"),
-                openNetwork.shared, openNetwork.creatorUid, testSsid);
+                openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName, testSsid);
         byte[] xmlBytes = xmlString.getBytes(StandardCharsets.UTF_8);
         mUserStore.storeRawDataToWrite(xmlBytes);
 
@@ -406,9 +412,10 @@
         mWifiConfigStore.switchUserStoreAndRead(mUserStore);
 
         // Setup network list store data.
-        NetworkListStoreData networkList = new NetworkListStoreData();
+        NetworkListStoreData networkList = new NetworkListStoreData(mContext);
         mWifiConfigStore.registerStoreData(networkList);
         WifiConfiguration openNetwork = WifiConfigurationTestUtil.createOpenNetwork();
+        openNetwork.creatorName = TEST_CREATOR_NAME;
         openNetwork.setIpConfiguration(
                 WifiConfigurationTestUtil.createDHCPIpConfigurationWithNoProxy());
         List<WifiConfiguration> userConfigs = new ArrayList<>();
@@ -428,7 +435,7 @@
         String xmlString = String.format(TEST_DATA_XML_STRING_FORMAT,
                 openNetwork.configKey().replaceAll("\"", "&quot;"),
                 openNetwork.SSID.replaceAll("\"", "&quot;"),
-                openNetwork.shared, openNetwork.creatorUid, testSsid);
+                openNetwork.shared, openNetwork.creatorUid, openNetwork.creatorName, testSsid);
         byte[] xmlBytes = xmlString.getBytes(StandardCharsets.UTF_8);
 
         mWifiConfigStore.write(true);