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