SupplicantStaIfaceHal: Handle exceptions during network load

To guard against the wpa_supplicant.conf having some invalid/unsupported
values, handle exceptions in framework and skip such networks instead of
crashing the entire system and failing the entire migration of data out
of wpa_supplicant.

Bug: 35915083
Test: Added unit tests
Change-Id: Ic7df2f144c34814e830eb1f48ff2204890fd83ea
(cherry picked from commit a859d834edbba90793c2ff36ce2d579cac617786)
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
index 52fe608..3a7ac03 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
@@ -464,9 +464,16 @@
             }
             WifiConfiguration config = new WifiConfiguration();
             Map<String, String> networkExtra = new HashMap<>();
-            if (!network.loadWifiConfiguration(config, networkExtra)) {
-                Log.e(TAG, "Failed to load wifi configuration for network with ID: " + networkId);
-                return false;
+            boolean loadSuccess = false;
+            try {
+                loadSuccess = network.loadWifiConfiguration(config, networkExtra);
+            } catch (IllegalArgumentException e) {
+                Log.wtf(TAG, "Exception while loading config params: " + config, e);
+            }
+            if (!loadSuccess) {
+                Log.e(TAG, "Failed to load wifi configuration for network with ID: " + networkId
+                        + ". Skipping...");
+                continue;
             }
             // Set the default IP assignments.
             config.setIpAssignment(IpConfiguration.IpAssignment.DHCP);
diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java
index 604844b..d711132 100644
--- a/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java
@@ -393,6 +393,13 @@
         }).when(mISupplicantStaIfaceMock)
                 .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class));
         doAnswer(new MockAnswerUtil.AnswerWithArguments() {
+            public void answer(final int networkId, ISupplicantStaIface.getNetworkCallback cb) {
+                cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class));
+                return;
+            }
+        }).when(mISupplicantStaIfaceMock)
+                .getNetwork(anyInt(), any(ISupplicantStaIface.getNetworkCallback.class));
+        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
             public boolean answer(WifiConfiguration config, Map<String, String> networkExtra) {
                 return false;
             }
@@ -401,7 +408,41 @@
 
         Map<String, WifiConfiguration> configs = new HashMap<>();
         SparseArray<Map<String, String>> extras = new SparseArray<>();
-        assertFalse(mDut.loadNetworks(configs, extras));
+        assertTrue(mDut.loadNetworks(configs, extras));
+        assertTrue(configs.isEmpty());
+    }
+
+    /**
+     * Tests the failure to load networks because of loadWifiConfiguration exception.
+     */
+    @Test
+    public void testLoadNetworksFailedDueToExceptionInLoadWifiConfiguration() throws Exception {
+        executeAndValidateInitializationSequence();
+        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
+            public void answer(ISupplicantStaIface.listNetworksCallback cb) {
+                cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet()));
+            }
+        }).when(mISupplicantStaIfaceMock)
+                .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class));
+        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
+            public void answer(final int networkId, ISupplicantStaIface.getNetworkCallback cb) {
+                cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class));
+                return;
+            }
+        }).when(mISupplicantStaIfaceMock)
+                .getNetwork(anyInt(), any(ISupplicantStaIface.getNetworkCallback.class));
+        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
+            public boolean answer(WifiConfiguration config, Map<String, String> networkExtra)
+                    throws Exception {
+                throw new IllegalArgumentException();
+            }
+        }).when(mSupplicantStaNetworkMock)
+                .loadWifiConfiguration(any(WifiConfiguration.class), any(Map.class));
+
+        Map<String, WifiConfiguration> configs = new HashMap<>();
+        SparseArray<Map<String, String>> extras = new SparseArray<>();
+        assertTrue(mDut.loadNetworks(configs, extras));
+        assertTrue(configs.isEmpty());
     }
 
     /**