• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wifi;
18 
19 import static com.android.server.wifi.WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION;
20 
21 import android.annotation.Nullable;
22 import android.net.wifi.WifiConfiguration;
23 import android.net.wifi.WifiEnterpriseConfig;
24 import android.net.wifi.WifiNetworkSuggestion;
25 import android.net.wifi.hotspot2.PasspointConfiguration;
26 import android.os.Process;
27 import android.telephony.TelephonyManager;
28 import android.util.Log;
29 import android.util.Pair;
30 
31 import com.android.server.wifi.WifiNetworkSuggestionsManager.ExtendedWifiNetworkSuggestion;
32 import com.android.server.wifi.WifiNetworkSuggestionsManager.PerAppInfo;
33 import com.android.server.wifi.hotspot2.PasspointXmlUtils;
34 import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil;
35 import com.android.server.wifi.util.XmlUtil;
36 import com.android.server.wifi.util.XmlUtil.WifiConfigurationXmlUtil;
37 
38 import org.xmlpull.v1.XmlPullParser;
39 import org.xmlpull.v1.XmlPullParserException;
40 import org.xmlpull.v1.XmlSerializer;
41 
42 import java.io.IOException;
43 import java.util.Collection;
44 import java.util.Collections;
45 import java.util.HashMap;
46 import java.util.Map;
47 import java.util.Map.Entry;
48 
49 /**
50  * This class performs serialization and parsing of XML data block that contain the list of WiFi
51  * network suggestions.
52  */
53 public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData {
54     private static final String TAG = "NetworkSuggestionStoreData";
55 
56     private static final String XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_MAP =
57             "NetworkSuggestionMap";
58     private static final String XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP =
59             "NetworkSuggestionPerApp";
60     private static final String XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION = "NetworkSuggestion";
61     private static final String XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION = "WifiConfiguration";
62     private static final String XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION =
63             "WifiEnterpriseConfiguration";
64     private static final String XML_TAG_IS_APP_INTERACTION_REQUIRED = "IsAppInteractionRequired";
65     private static final String XML_TAG_IS_USER_INTERACTION_REQUIRED = "IsUserInteractionRequired";
66     private static final String XML_TAG_IS_USER_ALLOWED_TO_MANUALLY_CONNECT =
67             "IsUserAllowedToManuallyConnect";
68     private static final String XML_TAG_IS_INITIALIZED_AUTO_JOIN = "InitializedAutoJoinEnabled";
69     private static final String XML_TAG_IS_AUTO_JOIN = "AutoJoinEnabled";
70     private static final String XML_TAG_SUGGESTOR_UID = "SuggestorUid";
71     private static final String XML_TAG_SUGGESTOR_PACKAGE_NAME = "SuggestorPackageName";
72     private static final String XML_TAG_SUGGESTOR_FEATURE_ID = "SuggestorFeatureId";
73     private static final String XML_TAG_SUGGESTOR_HAS_USER_APPROVED = "SuggestorHasUserApproved";
74     private static final String XML_TAG_SUGGESTOR_CARRIER_ID = "SuggestorCarrierId";
75     private static final String XML_TAG_SUGGESTOR_MAX_SIZE = "SuggestorMaxSize";
76     private static final String XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION =
77             "PasspointConfiguration";
78     private static final String XML_TAG_PRIORITY_GROUP = "PriorityGroup";
79     private static final String XML_TAG_CONNECT_CHOICE = "ConnectChoice";
80     private static final String XML_TAG_CONNECT_CHOICE_RSSI = "ConnectChoiceRssi";
81 
82     /**
83      * Interface define the data source for the network suggestions store data.
84      */
85     public interface DataSource {
86         /**
87          * Retrieve the network suggestion list from the data source to serialize them to disk.
88          *
89          * @return Map of package name to {@link PerAppInfo}
90          */
toSerialize()91         Map<String, PerAppInfo> toSerialize();
92 
93         /**
94          * Set the network suggestions list in the data source after serializing them from disk.
95          *
96          * @param networkSuggestions Map of package name to {@link PerAppInfo}
97          */
fromDeserialized(Map<String, PerAppInfo> networkSuggestions)98         void fromDeserialized(Map<String, PerAppInfo> networkSuggestions);
99 
100         /**
101          * Clear internal data structure in preparation for user switch or initial store read.
102          */
reset()103         void reset();
104 
105         /**
106          * Indicates whether there is new data to serialize.
107          */
hasNewDataToSerialize()108         boolean hasNewDataToSerialize();
109     }
110 
111     private final DataSource mDataSource;
112 
NetworkSuggestionStoreData(DataSource dataSource)113     public NetworkSuggestionStoreData(DataSource dataSource) {
114         mDataSource = dataSource;
115     }
116 
117     @Override
serializeData(XmlSerializer out, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)118     public void serializeData(XmlSerializer out,
119             @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)
120             throws XmlPullParserException, IOException {
121         serializeNetworkSuggestionsMap(out, mDataSource.toSerialize(), encryptionUtil);
122     }
123 
124     @Override
deserializeData(XmlPullParser in, int outerTagDepth, @WifiConfigStore.Version int version, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)125     public void deserializeData(XmlPullParser in, int outerTagDepth,
126             @WifiConfigStore.Version int version,
127             @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)
128             throws XmlPullParserException, IOException {
129         if (in == null) {
130             mDataSource.fromDeserialized(Collections.EMPTY_MAP);
131             return;
132         }
133         mDataSource.fromDeserialized(
134                 parseNetworkSuggestionsMap(in, outerTagDepth, version, encryptionUtil));
135     }
136 
137     @Override
resetData()138     public void resetData() {
139         mDataSource.reset();
140     }
141 
142     @Override
hasNewDataToSerialize()143     public boolean hasNewDataToSerialize() {
144         return mDataSource.hasNewDataToSerialize();
145     }
146 
147     @Override
getName()148     public String getName() {
149         return XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_MAP;
150     }
151 
152     @Override
getStoreFileId()153     public @WifiConfigStore.StoreFileId int getStoreFileId() {
154         return WifiConfigStore.STORE_FILE_USER_NETWORK_SUGGESTIONS;
155     }
156 
157     /**
158      * Serialize the map of package name to network suggestions to an output stream in XML format.
159      *
160      * @throws XmlPullParserException
161      * @throws IOException
162      */
serializeNetworkSuggestionsMap( XmlSerializer out, final Map<String, PerAppInfo> networkSuggestionsMap, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)163     private void serializeNetworkSuggestionsMap(
164             XmlSerializer out, final Map<String, PerAppInfo> networkSuggestionsMap,
165             @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)
166             throws XmlPullParserException, IOException {
167         if (networkSuggestionsMap == null) {
168             return;
169         }
170         for (Entry<String, PerAppInfo> entry : networkSuggestionsMap.entrySet()) {
171             String packageName = entry.getValue().packageName;
172             String featureId = entry.getValue().featureId;
173             boolean hasUserApproved = entry.getValue().hasUserApproved;
174             int maxSize = entry.getValue().maxSize;
175             int uid = entry.getValue().uid;
176             int carrierId = entry.getValue().carrierId;
177             Collection<ExtendedWifiNetworkSuggestion> networkSuggestions =
178                     entry.getValue().extNetworkSuggestions.values();
179             XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP);
180             XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_PACKAGE_NAME, packageName);
181             XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_FEATURE_ID, featureId);
182             XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_HAS_USER_APPROVED, hasUserApproved);
183             XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_MAX_SIZE, maxSize);
184             XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_UID, uid);
185             XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_CARRIER_ID, carrierId);
186             serializeExtNetworkSuggestions(out, networkSuggestions, encryptionUtil);
187             XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP);
188         }
189     }
190 
191     /**
192      * Serialize the set of network suggestions to an output stream in XML format.
193      *
194      * @throws XmlPullParserException
195      * @throws IOException
196      */
serializeExtNetworkSuggestions(XmlSerializer out, final Collection<ExtendedWifiNetworkSuggestion> extNetworkSuggestions, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)197     private void serializeExtNetworkSuggestions(XmlSerializer out,
198             final Collection<ExtendedWifiNetworkSuggestion> extNetworkSuggestions,
199             @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)
200             throws XmlPullParserException, IOException {
201         for (ExtendedWifiNetworkSuggestion extNetworkSuggestion : extNetworkSuggestions) {
202             serializeNetworkSuggestion(out, extNetworkSuggestion, encryptionUtil);
203         }
204     }
205 
206     /**
207      * Serialize a {@link ExtendedWifiNetworkSuggestion} to an output stream in XML format.
208      *
209      * @throws XmlPullParserException
210      * @throws IOException
211      */
serializeNetworkSuggestion(XmlSerializer out, final ExtendedWifiNetworkSuggestion extSuggestion, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)212     private void serializeNetworkSuggestion(XmlSerializer out,
213             final ExtendedWifiNetworkSuggestion extSuggestion,
214             @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)
215             throws XmlPullParserException, IOException {
216         WifiNetworkSuggestion suggestion = extSuggestion.wns;
217 
218         XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION);
219 
220         // Serialize WifiConfiguration.
221         XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION);
222         WifiConfigurationXmlUtil.writeToXmlForConfigStore(
223                 out, suggestion.wifiConfiguration, encryptionUtil);
224         XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION);
225         // Serialize enterprise configuration for enterprise networks.
226         if (suggestion.wifiConfiguration.enterpriseConfig != null
227                 && suggestion.wifiConfiguration.enterpriseConfig.getEapMethod()
228                 != WifiEnterpriseConfig.Eap.NONE) {
229             XmlUtil.writeNextSectionStart(
230                     out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION);
231             XmlUtil.WifiEnterpriseConfigXmlUtil.writeToXml(
232                     out, suggestion.wifiConfiguration.enterpriseConfig, encryptionUtil);
233             XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION);
234         }
235         if (suggestion.passpointConfiguration != null) {
236             XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION);
237             PasspointXmlUtils.serializePasspointConfiguration(out,
238                     suggestion.passpointConfiguration);
239             XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION);
240         }
241 
242         // Serialize other fields
243         XmlUtil.writeNextValue(out, XML_TAG_IS_APP_INTERACTION_REQUIRED,
244                 suggestion.isAppInteractionRequired);
245         XmlUtil.writeNextValue(out, XML_TAG_IS_USER_INTERACTION_REQUIRED,
246                 suggestion.isUserInteractionRequired);
247         XmlUtil.writeNextValue(out, XML_TAG_IS_USER_ALLOWED_TO_MANUALLY_CONNECT,
248                 suggestion.isUserAllowedToManuallyConnect);
249         XmlUtil.writeNextValue(out, XML_TAG_IS_INITIALIZED_AUTO_JOIN,
250                 suggestion.isInitialAutoJoinEnabled);
251         XmlUtil.writeNextValue(out, XML_TAG_IS_AUTO_JOIN,
252                 extSuggestion.isAutojoinEnabled);
253         XmlUtil.writeNextValue(out, XML_TAG_PRIORITY_GROUP, suggestion.priorityGroup);
254         XmlUtil.writeNextValue(out, XML_TAG_CONNECT_CHOICE, extSuggestion.connectChoice);
255         XmlUtil.writeNextValue(out, XML_TAG_CONNECT_CHOICE_RSSI, extSuggestion.connectChoiceRssi);
256         XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION);
257     }
258 
259     /**
260      * Parse a map of package name to network suggestions from an input stream in XML format.
261      *
262      * @throws XmlPullParserException
263      * @throws IOException
264      */
parseNetworkSuggestionsMap(XmlPullParser in, int outerTagDepth, @WifiConfigStore.Version int version, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)265     private Map<String, PerAppInfo> parseNetworkSuggestionsMap(XmlPullParser in, int outerTagDepth,
266             @WifiConfigStore.Version int version,
267             @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)
268             throws XmlPullParserException, IOException {
269         Map<String, PerAppInfo> networkSuggestionsMap = new HashMap<>();
270         while (XmlUtil.gotoNextSectionWithNameOrEnd(
271                 in, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP, outerTagDepth)) {
272             // Try/catch only runtime exceptions (like illegal args), any XML/IO exceptions are
273             // fatal and should abort the entire loading process.
274             try {
275                 PerAppInfo perAppInfo = null;
276                 String packageName = null;
277                 String featureId = null;
278                 boolean hasUserApproved = false;
279                 int maxSize = -1;
280                 int uid = Process.INVALID_UID;
281                 int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
282                 // Loop through and parse out all the elements from the stream within this section.
283                 while (XmlUtil.nextElementWithin(in, outerTagDepth + 1)) {
284                     if (in.getAttributeValue(null, "name") != null) {
285                         // Value elements.
286                         String[] valueName = new String[1];
287                         Object value = XmlUtil.readCurrentValue(in, valueName);
288                         switch (valueName[0]) {
289                             case XML_TAG_SUGGESTOR_PACKAGE_NAME:
290                                 packageName = (String) value;
291                                 break;
292                             case XML_TAG_SUGGESTOR_FEATURE_ID:
293                                 featureId = (String) value;
294                                 break;
295                             case XML_TAG_SUGGESTOR_HAS_USER_APPROVED:
296                                 hasUserApproved = (boolean) value;
297                                 break;
298                             case XML_TAG_SUGGESTOR_MAX_SIZE:
299                                 maxSize = (int) value;
300                                 break;
301                             case XML_TAG_SUGGESTOR_UID:
302                                 uid = (int) value;
303                                 break;
304                             case XML_TAG_SUGGESTOR_CARRIER_ID:
305                                 carrierId = (int) value;
306                                 break;
307                             default:
308                                 Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]);
309                                 break;
310                         }
311                     } else {
312                         String tagName = in.getName();
313                         if (tagName == null) {
314                             throw new XmlPullParserException("Unexpected null under "
315                                     + XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP);
316                         }
317                         // Create the PerAppInfo struct before parsing individual network
318                         // suggestions in the block.
319                         if (perAppInfo == null) {
320                             if (packageName == null) {
321                                 throw new XmlPullParserException(
322                                         "XML parsing of PerAppInfo failed");
323                             }
324                             perAppInfo = new PerAppInfo(uid, packageName, featureId);
325                             perAppInfo.hasUserApproved = hasUserApproved;
326                             perAppInfo.maxSize = maxSize;
327                             perAppInfo.carrierId = carrierId;
328                         }
329                         switch (tagName) {
330                             case XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION:
331                                 ExtendedWifiNetworkSuggestion ewns = parseNetworkSuggestion(in,
332                                         outerTagDepth + 2, version, encryptionUtil, perAppInfo);
333                                 perAppInfo.extNetworkSuggestions.put(ewns.hashCode(), ewns);
334                                 break;
335                             default:
336                                 Log.w(TAG, "Ignoring unknown tag under "
337                                         + XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP + ": "
338                                         + in.getName());
339                                 break;
340                         }
341                     }
342                 }
343                 // If app has no suggestions, create perAppInfo here.
344                 if (perAppInfo == null) {
345                     if (packageName == null) {
346                         throw new XmlPullParserException(
347                                 "XML parsing of PerAppInfo failed");
348                     }
349                     perAppInfo = new PerAppInfo(uid, packageName, featureId);
350                     perAppInfo.hasUserApproved = hasUserApproved;
351                     perAppInfo.maxSize = maxSize;
352                 }
353                 // Store this app info in the map.
354                 networkSuggestionsMap.put(packageName, perAppInfo);
355             } catch (RuntimeException e) {
356                 // Failed to parse this network, skip it.
357                 Log.e(TAG, "Failed to parse network suggestion. Skipping...", e);
358             }
359         }
360         return networkSuggestionsMap;
361     }
362 
363     /**
364      * Parse a {@link ExtendedWifiNetworkSuggestion} from an input stream in XML format.
365      *
366      * @throws XmlPullParserException
367      * @throws IOException
368      */
parseNetworkSuggestion(XmlPullParser in, int outerTagDepth, @WifiConfigStore.Version int version, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil, PerAppInfo perAppInfo)369     private ExtendedWifiNetworkSuggestion parseNetworkSuggestion(XmlPullParser in,
370             int outerTagDepth, @WifiConfigStore.Version int version,
371             @Nullable WifiConfigStoreEncryptionUtil encryptionUtil, PerAppInfo perAppInfo)
372             throws XmlPullParserException, IOException {
373         Pair<String, WifiConfiguration> parsedConfig = null;
374         WifiEnterpriseConfig enterpriseConfig = null;
375         PasspointConfiguration passpointConfiguration = null;
376         boolean isAppInteractionRequired = false;
377         boolean isUserInteractionRequired = false;
378         boolean isUserAllowedToManuallyConnect = false; // Backward compatibility.
379         boolean isInitializedAutoJoinEnabled = true; // backward compat
380         boolean isAutoJoinEnabled = true; // backward compat
381         boolean isNetworkUntrusted = false;
382         int priorityGroup = WifiNetworkSuggestionsManager.DEFAULT_PRIORITY_GROUP;
383         int suggestorUid = Process.INVALID_UID;
384         String connectChoice = null;
385         int connectChoiceRssi = 0;
386 
387         // Loop through and parse out all the elements from the stream within this section.
388         while (XmlUtil.nextElementWithin(in, outerTagDepth)) {
389             if (in.getAttributeValue(null, "name") != null) {
390                 // Value elements.
391                 String[] valueName = new String[1];
392                 Object value = XmlUtil.readCurrentValue(in, valueName);
393                 switch (valueName[0]) {
394                     case XML_TAG_IS_APP_INTERACTION_REQUIRED:
395                         isAppInteractionRequired = (boolean) value;
396                         break;
397                     case XML_TAG_IS_USER_INTERACTION_REQUIRED:
398                         isUserInteractionRequired = (boolean) value;
399                         break;
400                     case XML_TAG_IS_USER_ALLOWED_TO_MANUALLY_CONNECT:
401                         isUserAllowedToManuallyConnect = (boolean) value;
402                         break;
403                     case XML_TAG_IS_INITIALIZED_AUTO_JOIN:
404                         isInitializedAutoJoinEnabled = (boolean) value;
405                         break;
406                     case XML_TAG_IS_AUTO_JOIN:
407                         isAutoJoinEnabled = (boolean) value;
408                         break;
409                     case XML_TAG_SUGGESTOR_UID:
410                         // Only needed for migration of data from Q to R.
411                         suggestorUid = (int) value;
412                         break;
413                     case XML_TAG_PRIORITY_GROUP:
414                         priorityGroup = (int) value;
415                         break;
416                     case XML_TAG_CONNECT_CHOICE:
417                         connectChoice = (String) value;
418                         break;
419                     case XML_TAG_CONNECT_CHOICE_RSSI:
420                         connectChoiceRssi = (int) value;
421                         break;
422                     default:
423                         Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]);
424                         break;
425                 }
426             } else {
427                 String tagName = in.getName();
428                 if (tagName == null) {
429                     throw new XmlPullParserException("Unexpected null under "
430                             + XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION);
431                 }
432                 switch (tagName) {
433                     case XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION:
434                         if (parsedConfig != null) {
435                             throw new XmlPullParserException("Detected duplicate tag for: "
436                                     + XML_TAG_SECTION_HEADER_WIFI_CONFIGURATION);
437                         }
438                         parsedConfig = WifiConfigurationXmlUtil.parseFromXml(
439                                 in, outerTagDepth + 1,
440                                 version >= ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION,
441                                 encryptionUtil, true);
442                         break;
443                     case XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION:
444                         if (enterpriseConfig != null) {
445                             throw new XmlPullParserException("Detected duplicate tag for: "
446                                     + XML_TAG_SECTION_HEADER_WIFI_ENTERPRISE_CONFIGURATION);
447                         }
448                         enterpriseConfig = XmlUtil.WifiEnterpriseConfigXmlUtil.parseFromXml(
449                                 in, outerTagDepth + 1,
450                             version >= ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION,
451                             encryptionUtil);
452                         break;
453                     case XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION:
454                         if (passpointConfiguration != null) {
455                             throw new XmlPullParserException("Detected duplicate tag for: "
456                                     + XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION);
457                         }
458                         passpointConfiguration = PasspointXmlUtils
459                                 .deserializePasspointConfiguration(in, outerTagDepth + 1);
460                         break;
461                     default:
462                         Log.w(TAG, "Ignoring unknown tag under "
463                                 + XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION + ": " + in.getName());
464                         break;
465                 }
466             }
467         }
468         if (parsedConfig == null || parsedConfig.second == null) {
469             throw new XmlPullParserException("XML parsing of wifi configuration failed");
470         }
471         // Note: In R, we migrated the uid/package name storage from individual
472         // ExtWifiNetworkSuggestion to the top level PerAppInfo. This block of code helps
473         // with migration of data for devices upgrading from Q to R.
474         perAppInfo.setUid(suggestorUid);
475         WifiConfiguration wifiConfiguration = parsedConfig.second;
476         if (passpointConfiguration != null) {
477             wifiConfiguration.setPasspointUniqueId(passpointConfiguration.getUniqueId());
478         }
479         if (enterpriseConfig != null) {
480             wifiConfiguration.enterpriseConfig = enterpriseConfig;
481         }
482         ExtendedWifiNetworkSuggestion ewns = ExtendedWifiNetworkSuggestion
483                 .fromWns(new WifiNetworkSuggestion(wifiConfiguration, passpointConfiguration,
484                         isAppInteractionRequired, isUserInteractionRequired,
485                         isUserAllowedToManuallyConnect, isInitializedAutoJoinEnabled,
486                         priorityGroup), perAppInfo, isAutoJoinEnabled);
487         ewns.connectChoice = connectChoice;
488         ewns.connectChoiceRssi = connectChoiceRssi;
489         return ewns;
490     }
491 }
492 
493