Wifi连接流程

Wifi连接一个ap一般有两种方式:长按一个网络然后弹出一个菜单,选择连接网络(或者对于已经保存网络也是单击弹出菜单点击连接menu);另一种点击一个网络,然后弹出一个Dialog,输入密码再进行连接。两种方式的连接在底层并无区别,但是在应用层的逻辑略有不同。
首先我们先来罗列上层应用连接的流程。
在梳理流程中,对于与流程相关性不大的代码省略,否则篇幅就会过长,读者可以参照代码路径和方法名找到方法的具体实现。

Wifi连接使用Dialog

/android/packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java:

 public boolean onPreferenceTreeClick(Preference preference) {
//连接到开放网络(无密码)
	 case WifiUtils.CONNECT_TYPE_OPEN_NETWORK:
//连接到已保存的网络
	 case WifiUtils.CONNECT_TYPE_SAVED_NETWORK:
//都不是(没连过的)
default:
	showDialog(mSelectedAccessPoint, WifiConfigUiBase.MODE_CONNECT);
}
private void showDialog(AccessPoint accessPoint, int dialogMode) {

 // Save the access point and edit mode
	mDlgAccessPoint = accessPoint;
	mDialogMode = dialogMode;
	showDialog(WIFI_DIALOG_ID);
}
public Dialog onCreateDialog(int dialogId) {
	 case WIFI_DIALOG_ID:
	 	//创建一个Dialog
	 	mDialog = WifiDialog.createModal(getActivity(), this, mDlgAccessPoint, mDialogMode);
	 	return mDialog;
}

在Dialog中进行操作
/android/packages/apps/Settings/src/com/android/settings/wifi/WifiDialog.java:

 public void onClick(DialogInterface dialogInterface, int id) {
	if (mListener != null) {
		switch (id) {
			case BUTTON_SUBMIT:
						 mListener.onSubmit(this);
						 break;
			case BUTTON_FORGET:
		}
	}

}

/android/packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java:

 @Override
public void onSubmit(WifiDialog dialog) {
		if (mDialog != null) {
			submit(mDialog.getController());
		}
}
void submit(WifiConfigController configController) {
		mWifiManager.save(config, mSaveListener);
		if (mSelectedAccessPoint != null) { // Not an "Add network"
				connect(config, false /* isSavedNetwork */);
		}
		mWifiTracker.resumeScanning();//触发扫描
}

connect()方法就开始连接了。。。

Wifi连接使用Menu

还是从WifiSettings界面开始
/android/packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java:

@Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) {
	 if (mSelectedAccessPoint.isConnectable()) {
			menu.add(Menu.NONE, MENU_ID_CONNECT, 0 /* order */, R.string.wifi_connect);
    }
}
@Override
public boolean onContextItemSelected(MenuItem item) {
	 switch (item.getItemId()) {
			case MENU_ID_CONNECT: {
					connect(mSelectedAccessPoint.getConfig(), isSavedNetwork);
			}
	}
}

上述两种方法最后都调用到了WifiSettings.java的connect方法,那么接下来就从connect开始分析连接流程。

Wifi连接后续流程

/android/packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java:

protected void connect(final WifiConfiguration config, boolean isSavedNetwork) {
		mWifiManager.connect(config, mConnectListener);
}

/android/frameworks/base/wifi/java/android/net/wifi/WifiManager.java:

public void connect(@NonNull WifiConfiguration config, @Nullable ActionListener listener) {
	getChannel().sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID, putListener(listener), config);

}
public void save(@NonNull WifiConfiguration config, @Nullable ActionListener listener) {
		getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
}

connect方法发送了CONNECT_NETWORK和SAVE_NETWORK消息,WifiServiceImpl.java关注这些消息。
/android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java:

case WifiManager.SAVE_NETWORK: {
	else if (config != null) {
	//将消息转发至状态机 */
	 mClientModeImpl.sendMessage(Message.obtain(msg));
case WifiManager.CONNECT_NETWORK: 
	else if (config != null) {
	//将消息转发至状态机 */
	mClientModeImpl.sendMessage(Message.obtain(msg));

/android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeImpl.java:
ClientModeImpl是一个状态机,在WIFI打开之后,其处于ConnectModeState,所以在此状态下处理消息。

 class ConnectModeState extends State {
	case WifiManager.SAVE_NETWORK:
		 startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY);
	case WifiManager.CONNECT_NETWORK:
		 
 public void startConnectToNetwork(int networkId, int uid, String bssid) {
	sendMessage(CMD_START_CONNECT, networkId, uid, bssid);
}

保存成功之后,就去连接,还是处于ConnectModeState来处理消息。

case CMD_START_CONNECT:
	if (mWifiNative.connectToNetwork(mInterfaceName, config)) {
		。。。
		if (getCurrentState() != mDisconnectedState) {
			**transitionTo(mDisconnectingState);**
		}
	}

/android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java:

public boolean connectToNetwork(@NonNull String ifaceName, WifiConfiguration configuration) {
	mSupplicantStaIfaceHal.connectToNetwork(ifaceName, configuration);
}

/android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java:

 public boolean connectToNetwork(@NonNull String ifaceName, @NonNull WifiConfiguration config) {
 	addNetworkAndSaveConfig(ifaceName, config);
 }
private Pair<SupplicantStaNetworkHal, WifiConfiguration>addNetworkAndSaveConfig(@NonNull String ifaceName, WifiConfiguration config) {
	SupplicantStaNetworkHal network = addNetwork(ifaceName);//添加一个新的网络
}
//注册回调
public void onVendorStateChanged(int newState, byte[/* 6 */] bssid, int id, ArrayList<Byte> ssid, boolean filsHlpSent) {
 	mWifiMonitor.broadcastSupplicantStateChangeEvent(mIfaceName, getCurrentNetworkId(mIfaceName), wifiSsid, bssidStr, newSupplicantState);
 }

/android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiMonitor.java:

public void broadcastFilsNetworkConnectionEvent(String iface, int networkId, String bssid) {
	sendMessage(iface, FILS_NETWORK_CONNECTION_EVENT, networkId, 0, bssid);
}

/android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeImpl.java:
关注此消息,此时处于DisconnectingState。

case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
	deferMessage(message);
	transitionTo(mDisconnectedState);

接着状态转变到DisconnectedState

class DisconnectedState extends State {
	case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
		//向上层通知wifi状态
		setNetworkDetailedState(WifiInfo.getDetailedStateOf(stateChangeResult.state));
		/* ConnectModeState完成后续处理 */
		handleStatus = NOT_HANDLED;
		break;

所以又回到ConnectModeState。

case WifiMonitor.FILS_NETWORK_CONNECTION_EVENT:
case WifiMonitor.NETWORK_CONNECTION_EVENT:
	sendNetworkStateChangeBroadcast(mLastBssid);
	transitionTo(mObtainingIpState);

进入mObtainingIpState。

class ObtainingIpState extends State {
	public void enter(){
		mIpClient.startProvisioning(prov);
	}

/android/frameworks/base/packages/NetworkStack/src/android/net/ip/IpClient.java:

public void startProvisioning(ProvisioningConfiguration req) {
	mCallback.setNeighborDiscoveryOffload(true);
    sendMessage(CMD_START, new android.net.shared.ProvisioningConfiguration(req));
}

IpClient拥有四个状态,其初始状态是StoppedState。

class StoppedState extends State {
	case CMD_START:
		transitionTo(mStartedState);
class StartedState extends State {
	public void enter() {
		deferMessage(obtainMessage(CMD_JUMP_STARTED_TO_RUNNING));
	}
}	

自己发送消息,自己处理

case CMD_JUMP_STARTED_TO_RUNNING:
	transitionTo(mRunningState);

切换到RunningState

class RunningState extends State {
	 if (mConfiguration.mEnableIPv6 && !startIPv6()) {
		。。。
	}
	if (mConfiguration.mEnableIPv4 && !startIPv4()) {
		。。。
	}
private boolean startIPv4() {
	//先进状态机,让状态机处于初始化状态
	mDhcpClient = DhcpClient.makeDhcpClient(mContext, IpClient.this, mInterfaceParams);
	//然后向状态机发送消息,让其处理
 mDhcpClient.sendMessage(DhcpClient.CMD_START_DHCP);
}

/android/frameworks/base/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java:
进入状态机,其初始状态为mStoppedState。

class StoppedState extends State {
	case CMD_START_DHCP:
	if (mRegisteredForPreDhcpNotification) {//=true
		transitionTo(mWaitBeforeStartState);
	}
}

切换状态到

 class WaitBeforeStartState extends WaitBeforeOtherState {
		public WaitBeforeStartState(State otherState) {
			super();
			mOtherState = otherState;
		}

由于上述方法又super(),所以执行其父类状态enter

abstract class WaitBeforeOtherState extends LoggingState {
	public void enter() {
		super.enter();
		mController.sendMessage(CMD_PRE_DHCP_ACTION);
	}
}

发送了CMD_PRE_DHCP_ACTION消息,ClientModeImpl.java处理此消息,此前处于mObtainingIpState状态,由于此状态没有对应处理,所以
/android/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ClientModeImpl.java:

default:
	 handleStatus = NOT_HANDLED;//消息交由其父状态mL2ConnectedState来处理
	 break;
class L2ConnectedState extends State {
	case CMD_PRE_DHCP_ACTION:
	handlePreDhcpSetup();
	break;
}
void handlePreDhcpSetup() {
	sendMessage(CMD_PRE_DHCP_ACTION_COMPLETE);
}

再次回到:
/android/frameworks/base/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java:
//当前处于WaitBeforeOtherState

 case CMD_PRE_DHCP_ACTION_COMPLETE:
 		transitionTo(mOtherState);//OtherState=mDhcpInitState

切换状态:

class DhcpInitState extends PacketRetransmittingState {
	//接收数据包(开始是空的,因为要先主动发送数据包)
	protected void receivePacket(DhcpPacket packet) {
		transitionTo(mDhcpRequestingState);
	}
}

进入父类enter

abstract class PacketRetransmittingState extends LoggingState {
	public void enter() {
	sendMessage(CMD_KICK);
	}
}
case CMD_KICK:
	sendPacket();//主动发数据包
	 scheduleKick();
	return HANDLED;

切换状态:

 class DhcpRequestingState extends PacketRetransmittingState {
 	/接收数据包
	protected void receivePacket(DhcpPacket packet) {
	 setDhcpLeaseExpiry(packet);
	acceptDhcpResults(results, "Confirmed");
	transitionTo(mConfiguringInterfaceState);
}
//接收数据集
private void acceptDhcpResults(DhcpResults results, String msg) {
	notifySuccess();
}
private void notifySuccess() {
	mController.sendMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, new DhcpResults(mDhcpLease));
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值