Android 12.0 WiFi连接流程分析之IP地址分配流程

1.前言

在12.0的系统rom定制化开发中,对于wifi的定制功能也是比较多的,在关于wifi连接流程模块的 分析,了解整个wifi连接流程也是非常重要的,接下来看下wifi的连接流程分析下相关功能实现

2.WiFi连接流程分析之IP地址分配流程的核心类

frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeImpl.java
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiMonitor.java
frameworks\opt\net\wifi\service\java\com\android\server\wifi\SupplicantStaIfaceCallbackImpl.java

3.WiFi连接流程分析之IP地址分配流程的核心功能分析和实现

ClientModeImpl 是ClientMode的状态机,是用于控制WiFi 连接,获取IP ,设置网络配置。 ClientModeImpl是Android Wi-Fi的大管家,处理大量的客户端事件,用来管理Wi-Fi驱动连接、断开、获取IP、漫游等各个状态,在Android老版本中,其被命名为 WifiStateMachine,ClientModeImpl ClientModeImpl是一个实现了Wi-Fi多重模式操作的类,它是Android操作系统中用于管理 Wi-Fi连接的一部分。它主要负责在客户端模式下管理Wi-Fi连接,并且可以帮助设备自动 连接到可用的Wi-Fi网络。

3.1ClientModeImpl关于wifi连接的相关流程分析

ClientModeImpl 是ClientMode的状态机,是用于控制WiFi 连接,获取IP ,设置网络配置。上一篇我们说到启动后,发送消息使得ClientModeImpl 状态机切换到DisconnectedState 状态;调用DisconnectedState enter 方法;enter主要是调用 WifiConnectivityManager 的handleConnectionStateChanged 方法处理WiFi 网络状态的改变。

    private boolean startIpClient(WifiConfiguration config, boolean isFilsConnection) {
        if (mIpClient == null) {
            return false;
        }
 
        final boolean isUsingStaticIp =
                (config.getIpAssignment() == IpConfiguration.IpAssignment.STATIC);
        final boolean isUsingMacRandomization =
                config.macRandomizationSetting
                        == WifiConfiguration.RANDOMIZATION_PERSISTENT
                        && isConnectedMacRandomizationEnabled();
        if (mVerboseLoggingEnabled) {
            final String key = config.getKey();
            log("startIpClient netId=" + Integer.toString(mLastNetworkId)
                    + " " + key + " "
                    + " roam=" + mIsAutoRoaming
                    + " static=" + isUsingStaticIp
                    + " randomMac=" + isUsingMacRandomization
                    + " isFilsConnection=" + isFilsConnection);
        }
 
        final MacAddress currentBssid = getCurrentBssid();
        final String l2Key = mLastL2KeyAndGroupHint != null
                ? mLastL2KeyAndGroupHint.first : null;
        final String groupHint = mLastL2KeyAndGroupHint != null
                ? mLastL2KeyAndGroupHint.second : null;
        final Layer2Information layer2Info = new Layer2Information(l2Key, groupHint,
                currentBssid);
.....
 
            if (!isUsingStaticIp) {
                prov = new ProvisioningConfiguration.Builder()
                    .withPreDhcpAction()
                    .withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName))
                    .withNetwork(getCurrentNetwork())
                    .withDisplayName(config.SSID)
                    .withScanResultInfo(scanResultInfo)
                    .withLayer2Information(layer2Info);
            } else {
                StaticIpConfiguration staticIpConfig = config.getStaticIpConfiguration();
                prov = new ProvisioningConfiguration.Builder()
                        .withStaticConfiguration(staticIpConfig)
                        .withApfCapabilities(mWifiNative.getApfCapabilities(mInterfaceName))
                        .withNetwork(getCurrentNetwork())
                        .withDisplayName(config.SSID)
                        .withLayer2Information(layer2Info);
            }
            if (isUsingMacRandomization) {
                // Use EUI64 address generation for link-local IPv6 addresses.
                prov.withRandomMacAddress();
            }
            mIpClient.startProvisioning(prov.build());
        }
 
        return true;
    }

在ClientModeImpl中有一个函数startIpClient。这个函数会在俩个地方被调用,一个是连接 的时候ConnectModeState,一个是连接成功以后进入ObtainingIpState。这俩个地方的区 别就是isFilsConnection的不同,连接过程中isFilsConnection为true,把IPClinet先关掉。 如果isFilsConnection为flase,则开始处理IP地址分配。 SupplicantStaIfaceCallbackImpl.java中注册了一个Supplicant的回调函数,当supplicant的状态发生改变时这里就会监听到,然后WifiMonitor就会发送statechange的广播

    @Override
    public void onStateChanged(int newState, byte[/* 6 */] bssid, int id,
                               ArrayList ssid) {
        synchronized (mLock) {
            mStaIfaceHal.logCallback("onStateChanged");
            SupplicantState newSupplicantState =
                    supplicantHidlStateToFrameworkState(newState);
            WifiSsid wifiSsid =
                    WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(ssid));
            String bssidStr = NativeUtil.macAddressFromByteArray(bssid);
            mStateIsFourway = (newState == ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE);
            if (newSupplicantState == SupplicantState.COMPLETED) {
                mWifiMonitor.broadcastNetworkConnectionEvent(
                        mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), bssidStr);
            }
            mWifiMonitor.broadcastSupplicantStateChangeEvent(
                    mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), wifiSsid,
                    bssidStr, newSupplicantState);
        }
    }
public void broadcastNetworkConnectionEvent(String iface, int networkId, boolean filsHlpSent,
        String bssid) {
    sendMessage(iface, NETWORK_CONNECTION_EVENT, networkId, filsHlpSent ? 1 : 0, bssid);
}

在SupplicantStaIfaceCallbackImpl.java中的onStateChanged方法中,监听wifi的状态改变以后 就会调用WifiMonitor.java的broadcastNetworkConnectionEvent通过发送NETWORK_CONNECTION_EVENT 消息来继续wifi连接流程,然后在ClientModeImpl.java中继续处理wifi连接流程

               case WifiMonitor.NETWORK_CONNECTION_EVENT:
                    if (mVerboseLoggingEnabled) log("Network connection established");
                    mLastNetworkId = message.arg1;
                    mWifiConfigManager.clearRecentFailureReason(mLastNetworkId);
                    mLastBssid = (String) message.obj;
                    reasonCode = message.arg2;
                    config = getCurrentWifiConfiguration();
                    if (config != null) {
                        mWifiInfo.setBSSID(mLastBssid);
                        mWifiInfo.setNetworkId(mLastNetworkId);
                        mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName));
 
                        ScanDetailCache scanDetailCache =
                                mWifiConfigManager.getScanDetailCacheForNetwork(config.networkId);
                        if (scanDetailCache != null && mLastBssid != null) {
                            ScanResult scanResult = scanDetailCache.getScanResult(mLastBssid);
                            if (scanResult != null) {
                                mWifiInfo.setFrequency(scanResult.frequency);
                            }
                        }
 
                        // We need to get the updated pseudonym from supplicant for EAP-SIM/AKA/AKA'
                        if (config.enterpriseConfig != null
                                && config.enterpriseConfig.isAuthenticationSimBased()) {
                            mLastSubId = mWifiCarrierInfoManager.getBestMatchSubscriptionId(config);
                            mLastSimBasedConnectionCarrierName =
                                mWifiCarrierInfoManager.getCarrierNameforSubId(mLastSubId);
                            String anonymousIdentity =
                                    mWifiNative.getEapAnonymousIdentity(mInterfaceName);
                            if (!TextUtils.isEmpty(anonymousIdentity)
                                    && !WifiCarrierInfoManager
                                    .isAnonymousAtRealmIdentity(anonymousIdentity)) {
                                String decoratedPseudonym = mWifiCarrierInfoManager
                                        .decoratePseudonymWith3GppRealm(config,
                                                anonymousIdentity);
                                if (decoratedPseudonym != null) {
                                    anonymousIdentity = decoratedPseudonym;
                                }
                                if (mVerboseLoggingEnabled) {
                                    log("EAP Pseudonym: " + anonymousIdentity);
                                }
                                // Save the pseudonym only if it is a real one
                                config.enterpriseConfig.setAnonymousIdentity(anonymousIdentity);
                            } else {
                                // Clear any stored pseudonyms
                                config.enterpriseConfig.setAnonymousIdentity(null);
                            }
                            mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID);
                        }
                        transitionTo(mObtainingIpState);
                    } else {
                        logw("Connected to unknown networkId " + mLastNetworkId
                                + ", disconnecting...");
                        sendMessage(CMD_DISCONNECT);
                    }
                    break;

在ClientModeImpl.java中继续处理wifi连接流程中,当收到WifiMonitor.NETWORK_CONNECTION_EVENT 连接wifi的事件以后,就开启连接当前wifi的工作流程,具体主要是通过 mWifiConfigManager.addOrUpdateNetwork(config, Process.WIFI_UID);来处理连接wifi的 具体工作

你可能感兴趣的:(android,12.0,Rom开发疑难问题分析,android,tcp/ip,wifi连接,ip地址,分配ip)