diff options
Diffstat (limited to 'service')
3 files changed, 169 insertions, 7 deletions
diff --git a/service/java/com/android/server/wifi/RandomizedMacStoreData.java b/service/java/com/android/server/wifi/RandomizedMacStoreData.java new file mode 100644 index 000000000..1e4d972ef --- /dev/null +++ b/service/java/com/android/server/wifi/RandomizedMacStoreData.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wifi; + +import com.android.server.wifi.util.XmlUtil; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * This class performs serialization and parsing of XML data block that contain the mapping + * from configKey to randomized MAC address + * (XML block data inside <MacAddressMappingList> tag). + */ +public class RandomizedMacStoreData implements WifiConfigStore.StoreData { + private static final String XML_TAG_SECTION_HEADER_MAC_ADDRESS_MAP = "MacAddressMap"; + private static final String XML_TAG_MAC_MAP = "MacMapEntry"; + + private Map<String, String> mMacMapping; + + RandomizedMacStoreData() {} + + @Override + public void serializeData(XmlSerializer out) + throws XmlPullParserException, IOException { + if (mMacMapping != null) { + XmlUtil.writeNextValue(out, XML_TAG_MAC_MAP, mMacMapping); + } + } + + @Override + public void deserializeData(XmlPullParser in, int outerTagDepth) + throws XmlPullParserException, IOException { + // Ignore empty reads. + if (in == null) { + return; + } + while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { + String[] valueName = new String[1]; + Object value = XmlUtil.readCurrentValue(in, valueName); + if (valueName[0] == null) { + throw new XmlPullParserException("Missing value name"); + } + switch (valueName[0]) { + case XML_TAG_MAC_MAP: + mMacMapping = (Map<String, String>) value; + break; + default: + throw new XmlPullParserException("Unknown tag under " + + XML_TAG_SECTION_HEADER_MAC_ADDRESS_MAP + + ": " + valueName[0]); + } + } + } + + @Override + public void resetData() { + mMacMapping = null; + } + + @Override + public boolean hasNewDataToSerialize() { + // always persist. + return true; + } + + @Override + public String getName() { + return XML_TAG_SECTION_HEADER_MAC_ADDRESS_MAP; + } + + @Override + public @WifiConfigStore.StoreFileId int getStoreFileId() { + // Shared general store. + return WifiConfigStore.STORE_FILE_SHARED_GENERAL; + } + + /** + * An empty Map will be returned for null MAC address map. + * + * @return Map of mapping from configKey to the randomized MAC address. + */ + public Map<String, String> getMacMapping() { + if (mMacMapping == null) { + return new HashMap<String, String>(); + } + return mMacMapping; + } + + /** + * Sets the data to be stored to file. + * @param macMapping + */ + public void setMacMapping(Map<String, String> macMapping) { + mMacMapping = macMapping; + } +} + diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java index a17c8c908..bd5ffe905 100644 --- a/service/java/com/android/server/wifi/WifiConfigManager.java +++ b/service/java/com/android/server/wifi/WifiConfigManager.java @@ -283,6 +283,14 @@ public class WifiConfigManager { * The SSIDs are encoded in a String as per definition of WifiConfiguration.SSID field. */ private final Set<String> mDeletedEphemeralSSIDs; + + /** + * Framework keeps a mapping from configKey to the randomized MAC address so that + * when a user forgets a network and thne adds it back, the same randomized MAC address + * will get used. + */ + private final Map<String, String> mRandomizedMacAddressMapping; + /** * Flag to indicate if only networks with the same psk should be linked. * TODO(b/30706406): Remove this flag if unused. @@ -348,6 +356,7 @@ public class WifiConfigManager { private final NetworkListSharedStoreData mNetworkListSharedStoreData; private final NetworkListUserStoreData mNetworkListUserStoreData; private final DeletedEphemeralSsidsStoreData mDeletedEphemeralSsidsStoreData; + private final RandomizedMacStoreData mRandomizedMacStoreData; // Store the saved network update listener. private OnSavedNetworkUpdateListener mListener = null; @@ -369,6 +378,7 @@ public class WifiConfigManager { NetworkListSharedStoreData networkListSharedStoreData, NetworkListUserStoreData networkListUserStoreData, DeletedEphemeralSsidsStoreData deletedEphemeralSsidsStoreData, + RandomizedMacStoreData randomizedMacStoreData, FrameworkFacade frameworkFacade, Looper looper) { mContext = context; mClock = clock; @@ -384,14 +394,17 @@ public class WifiConfigManager { mConfiguredNetworks = new ConfigurationMap(userManager); mScanDetailCaches = new HashMap<>(16, 0.75f); mDeletedEphemeralSSIDs = new HashSet<>(); + mRandomizedMacAddressMapping = new HashMap<>(); // Register store data for network list and deleted ephemeral SSIDs. mNetworkListSharedStoreData = networkListSharedStoreData; mNetworkListUserStoreData = networkListUserStoreData; mDeletedEphemeralSsidsStoreData = deletedEphemeralSsidsStoreData; + mRandomizedMacStoreData = randomizedMacStoreData; mWifiConfigStore.registerStoreData(mNetworkListSharedStoreData); mWifiConfigStore.registerStoreData(mNetworkListUserStoreData); mWifiConfigStore.registerStoreData(mDeletedEphemeralSsidsStoreData); + mWifiConfigStore.registerStoreData(mRandomizedMacStoreData); mOnlyLinkSameCredentialConfigurations = mContext.getResources().getBoolean( R.bool.config_wifi_only_link_same_credential_configurations); @@ -1025,11 +1038,37 @@ public class WifiConfigManager { mContext.getPackageManager().getNameForUid(uid); newInternalConfig.creationTime = newInternalConfig.updateTime = createDebugTimeStampString(mClock.getWallClockMillis()); + updateRandomizedMacAddress(newInternalConfig); return newInternalConfig; } /** + * Sets the randomized address for the given configuration from stored map if it exist. + * Otherwise generates a new randomized address and save to the stored map. + * @param config + */ + private void updateRandomizedMacAddress(WifiConfiguration config) { + // Update randomized MAC address according to stored map + final String key = config.configKey(); + // If the key is not found in the current store, then it means this network has never been + // seen before. So add it to store. + if (!mRandomizedMacAddressMapping.containsKey(key)) { + mRandomizedMacAddressMapping.put(key, + config.getOrCreateRandomizedMacAddress().toString()); + } else { // Otherwise read from the store and set the WifiConfiguration + try { + config.setRandomizedMacAddress( + MacAddress.fromString(mRandomizedMacAddressMapping.get(key))); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Error creating randomized MAC address from stored value."); + mRandomizedMacAddressMapping.put(key, + config.getOrCreateRandomizedMacAddress().toString()); + } + } + } + + /** * Create a new internal WifiConfiguration object by copying over parameters from the provided * external configuration to a copy of the existing internal WifiConfiguration object. * @@ -2818,6 +2857,7 @@ public class WifiConfigManager { localLog("clearInternalData: Clearing all internal data"); mConfiguredNetworks.clear(); mDeletedEphemeralSSIDs.clear(); + mRandomizedMacAddressMapping.clear(); mScanDetailCaches.clear(); clearLastSelectedNetwork(); } @@ -2860,7 +2900,8 @@ public class WifiConfigManager { * @param configurations list of configurations retrieved from store. */ private void loadInternalDataFromSharedStore( - List<WifiConfiguration> configurations) { + List<WifiConfiguration> configurations, + Map<String, String> macAddressMapping) { for (WifiConfiguration configuration : configurations) { configuration.networkId = mNextNetworkId++; if (mVerboseLoggingEnabled) { @@ -2872,6 +2913,7 @@ public class WifiConfigManager { Log.e(TAG, "Failed to add network to config map", e); } } + mRandomizedMacAddressMapping.putAll(macAddressMapping); } /** @@ -2914,11 +2956,12 @@ public class WifiConfigManager { */ private void loadInternalData( List<WifiConfiguration> sharedConfigurations, - List<WifiConfiguration> userConfigurations, Set<String> deletedEphemeralSSIDs) { + List<WifiConfiguration> userConfigurations, Set<String> deletedEphemeralSSIDs, + Map<String, String> macAddressMapping) { // Clear out all the existing in-memory lists and load the lists from what was retrieved // from the config store. clearInternalData(); - loadInternalDataFromSharedStore(sharedConfigurations); + loadInternalDataFromSharedStore(sharedConfigurations, macAddressMapping); loadInternalDataFromUserStore(userConfigurations, deletedEphemeralSSIDs); if (mConfiguredNetworks.sizeForAllUsers() == 0) { Log.w(TAG, "No stored networks found."); @@ -2952,7 +2995,7 @@ public class WifiConfigManager { WifiConfigStoreDataLegacy storeData = mWifiConfigStoreLegacy.read(); Log.d(TAG, "Reading from legacy store completed"); loadInternalData(storeData.getConfigurations(), new ArrayList<WifiConfiguration>(), - storeData.getDeletedEphemeralSSIDs()); + storeData.getDeletedEphemeralSSIDs(), mRandomizedMacStoreData.getMacMapping()); // Setup user store for the current user in case it have not setup yet, so that data // owned by the current user will be backed to the user store. @@ -3003,7 +3046,8 @@ public class WifiConfigManager { } loadInternalData(mNetworkListSharedStoreData.getConfigurations(), mNetworkListUserStoreData.getConfigurations(), - mDeletedEphemeralSsidsStoreData.getSsidList()); + mDeletedEphemeralSsidsStoreData.getSsidList(), + mRandomizedMacStoreData.getMacMapping()); return true; } @@ -3093,6 +3137,7 @@ public class WifiConfigManager { mNetworkListSharedStoreData.setConfigurations(sharedConfigurations); mNetworkListUserStoreData.setConfigurations(userConfigurations); mDeletedEphemeralSsidsStoreData.setSsidList(mDeletedEphemeralSSIDs); + mRandomizedMacStoreData.setMacMapping(mRandomizedMacAddressMapping); try { mWifiConfigStore.write(forceWrite); diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index 2954608ee..40737861b 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -241,8 +241,8 @@ public class WifiInjector { mWifiKeyStore, mWifiConfigStore, mWifiConfigStoreLegacy, mWifiPermissionsUtil, mWifiPermissionsWrapper, new NetworkListSharedStoreData(mContext), new NetworkListUserStoreData(mContext), - new DeletedEphemeralSsidsStoreData(), mFrameworkFacade, - mWifiCoreHandlerThread.getLooper()); + new DeletedEphemeralSsidsStoreData(), new RandomizedMacStoreData(), + mFrameworkFacade, mWifiCoreHandlerThread.getLooper()); mWifiScoreCard = new WifiScoreCard(mClock, "TODO(b/112196799) seed me properly"); mWifiMetrics.setWifiConfigManager(mWifiConfigManager); mWifiConnectivityHelper = new WifiConnectivityHelper(mWifiNative); |