Android 11 WiFi MAC Randomization

开启未连接

ClientModeImpl

service/java/com/android/server/wifi/ClientModeImpl.java

setupClientMode

复制代码
3637         if (isConnectedMacRandomizationEnabled()) {
3638             mWifiNative.setMacAddress(mInterfaceName, MacAddressUtils.createRandomUnicastAddress());
3639         }

打开WLAN,但不连接,关闭再打开WiFi MAC地址会变。

连接

更新MAC地址

updateWifiConfigOnStartConnection

连接时根据设置里的配置更新MAC地址,"网络详情"-》"高级"-》"隐私",使用随机MAC(默认),使用设备MAC。

Network & internet -》WiFi -》Netowrk details -》Privacy:Use randomized MAC (default)、Use device MAC

复制代码
6378     /**
6379      * Update the wifi configuration before sending connect to
6380      * supplicant/driver.
6381      *
6382      * @param config wifi configuration object.
6383      * @param bssid BSSID to assocaite with.
6384      */
6385     void updateWifiConfigOnStartConnection(WifiConfiguration config, String bssid) {


6470         if (isConnectedMacRandomizationEnabled()) {
6471             if (config.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
6472                 configureRandomizedMacAddress(config);
6473             } else {
6474                 setCurrentMacToFactoryMac(config);
6475             }
6476         }

使用随机MAC(默认)

configureRandomizedMacAddress

配置随机MAC地址。

复制代码
3301      * Dynamically change the MAC address to use the locally randomized
3302      * MAC address generated for each network.
3303      * @param config WifiConfiguration with mRandomizedMacAddress to change into. If the address
3304      * is masked out or not set, it will generate a new random MAC address.
3305      */
3306     private void configureRandomizedMacAddress(WifiConfiguration config) {
3307         if (config == null) {
3308             Log.e(TAG, "No config to change MAC address to");
3309             return;
3310         }
3311         String currentMacString = mWifiNative.getMacAddress(mInterfaceName);
3312         MacAddress currentMac = currentMacString == null ? null :
3313                 MacAddress.fromString(currentMacString);
3314         MacAddress newMac = mWifiConfigManager.getRandomizedMacAndUpdateIfNeeded(config);
3315         if (!WifiConfiguration.isValidMacAddressForRandomization(newMac)) {
3316             Log.wtf(TAG, "Config generated an invalid MAC address");
3317         } else if (newMac.equals(currentMac)) {
3318             Log.d(TAG, "No changes in MAC address");
3319         } else {
3320             mWifiMetrics.logStaEvent(StaEvent.TYPE_MAC_CHANGE, config);
3321             boolean setMacSuccess =
3322                     mWifiNative.setMacAddress(mInterfaceName, newMac);
3323             if (setMacSuccess) {
3324                 mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, newMac);
3325             }
3326             Log.d(TAG, "ConnectedMacRandomization SSID(" + config.getPrintableSsid()
3327                     + "). setMacAddress(" + newMac.toString() + ") from "
3328                     + currentMacString + " = " + setMacSuccess);
3329         }
3330     }
获取随机MAC地址

getRandomizedMacAndUpdateIfNeeded

enhanced_mac_randomization_force_enabled=1按需更新MAC地址。

复制代码
 573     /**
 574      * Returns the randomized MAC address that should be used for this WifiConfiguration.
 575      * This API may return a randomized MAC different from the persistent randomized MAC if
 576      * the WifiConfiguration is configured for aggressive MAC randomization.
 577      * @param config
 578      * @return MacAddress
 579      */
 580     public MacAddress getRandomizedMacAndUpdateIfNeeded(WifiConfiguration config) {
 581         MacAddress mac = shouldUseAggressiveRandomization(config)
 582                 ? updateRandomizedMacIfNeeded(config)
 583                 : setRandomizedMacToPersistentMac(config);
 584         return mac;
 585     }
保存随机MAC地址

setRandomizedMacToPersistentMac

用HMAC-SHA256计算MAC地址,并保存

复制代码
 537     /**
 538      * Obtain the persistent MAC address by first reading from an internal database. If non exists
 539      * then calculate the persistent MAC using HMAC-SHA256.
 540      * Finally set the randomized MAC of the configuration to the randomized MAC obtained.
 541      * @param config the WifiConfiguration to make the update
 542      * @return the persistent MacAddress or null if the operation is unsuccessful
 543      */
 544     private MacAddress setRandomizedMacToPersistentMac(WifiConfiguration config) {
 545         MacAddress persistentMac = getPersistentMacAddress(config);
 546         if (persistentMac == null || persistentMac.equals(config.getRandomizedMacAddress())) {
 547             return persistentMac;
 548         }
 549         WifiConfiguration internalConfig = getInternalConfiguredNetwork(config.networkId);
 550         internalConfig.setRandomizedMacAddress(persistentMac);
 551         return persistentMac;
 552     }
生成随机MAC地址

会保存生成的随机MAC地址直到恢复出厂设置。

复制代码
 470     /**
 471      * The persistent randomized MAC address is locally generated for each SSID and does not
 472      * change until factory reset of the device. In the initial Q release the per-SSID randomized
 473      * MAC is saved on the device, but in an update the storing of randomized MAC is removed.
 474      * Instead, the randomized MAC is calculated directly from the SSID and a on device secret.
 475      * For backward compatibility, this method first checks the device storage for saved
 476      * randomized MAC. If it is not found or the saved MAC is invalid then it will calculate the
 477      * randomized MAC directly.
 478      *
 479      * In the future as devices launched on Q no longer get supported, this method should get
 480      * simplified to return the calculated MAC address directly.
 481      * @param config the WifiConfiguration to obtain MAC address for.
 482      * @return persistent MAC address for this WifiConfiguration
 483      */
 484     private MacAddress getPersistentMacAddress(WifiConfiguration config) {

使用设备MAC

setCurrentMacToFactoryMac

设置为厂家提供MAC地址。

复制代码
3332     /**
3333      * Sets the current MAC to the factory MAC address.
3334      */
3335     private void setCurrentMacToFactoryMac(WifiConfiguration config) {
3336         MacAddress factoryMac = mWifiNative.getFactoryMacAddress(mInterfaceName);
3337         if (factoryMac == null) {
3338             Log.e(TAG, "Fail to set factory MAC address. Factory MAC is null.");
3339             return;
3340         }
3341         String currentMacStr = mWifiNative.getMacAddress(mInterfaceName);
3342         if (!TextUtils.equals(currentMacStr, factoryMac.toString())) {
3343             if (mWifiNative.setMacAddress(mInterfaceName, factoryMac)) {
3344                 mWifiNative.removeNetworkCachedDataIfNeeded(config.networkId, factoryMac);
3345                 mWifiMetrics.logStaEvent(StaEvent.TYPE_MAC_CHANGE, config);
3346             } else {
3347                 Log.e(TAG, "Failed to set MAC address to " + "'" + factoryMac.toString() + "'");
3348             }
3349         }
3350     }

MacAddressUtil

service/java/com/android/server/wifi/MacAddressUtil.java

获取hash函数

复制代码
100     private Mac obtainMacRandHashFunctionInternal(int uid, String alias) {
101         try {
102             KeyStore keyStore = AndroidKeyStoreProvider.getKeyStoreForUid(uid);
103             // tries to retrieve the secret, and generate a new one if it's unavailable.
104             Key key = keyStore.getKey(alias, null);
105             if (key == null) {
106                 key = generateAndPersistNewMacRandomizationSecret(uid, alias);
107             }
108             if (key == null) {
109                 Log.e(TAG, "Failed to generate secret for " + alias);
110                 return null;
111             }
112             Mac result = Mac.getInstance("HmacSHA256");
113             result.init(key);
114             return result;
115         } catch (KeyStoreException | NoSuchAlgorithmException | InvalidKeyException
116                 | UnrecoverableKeyException | NoSuchProviderException e) {
117             Log.e(TAG, "Failure in obtainMacRandHashFunction", e);
118             return null;
119         }
120     }

计算MAC地址

calculatePersistentMac根据key hash函数计算MAC地址。

加调试日志

复制代码
--- a/service/java/com/android/server/wifi/MacAddressUtil.java
+++ b/service/java/com/android/server/wifi/MacAddressUtil.java
@@ -50,6 +50,15 @@ public class MacAddressUtil {
     private static final long MAC_ADDRESS_LOCALLY_ASSIGNED_MASK = 1L << 41;
     private static final long MAC_ADDRESS_MULTICAST_MASK = 1L << 40;

+       private static String bytesToHex(byte[] bytes) {
+        StringBuilder hexString = new StringBuilder();
+        for (byte b : bytes) {
+            String hex = String.format("%02X", b);
+            hexString.append(hex);
+        }
+        return hexString.toString();
+    }
+
     /**
      * Computes the persistent randomized MAC using the given key and hash function.
      * @param key the key to compute MAC address for
@@ -82,6 +91,8 @@ public class MacAddressUtil {
         // MacAddress.fromBytes requires input of length 6, which is obtained from the
         // last 6 bytes from the generated long.
         MacAddress macAddress = MacAddress.fromBytes(Arrays.copyOfRange(bf.array(), 2, 8));
+               String hashStr = bytesToHex(hashedBytes);
+               Log.i(TAG, "key:" + key + ",hash:" + hashStr + "," + macAddress);
         return macAddress;
     }

配置

config.xml

frameworks/opt/net/wifi/service/res/values/config.xml

config_wifi_connected_mac_randomization_supported

复制代码
244     <!-- Indicates that connected MAC randomization is supported on this device -->
245     <bool translatable="false" name="config_wifi_connected_mac_randomization_supported">true</bool>
246
247     <!-- Indicates that p2p MAC randomization is supported on this device -->
248     <bool translatable="false" name="config_wifi_p2p_mac_randomization_supported">true</bool>
249
250     <!-- Indicates that AP mode MAC randomization is supported on this device -->
251     <bool translatable="false" name="config_wifi_ap_mac_randomization_supported">false</bool>
252
253     <!-- list of SSIDs to enable aggressive MAC randomization on -->
254     <string-array translatable="false" name="config_wifi_aggressive_randomization_ssid_allowlist">
255         <!-- SSIDs are expected in quoted format:
256         <item>\"SSID_1\"</item>
257         <item>\"SSID_2\"</item>
258         -->
259     </string-array>
260
261     <!-- list of SSIDs to disable aggressive MAC randomization on. If a SSID is in both the
262     allowlist and blocklist, then aggressive MAC randomization will still be disabled. -->
263     <string-array translatable="false" name="config_wifi_aggressive_randomization_ssid_blocklist">
264         <!-- SSIDs are expected in quoted format:
265         <item>\"SSID_1\"</item>
266         <item>\"SSID_2\"</item>
267         -->
268     </string-array>

随机MAC地址设置

配置创建

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiConfigManager.java

复制代码
 633     /**
 634      * Helper method to create a copy of the provided internal WifiConfiguration object to be
 635      * passed to external modules.
 636      *
 637      * @param configuration provided WifiConfiguration object.
 638      * @param maskPasswords Mask passwords or not.
 639      * @param targetUid Target UID for MAC address reading: -1 = mask all, 0 = mask none, >0 =
 640      *                  mask all but the targetUid (carrier app).
 641      * @return Copy of the WifiConfiguration object.
 642      */
 643     private WifiConfiguration createExternalWifiConfiguration(
 644             WifiConfiguration configuration, boolean maskPasswords, int targetUid) {
 645         WifiConfiguration network = new WifiConfiguration(configuration);
 646         if (maskPasswords) {
 647             maskPasswordsInWifiConfiguration(network);
 648         }
 649         if (targetUid != Process.WIFI_UID && targetUid != Process.SYSTEM_UID
 650                 && targetUid != configuration.creatorUid) {
 651             maskRandomizedMacAddressInWifiConfiguration(network);
 652         }
 653         if (!isMacRandomizationSupported()) {
 654             network.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
 655         }
 656         return network;
 657     }

默认值修改

WifiConfiguration

修改frameworks/base/wifi/java/android/net/wifi/WifiConfiguration.java无效。

复制代码
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1154,7 +1154,7 @@ public class WifiConfiguration implements Parcelable {
      */
     @SystemApi
     @MacRandomizationSetting
-    public int macRandomizationSetting = RANDOMIZATION_PERSISTENT;
+    public int macRandomizationSetting = RANDOMIZATION_NONE;

     /**
      * @hide
PasspointProvider

也不是

frameworks/opt/net/wifi/service/java/com/android/server/wifi/hotspot2/PasspointProvider.java

复制代码
 451     /**
 452      * Generate a WifiConfiguration based on the provider's configuration.  The generated
 453      * WifiConfiguration will include all the necessary credentials for network connection except
 454      * the SSID, which should be added by the caller when the config is being used for network
 455      * connection.
 456      *
 457      * @return {@link WifiConfiguration}
 458      */
 459     public WifiConfiguration getWifiConfig() {
 460         WifiConfiguration wifiConfig = new WifiConfiguration();
 461         wifiConfig.FQDN = mConfig.getHomeSp().getFqdn();
 462         wifiConfig.setPasspointUniqueId(mConfig.getUniqueId());
 463         if (mConfig.getHomeSp().getRoamingConsortiumOis() != null) {
 464             wifiConfig.roamingConsortiumIds = Arrays.copyOf(
 465                     mConfig.getHomeSp().getRoamingConsortiumOis(),
 466                     mConfig.getHomeSp().getRoamingConsortiumOis().length);
 467         }
 ...
 525         if (mConfig.isMacRandomizationEnabled()) {
 526             wifiConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
 527         } else {
 528             wifiConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
 529         }
MtkSettings
WifiPrivacyPreferenceController

不是

复制代码
--- a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
@@ -115,7 +115,7 @@ public class WifiPrivacyPreferenceController extends BasePreferenceController im
         if (mWifiConfiguration != null) {
             return mWifiConfiguration.macRandomizationSetting;
         }
-        return WifiConfiguration.RANDOMIZATION_PERSISTENT;
+        return WifiConfiguration.RANDOMIZATION_NONE;
     }

     private static final int PREF_RANDOMIZATION_PERSISTENT = 0;

src/com/android/settings/wifi/WifiConfigController2.java

initWifiConfigController2

修改PrivacySettingsSpinner,默认选择"使用设备MAC"。

复制代码
--- a/src/com/android/settings/wifi/WifiConfigController2.java
+++ b/src/com/android/settings/wifi/WifiConfigController2.java
@@ -288,6 +288,9 @@ public class WifiConfigController2 implements TextWatcher,
             ViewGroup group = (ViewGroup) mView.findViewById(R.id.info);

             boolean showAdvancedFields = false;
+            if (!mWifiEntry.isSaved()) {
+                mPrivacySettingsSpinner.setSelection(1);
+            }
             if (mWifiEntry.isSaved()) {
                 WifiConfiguration config = mWifiEntry.getWifiConfiguration();
                 mMeteredSettingsSpinner.setSelection(config.meteredOverride);
getConfig

点击连接时,会获取PrivacySettingsSpinner的选择,保存到配置中。

复制代码
 839         if (mPrivacySettingsSpinner != null) {
 840             int macValue;
 841             if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_WIFITRACKER2)) {
 842                 macValue = WifiPrivacyPreferenceController2.translatePrefValueToMacRandomizedValue(
 843                         mPrivacySettingsSpinner.getSelectedItemPosition());
 844             } else {
 845                 macValue = WifiPrivacyPreferenceController.translatePrefValueToMacRandomizedValue(
 846                         mPrivacySettingsSpinner.getSelectedItemPosition());
 847             }
 848             config.macRandomizationSetting = macValue;
 849         }
相关推荐
幻雨様1 小时前
UE5多人MOBA+GAS 45、制作冲刺技能
android·ue5
Jerry说前后端3 小时前
Android 数据可视化开发:从技术选型到性能优化
android·信息可视化·性能优化
Meteors.4 小时前
Android约束布局(ConstraintLayout)常用属性
android
alexhilton5 小时前
玩转Shader之学会如何变形画布
android·kotlin·android jetpack
whysqwhw9 小时前
安卓图片性能优化技巧
android
风往哪边走9 小时前
自定义底部筛选弹框
android
Yyyy48210 小时前
MyCAT基础概念
android
Android轮子哥10 小时前
尝试解决 Android 适配最后一公里
android
雨白11 小时前
OkHttp 源码解析:enqueue 非同步流程与 Dispatcher 调度
android
风往哪边走12 小时前
自定义仿日历组件弹框
android