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