ConnectivityService用来管理系统中所有网络,谁能连接,谁需要断开。在连接一个网络是,收集网络信息,通过ConnetivityManager提供给应用使用。
在WIFI连接过程中,到链路层L2ConnectedState状态时,有:
class L2ConnectedState extends State {
@Override
public void enter() {
mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext,
"WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter,
mLinkProperties, 60, mNetworkMisc);
}
}
WifiNetworkAgent集成自NetworkAgent,NetworkAgent作为一种网络的代理,和ConnectivityService建立联系。
private class WifiNetworkAgent extends NetworkAgent {
public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
super(l, c, TAG, ni, nc, lp, score, misc);
}
}
NetworkAgent构造方法为:
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score) {
this(looper, context, logTag, ni, nc, lp, score, null);
}
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
super(looper);
LOG_TAG = logTag;
mContext = context;
if (ni == null || nc == null || lp == null) {
throw new IllegalArgumentException();
}
if (VDBG) log("Registering NetworkAgent");
ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
}
最后通过registerNetworkAgent向ConnectivityManager注册NetworkAgent。此处传入了networkinfo,wifi连接状态是CONNECTING, 传入了score = 60,looper参数是消息处理位置,这里是WifiStateMachine. registerNetworkAgent通过ConnectivityManager到达ConnectivityService.
public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkMisc networkMisc) {
enforceConnectivityInternalPermission();
// TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
// satisfies mDefaultRequest.
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties(
linkProperties), new NetworkCapabilities(networkCapabilities), currentScore,
mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
synchronized (this) {
nai.networkMonitor.systemReady = mSystemReady;
}
addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network,
networkInfo.getExtraInfo());
if (DBG) log("registerNetworkAgent " + nai);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
return nai.network.netId
NetworkAgentInfo在ConnectivityService中使用,它是NetwrokInfo等信息集合。通过本类Handler发送EVENT_REGISTER_NETWORK_AGENT消息。
消息处理方法是handleRegisterNetworkAgent().
private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
NetworkInfo networkInfo = na.networkInfo;
na.networkInfo = null;
updateNetworkInfo(na, networkInfo);
}
updateNetworkInfor更新网络:
private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
networkAgent.everConnected = true;
updateLinkProperties(networkAgent, null);
notifyIfacesChangedForNetworkStats();
networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
scheduleUnvalidatedPrompt(networkAgent);
if (networkAgent.isVPN()) {
// Temporarily disable the default proxy (not global).
synchronized (mProxyLock) {
if (!mDefaultProxyDisabled) {
mDefaultProxyDisabled = true;
if (mGlobalProxy == null && mDefaultProxy != null) {
sendProxyBroadcast(null);
}
}
}
// TODO: support proxy per network.
}
// Whether a particular NetworkRequest listen should cause signal strength thresholds to
// be communicated to a particular NetworkAgent depends only on the network's immutable,
// capabilities, so it only needs to be done once on initial connect, not every time the
// network's capabilities change. Note that we do this before rematching the network,
// so we could decide to tear it down immediately afterwards. That's fine though - on
// disconnection NetworkAgents should stop any signal strength monitoring they have been
// doing.
updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
// Consider network even though it is not yet validated.
final long now = SystemClock.elapsedRealtime();
rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);
// This has to happen after matching the requests, because callbacks are just requests.
notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);
}
}
由于WIFI网络当前是CONNECTING, 此次调用不会做任何处理。但是当WIFI进入连接状态,将会有如下调用:
class ConnectedState extends State {
if (mWifiConnectivityManager != null) {
mWifiConnectivityManager.handleConnectionStateChanged(
WifiConnectivityManager.WIFI_STATE_CONNECTED);
}
}
但是当IpManager获得到IP地址,WifiStateMachine通过设置的回调,发出CMD_IP_CONFIGURATION_SUCCESSFUL消息。并做如下处理:
case CMD_IP_CONFIGURATION_SUCCESSFUL:
handleSuccessfulIpConfiguration();
reportConnectionAttemptEnd(
WifiMetrics.ConnectionEvent.FAILURE_NONE,
WifiMetricsProto.ConnectionEvent.HLF_NONE);
sendConnectedState();
transitionTo(mConnectedState);
break;
sendConnectedState()方法将和ConnectivityService通信。
private void sendConnectedState() {
setNetworkDetailedState(DetailedState.CONNECTED); // 设置网络状态为CONNECTED
mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.CONNECTED);
sendNetworkStateChangeBroadcast(mLastBssid);
}
在setNetworkDetailedState有一个比较重要的方法,setNetworkDetailedState。WifiStateMachine中通过setNetworkDetailedState更新WIFI状态到ConnectivityService.
private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) {
if (state != mNetworkInfo.getDetailedState()) {
mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());
if (mNetworkAgent != null) {
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
}
sendNetworkStateChangeBroadcast(null);
return true;
}
}
这里发送EVENT_NETWORK_INFO_CHANGED到ConnectivityService处理。处理方法是:
updateNetworkInfo(nai, info);在之前已经分析过。现在详细分析:
private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
NetworkInfo.State state = newInfo.getState();
NetworkInfo oldInfo = null;
final int oldScore = networkAgent.getCurrentScore();
if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
networkAgent.everConnected = true;
updateLinkProperties(networkAgent, null);
notifyIfacesChangedForNetworkStats();
networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
scheduleUnvalidatedPrompt(networkAgent);
if (networkAgent.isVPN()) {
// Temporarily disable the default proxy (not global).
synchronized (mProxyLock) {
if (!mDefaultProxyDisabled) {
mDefaultProxyDisabled = true;
if (mGlobalProxy == null && mDefaultProxy != null) {
sendProxyBroadcast(null);
}
}
}
// TODO: support proxy per network.
}
final long now = SystemClock.elapsedRealtime();
rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);
}
这里关注两个地方:
1.networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED); //这个消息将发给networkMonitor做protal
2.rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now); // 处理网络连接
这里先做网络做protal上网验证,这个验证可能会影响网络评分。然后在对网络进行管理,是连接网络,断开其他网络还是不连接。继续看起实现:
private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now) {
final int score = newNetwork.getCurrentScore(); // 当前接入的网络评分
// 已经加入的网络
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
// 根据评分启动网络
if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
if (VDBG) log("rematch for " + newNetwork.name());
if (currentNetwork != null) {
if (VDBG) log(" accepting network in place of " + currentNetwork.name());
currentNetwork.removeRequest(nri.request.requestId);
currentNetwork.lingerRequest(nri.request, now, mLingerDelayMs);
affectedNetworks.add(currentNetwork);
} else {
if (VDBG) log(" accepting network in place of null");
}
newNetwork.unlingerRequest(nri.request);
mNetworkForRequestId.put(nri.request.requestId, newNetwork);
if (!newNetwork.addRequest(nri.request)) {
Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request);
}
addedRequests.add(nri);
keep = true;
// Tell NetworkFactories about the new score, so they can stop
// trying to connect if they know they cannot match it.
// TODO - this could get expensive if we have alot of requests for this
// network. Think about if there is a way to reduce this. Push
// netid->request mapping to each factory?
sendUpdatedScoreToFactories(nri.request, score);
if (isDefaultRequest(nri)) {
isNewDefault = true;
oldDefaultNetwork = currentNetwork;
if (currentNetwork != null) {
mLingerMonitor.noteLingerDefaultNetwork(currentNetwork, newNetwork);
}
}
}
updateLingerState(newNetwork, now);
// 断开不需要的网络
if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) {
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
if (unneeded(nai, UnneededFor.TEARDOWN)) {
if (nai.getLingerExpiry() > 0) {
// This network has active linger timers and no requests, but is not
// lingering. Linger it.
//
// One way (the only way?) this can happen if this network is unvalidated
// and became unneeded due to another network improving its score to the
// point where this network will no longer be able to satisfy any requests
// even if it validates.
updateLingerState(nai, now);
} else {
if (DBG) log("Reaping " + nai.name());
teardownUnneededNetwork(nai);
}
}
}
}
}
}