在12.0的系统rom定制化开发中,对于wifi的定制功能也是比较多的,在关于wifi连接流程模块的 分析,了解整个wifi连接流程也是非常重要的,接下来看下wifi的连接流程分析下相关功能实现
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
ClientModeImpl 是ClientMode的状态机,是用于控制WiFi 连接,获取IP ,设置网络配置。 ClientModeImpl是Android Wi-Fi的大管家,处理大量的客户端事件,用来管理Wi-Fi驱动连接、断开、获取IP、漫游等各个状态,在Android老版本中,其被命名为 WifiStateMachine,ClientModeImpl ClientModeImpl是一个实现了Wi-Fi多重模式操作的类,它是Android操作系统中用于管理 Wi-Fi连接的一部分。它主要负责在客户端模式下管理Wi-Fi连接,并且可以帮助设备自动 连接到可用的Wi-Fi网络。
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的 具体工作