1 /*
2  * Copyright (C) 2019 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 android.annotation.Nullable;
20 import android.content.Context;
21 import android.net.MacAddress;
22 import android.net.wifi.SoftApConfiguration;
23 import android.net.wifi.WifiMigration;
24 import android.text.TextUtils;
25 import android.util.Log;
26 import android.util.SparseIntArray;
27 
28 import com.android.modules.utils.build.SdkLevel;
29 import com.android.server.wifi.util.ApConfigUtil;
30 import com.android.server.wifi.util.SettingsMigrationDataHolder;
31 import com.android.server.wifi.util.WifiConfigStoreEncryptionUtil;
32 import com.android.server.wifi.util.XmlUtil;
33 
34 import org.xmlpull.v1.XmlPullParser;
35 import org.xmlpull.v1.XmlPullParserException;
36 import org.xmlpull.v1.XmlSerializer;
37 
38 import java.io.IOException;
39 import java.util.ArrayList;
40 import java.util.List;
41 
42 /**
43  * Store data for SoftAp
44  */
45 public class SoftApStoreData implements WifiConfigStore.StoreData {
46     private static final String TAG = "SoftApStoreData";
47     private static final String XML_TAG_SECTION_HEADER_SOFTAP = "SoftAp";
48     private static final String XML_TAG_SSID = "SSID";
49     private static final String XML_TAG_BSSID = "Bssid";
50     private static final String XML_TAG_BAND = "Band";
51     private static final String XML_TAG_CHANNEL = "Channel";
52     private static final String XML_TAG_HIDDEN_SSID = "HiddenSSID";
53     private static final String XML_TAG_SECURITY_TYPE = "SecurityType";
54     private static final String XML_TAG_WPA2_PASSPHRASE = "Wpa2Passphrase";
55     private static final String XML_TAG_AP_BAND = "ApBand";
56     private static final String XML_TAG_PASSPHRASE = "Passphrase";
57     private static final String XML_TAG_MAX_NUMBER_OF_CLIENTS = "MaxNumberOfClients";
58     private static final String XML_TAG_AUTO_SHUTDOWN_ENABLED = "AutoShutdownEnabled";
59     private static final String XML_TAG_SHUTDOWN_TIMEOUT_MILLIS = "ShutdownTimeoutMillis";
60     private static final String XML_TAG_CLIENT_CONTROL_BY_USER = "ClientControlByUser";
61     private static final String XML_TAG_BLOCKED_CLIENT_LIST = "BlockedClientList";
62     private static final String XML_TAG_ALLOWED_CLIENT_LIST = "AllowedClientList";
63     private static final String XML_TAG_BRIDGED_MODE_OPPORTUNISTIC_SHUTDOWN_ENABLED =
64             "BridgedModeOpportunisticShutdownEnabled";
65     private static final String XML_TAG_MAC_RAMDOMIZATION_SETTING = "MacRandomizationSetting";
66     private static final String XML_TAG_BAND_CHANNEL_MAP = "BandChannelMap";
67     private static final String XML_TAG_80211_AX_ENABLED = "80211axEnabled";
68     private static final String XML_TAG_USER_CONFIGURATION = "UserConfiguration";
69 
70 
71     private final Context mContext;
72     private final SettingsMigrationDataHolder mSettingsMigrationDataHolder;
73     private final DataSource mDataSource;
74 
75     /**
76      * Interface define the data source for the notifier store data.
77      */
78     public interface DataSource {
79         /**
80          * Retrieve the SoftAp configuration from the data source to serialize them to disk.
81          *
82          * @return {@link SoftApConfiguration} Instance of SoftApConfiguration.
83          */
toSerialize()84         SoftApConfiguration toSerialize();
85 
86         /**
87          * Set the SoftAp configuration in the data source after serializing them from disk.
88          *
89          * @param config {@link SoftApConfiguration} Instance of SoftApConfiguration.
90          */
fromDeserialized(SoftApConfiguration config)91         void fromDeserialized(SoftApConfiguration config);
92 
93         /**
94          * Clear internal data structure in preparation for user switch or initial store read.
95          */
reset()96         void reset();
97 
98         /**
99          * Indicates whether there is new data to serialize.
100          */
hasNewDataToSerialize()101         boolean hasNewDataToSerialize();
102     }
103 
104     /**
105      * Creates the SSID Set store data.
106      *
107      * @param dataSource The DataSource that implements the update and retrieval of the SSID set.
108      */
SoftApStoreData(Context context, SettingsMigrationDataHolder settingsMigrationDataHolder, DataSource dataSource)109     SoftApStoreData(Context context, SettingsMigrationDataHolder settingsMigrationDataHolder,
110             DataSource dataSource) {
111         mContext = context;
112         mSettingsMigrationDataHolder = settingsMigrationDataHolder;
113         mDataSource = dataSource;
114     }
115 
116     @Override
serializeData(XmlSerializer out, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)117     public void serializeData(XmlSerializer out,
118             @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)
119             throws XmlPullParserException, IOException {
120         SoftApConfiguration softApConfig = mDataSource.toSerialize();
121         if (softApConfig != null) {
122             XmlUtil.writeNextValue(out, XML_TAG_SSID, softApConfig.getSsid());
123             if (softApConfig.getBssid() != null) {
124                 XmlUtil.writeNextValue(out, XML_TAG_BSSID, softApConfig.getBssid().toString());
125             }
126             if (!SdkLevel.isAtLeastS()) {
127                 // Band and channel change to store in Tag:BandChannelMap from S.
128                 XmlUtil.writeNextValue(out, XML_TAG_AP_BAND, softApConfig.getBand());
129                 XmlUtil.writeNextValue(out, XML_TAG_CHANNEL, softApConfig.getChannel());
130             }
131             XmlUtil.writeNextValue(out, XML_TAG_HIDDEN_SSID, softApConfig.isHiddenSsid());
132             XmlUtil.writeNextValue(out, XML_TAG_SECURITY_TYPE, softApConfig.getSecurityType());
133             if (softApConfig.getSecurityType() != SoftApConfiguration.SECURITY_TYPE_OPEN) {
134                 XmlUtil.writeNextValue(out, XML_TAG_PASSPHRASE,
135                         softApConfig.getPassphrase());
136             }
137 
138             XmlUtil.writeNextValue(out, XML_TAG_MAX_NUMBER_OF_CLIENTS,
139                     softApConfig.getMaxNumberOfClients());
140             XmlUtil.writeNextValue(out, XML_TAG_CLIENT_CONTROL_BY_USER,
141                     softApConfig.isClientControlByUserEnabled());
142             XmlUtil.writeNextValue(out, XML_TAG_AUTO_SHUTDOWN_ENABLED,
143                     softApConfig.isAutoShutdownEnabled());
144             XmlUtil.writeNextValue(out, XML_TAG_SHUTDOWN_TIMEOUT_MILLIS,
145                     softApConfig.getShutdownTimeoutMillis());
146             XmlUtil.writeNextSectionStart(out, XML_TAG_BLOCKED_CLIENT_LIST);
147             XmlUtil.SoftApConfigurationXmlUtil.writeClientListToXml(out,
148                     softApConfig.getBlockedClientList());
149             XmlUtil.writeNextSectionEnd(out, XML_TAG_BLOCKED_CLIENT_LIST);
150 
151             XmlUtil.writeNextSectionStart(out, XML_TAG_ALLOWED_CLIENT_LIST);
152             XmlUtil.SoftApConfigurationXmlUtil.writeClientListToXml(out,
153                     softApConfig.getAllowedClientList());
154             XmlUtil.writeNextSectionEnd(out, XML_TAG_ALLOWED_CLIENT_LIST);
155             if (SdkLevel.isAtLeastS()) {
156                 XmlUtil.writeNextValue(out, XML_TAG_BRIDGED_MODE_OPPORTUNISTIC_SHUTDOWN_ENABLED,
157                         softApConfig.isBridgedModeOpportunisticShutdownEnabled());
158                 XmlUtil.writeNextValue(out, XML_TAG_MAC_RAMDOMIZATION_SETTING,
159                         softApConfig.getMacRandomizationSetting());
160 
161                 XmlUtil.writeNextSectionStart(out, XML_TAG_BAND_CHANNEL_MAP);
162                 XmlUtil.SoftApConfigurationXmlUtil.writeChannelsToXml(out,
163                         softApConfig.getChannels());
164                 XmlUtil.writeNextSectionEnd(out, XML_TAG_BAND_CHANNEL_MAP);
165                 XmlUtil.writeNextValue(out, XML_TAG_80211_AX_ENABLED,
166                         softApConfig.isIeee80211axEnabled());
167                 XmlUtil.writeNextValue(out, XML_TAG_USER_CONFIGURATION,
168                         softApConfig.isUserConfiguration());
169             }
170         }
171     }
172 
173     @Override
deserializeData(XmlPullParser in, int outerTagDepth, @WifiConfigStore.Version int version, @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)174     public void deserializeData(XmlPullParser in, int outerTagDepth,
175             @WifiConfigStore.Version int version,
176             @Nullable WifiConfigStoreEncryptionUtil encryptionUtil)
177             throws XmlPullParserException, IOException {
178         // Ignore empty reads.
179         if (in == null) {
180             return;
181         }
182         SoftApConfiguration.Builder softApConfigBuilder = new SoftApConfiguration.Builder();
183         int securityType = SoftApConfiguration.SECURITY_TYPE_OPEN;
184         String passphrase = null;
185         String ssid = null;
186         String bssid = null;
187         // Note that, during deserializaion, we may read the old band encoding (XML_TAG_BAND)
188         // or the new band encoding (XML_TAG_AP_BAND) that is used after the introduction of the
189         // 6GHz band. If the old encoding is found, a conversion is done.
190         int channel = -1;
191         int apBand = -1;
192         boolean hasBandChannelMap = false;
193         List<MacAddress> blockedList = new ArrayList<>();
194         List<MacAddress> allowedList = new ArrayList<>();
195         boolean autoShutdownEnabledTagPresent = false;
196         try {
197             while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) {
198                 if (in.getAttributeValue(null, "name") != null) {
199                     String[] valueName = new String[1];
200                     Object value = XmlUtil.readCurrentValue(in, valueName);
201                     if (TextUtils.isEmpty(valueName[0])) {
202                         throw new XmlPullParserException("Missing value name");
203                     }
204                     switch (valueName[0]) {
205                         case XML_TAG_SSID:
206                             ssid = (String) value;
207                             softApConfigBuilder.setSsid((String) value);
208                             break;
209                         case XML_TAG_BSSID:
210                             bssid = (String) value;
211                             softApConfigBuilder.setBssid(MacAddress.fromString(bssid));
212                             break;
213                         case XML_TAG_BAND:
214                             apBand = ApConfigUtil.convertWifiConfigBandToSoftApConfigBand(
215                                     (int) value);
216                             break;
217                         case XML_TAG_AP_BAND:
218                             apBand = (int) value;
219                             break;
220                         case XML_TAG_CHANNEL:
221                             channel = (int) value;
222                             break;
223                         case XML_TAG_HIDDEN_SSID:
224                             softApConfigBuilder.setHiddenSsid((boolean) value);
225                             break;
226                         case XML_TAG_SECURITY_TYPE:
227                             securityType = (int) value;
228                             break;
229                         case XML_TAG_WPA2_PASSPHRASE:
230                         case XML_TAG_PASSPHRASE:
231                             passphrase = (String) value;
232                             break;
233                         case XML_TAG_MAX_NUMBER_OF_CLIENTS:
234                             softApConfigBuilder.setMaxNumberOfClients((int) value);
235                             break;
236                         case XML_TAG_AUTO_SHUTDOWN_ENABLED:
237                             softApConfigBuilder.setAutoShutdownEnabled((boolean) value);
238                             autoShutdownEnabledTagPresent = true;
239                             break;
240                         case XML_TAG_SHUTDOWN_TIMEOUT_MILLIS:
241                             if (value instanceof Integer) {
242                                 softApConfigBuilder
243                                         .setShutdownTimeoutMillis(Long.valueOf((int) value));
244                             } else if (value instanceof Long) {
245                                 softApConfigBuilder.setShutdownTimeoutMillis((long) value);
246                             }
247                             break;
248                         case XML_TAG_CLIENT_CONTROL_BY_USER:
249                             softApConfigBuilder.setClientControlByUserEnabled((boolean) value);
250                             break;
251                         case XML_TAG_BRIDGED_MODE_OPPORTUNISTIC_SHUTDOWN_ENABLED:
252                             if (SdkLevel.isAtLeastS()) {
253                                 softApConfigBuilder.setBridgedModeOpportunisticShutdownEnabled(
254                                         (boolean) value);
255                             }
256                             break;
257                         case XML_TAG_MAC_RAMDOMIZATION_SETTING:
258                             if (SdkLevel.isAtLeastS()) {
259                                 softApConfigBuilder.setMacRandomizationSetting((int) value);
260                             }
261                             break;
262                         case XML_TAG_80211_AX_ENABLED:
263                             if (SdkLevel.isAtLeastS()) {
264                                 softApConfigBuilder.setIeee80211axEnabled((boolean) value);
265                             }
266                             break;
267                         case XML_TAG_USER_CONFIGURATION:
268                             if (SdkLevel.isAtLeastS()) {
269                                 softApConfigBuilder.setUserConfiguration((boolean) value);
270                             }
271                             break;
272                         default:
273                             Log.w(TAG, "Ignoring unknown value name " + valueName[0]);
274                             break;
275                     }
276                 } else {
277                     String tagName = in.getName();
278                     List<MacAddress> parseredList;
279                     if (tagName == null) {
280                         throw new XmlPullParserException("Unexpected null tag found");
281                     }
282                     switch (tagName) {
283                         case XML_TAG_BLOCKED_CLIENT_LIST:
284                             parseredList =
285                                     XmlUtil.SoftApConfigurationXmlUtil.parseClientListFromXml(
286                                     in, outerTagDepth + 1);
287                             if (parseredList != null) blockedList = new ArrayList<>(parseredList);
288                             break;
289                         case XML_TAG_ALLOWED_CLIENT_LIST:
290                             parseredList =
291                                     XmlUtil.SoftApConfigurationXmlUtil.parseClientListFromXml(
292                                     in, outerTagDepth + 1);
293                             if (parseredList != null) allowedList = new ArrayList<>(parseredList);
294                             break;
295                         case XML_TAG_BAND_CHANNEL_MAP:
296                             if (SdkLevel.isAtLeastS()) {
297                                 hasBandChannelMap = true;
298                                 SparseIntArray channels = XmlUtil.SoftApConfigurationXmlUtil
299                                         .parseChannelsFromXml(in, outerTagDepth + 1);
300                                 softApConfigBuilder.setChannels(channels);
301                             }
302                             break;
303                         default:
304                             Log.w(TAG, "Ignoring unknown tag found: " + tagName);
305                             break;
306                     }
307                 }
308             }
309             softApConfigBuilder.setBlockedClientList(blockedList);
310             softApConfigBuilder.setAllowedClientList(allowedList);
311             if (!hasBandChannelMap) {
312                 // Set channel and band
313                 if (channel == 0) {
314                     softApConfigBuilder.setBand(apBand);
315                 } else {
316                     softApConfigBuilder.setChannel(channel, apBand);
317                 }
318             }
319 
320             // We should at-least have SSID restored from store.
321             if (ssid == null) {
322                 Log.e(TAG, "Failed to parse SSID");
323                 return;
324             }
325             if (securityType != SoftApConfiguration.SECURITY_TYPE_OPEN) {
326                 softApConfigBuilder.setPassphrase(passphrase, securityType);
327             }
328             if (!autoShutdownEnabledTagPresent) {
329                 // Migrate data out of settings.
330                 WifiMigration.SettingsMigrationData migrationData =
331                         mSettingsMigrationDataHolder.retrieveData();
332                 if (migrationData == null) {
333                     Log.e(TAG, "No migration data present");
334                 } else {
335                     softApConfigBuilder.setAutoShutdownEnabled(
336                             migrationData.isSoftApTimeoutEnabled());
337                 }
338             }
339         } catch (IllegalArgumentException e) {
340             Log.e(TAG, "Failed to parse configuration" + e);
341             return;
342         }
343         mDataSource.fromDeserialized(softApConfigBuilder.setSsid(ssid).build());
344     }
345 
346     @Override
resetData()347     public void resetData() {
348         mDataSource.reset();
349     }
350 
351     @Override
hasNewDataToSerialize()352     public boolean hasNewDataToSerialize() {
353         return mDataSource.hasNewDataToSerialize();
354     }
355 
356     @Override
getName()357     public String getName() {
358         return XML_TAG_SECTION_HEADER_SOFTAP;
359     }
360 
361     @Override
getStoreFileId()362     public @WifiConfigStore.StoreFileId int getStoreFileId() {
363         return WifiConfigStore.STORE_FILE_SHARED_SOFTAP; // Shared softap store.
364     }
365 }
366