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 小时前
【Android】使用TextView实现按钮开关代替Switch开关
android
江-月*夜4 小时前
uniapp vuex 搭建
android·javascript·uni-app
大风起兮云飞扬丶5 小时前
Android——显式/隐式Intent
android
大风起兮云飞扬丶5 小时前
Android——metaData
android
看山还是山,看水还是。5 小时前
Nginx 的 Http 模块介绍(中)
android·运维·网络·nginx·http
SouthBay4938 小时前
PHP内存马:不死马
android·开发语言·php
安於宿命8 小时前
【Linux内核揭秘】深入理解命令行参数和环境变量
android·linux·服务器
Gerry_Liang9 小时前
Android Studio 无法查看Kotlin源码的解决办法
android·kotlin·android studio
IT生活课堂10 小时前
唤醒车机时娱乐屏出现黑屏,卡顿的案例分享
android·智能手机·汽车
翔云API11 小时前
PC端增值税发票识别API-翔云智能财务发票识别OCR接口
android·c语言·开发语言·php