接着前面说
前面写了一篇《Wifi启动流程分析》,大致分析了一下进入Android后wifi的启动情况。在最开始的地方也说了有创建一个ConnectivityService对象来管理一系列数据连接相关的服务。
try {
Slog.i(TAG, "Connectivity Service");
connectivity = new ConnectivityService(
context, networkManagement, networkStats, networkPolicy);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
networkStats.bindConnectivityManager(connectivity);
networkPolicy.bindConnectivityManager(connectivity);
wifiP2p.connectivityServiceReady();
wifi.checkAndStartWifi();
} catch (Throwable e) {
reportWtf("starting Connectivity Service", e);
}
接下来看看在ConnectivityService的构造方法中做了什么。
public ConnectivityService(Context context, INetworkManagementService netManager,
INetworkStatsService statsService, INetworkPolicyManager policyManager,
NetworkFactory netFactory) {
if (DBG) log("ConnectivityService starting up");
HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
handlerThread.start();
mHandler = new InternalHandler(handlerThread.getLooper());
mTrackerHandler = new NetworkStateTrackerHandler(handlerThread.getLooper());
if (netFactory == null) {
netFactory = new DefaultNetworkFactory(context, mTrackerHandler);
}
...//此处省略,很多行O(∩_∩)O~
for (int targetNetworkType : mPriorityList) {
final NetworkConfig config = mNetConfigs[targetNetworkType];
final NetworkStateTracker tracker;
try {
tracker = netFactory.createTracker(targetNetworkType, config);
mNetTrackers[targetNetworkType] = tracker;
} catch (IllegalArgumentException e) {
Slog.e(TAG, "Problem creating " + getNetworkTypeName(targetNetworkType)
+ " tracker: " + e);
continue;
}
tracker.startMonitoring(context, mTrackerHandler);
if (config.isDefault()) {
tracker.reconnect();
}
}
.......//省略...
}
这里可以看到,首先创建了一个NetworkStateTrackerHandler:
mTrackerHandler = new NetworkStateTrackerHandler(handlerThread.getLooper());
一看到Handler,很自然就会想到消息处理,那么这里会处理什么消息呢,先mark一下,等会儿再说。
接着往下看,看到创建了一个工厂实例:
netFactory = new DefaultNetworkFactory(context, mTrackerHandler);
既然是工厂类,那么里面必然有很多功能相似的方法集合,具体干嘛的,也在后面说,不要骂我O(∩_∩)O~。
接下来,看到一个for循环了,每次循环是创建了一个tracker:
tracker = netFactory.createTracker(targetNetworkType, config);
然后就拿到这个tracker开始监控网络状态:
tracker.startMonitoring(context, mTrackerHandler);
接下来就先不看了,让我们来回头看看这些都是在干嘛的。
源码分析
先来看看创建的netFactory是干嘛的:
public interface NetworkFactory {
public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config);
}
private static class DefaultNetworkFactory implements NetworkFactory {
private final Context mContext;
private final Handler mTrackerHandler;
public DefaultNetworkFactory(Context context, Handler trackerHandler) {
mContext = context;
mTrackerHandler = trackerHandler;
}
@Override
public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config) {
switch (config.radio) {
case TYPE_WIFI:
return new WifiStateTracker(targetNetworkType, config.name);
case TYPE_MOBILE:
return new MobileDataStateTracker(targetNetworkType, config.name);
case TYPE_DUMMY:
return new DummyDataStateTracker(targetNetworkType, config.name);
case TYPE_BLUETOOTH:
return BluetoothTetheringDataTracker.getInstance();
case TYPE_WIMAX:
return makeWimaxStateTracker(mContext, mTrackerHandler);
case TYPE_ETHERNET:
return EthernetDataTracker.getInstance();
default:
throw new IllegalArgumentException(
"Trying to create a NetworkStateTracker for an unknown radio type: "
+ config.radio);
}
}
}
这个的代码也比较短,作为ConnectivityService的静态内部类存在。
这个工厂类,主要是根据给定的NetworkConfig生成一个NetworkStateTracker实例。
可以看到,当类型为wifi时,会创建一个Wifi的状态追踪器:
new WifiStateTracker(targetNetworkType, config.name);
这个正是我们想要的。
/frameworks/base/wifi/java/android/net/wifi/WifiStateTracker.java
public WifiStateTracker(int netType, String networkName) {
mNetworkInfo = new NetworkInfo(netType, 0, networkName, "");
mLinkProperties = new LinkProperties();
mLinkCapabilities = new LinkCapabilities();
mNetworkInfo.setIsAvailable(false);
setTeardownRequested(false);
}
这个构造方法中也没做很多事情,做了一些初始化的工作。虽然构造方法中没做什么,不过我们知道,这个对象中的一些方法很重要,比如startMonitoring。
在拿到netFactory对象之后,紧接着就是调用了createTracker方法,针对每种类型的连接创建对应的tracker对象,这个在上面的for循环中可以清晰的看到。像wifi接下来就与WifiStateTracker密切相关。
在得到tracker对象之后,我们看到每个tracker开始执行自己的监控:
tracker.startMonitoring(context, mTrackerHandler);
上面已经说了,看WifiStateTracker中的方法实现:
/**
* Begin monitoring wifi connectivity
*/
public void startMonitoring(Context context, Handler target) {
mCsHandler = target;
mContext = context;
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
mWifiStateReceiver = new WifiStateReceiver();
mContext.registerReceiver(mWifiStateReceiver, filter);
}
这里注册一个广播接收者,主要监听网络状态变化和链路配置信息的变化。下面是这个广播接收者的实现:
private class WifiStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO);
mLinkProperties = intent.getParcelableExtra(
WifiManager.EXTRA_LINK_PROPERTIES);
if (mLinkProperties == null) {
mLinkProperties = new LinkProperties();
}
mLinkCapabilities = intent.getParcelableExtra(
WifiManager.EXTRA_LINK_CAPABILITIES);
if (mLinkCapabilities == null) {
mLinkCapabilities = new LinkCapabilities();
}
// don't want to send redundent state messages
// but send portal check detailed state notice
NetworkInfo.State state = mNetworkInfo.getState();
if (mLastState == state &;&;
mNetworkInfo.getDetailedState() != DetailedState.CAPTIVE_PORTAL_CHECK) {
return;
} else {
mLastState = state;
}
Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED,
new NetworkInfo(mNetworkInfo));
msg.sendToTarget();
} else if (intent.getAction().equals(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION)) {
mLinkProperties = (LinkProperties) intent.getParcelableExtra(
WifiManager.EXTRA_LINK_PROPERTIES);
Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
msg.sendToTarget();
}
}
}
最后会通过mCsHandler发送了一个消息,消息由谁来接收呢?
前面已经说过mTrackerHandler这个Handler,消息就是传到它这里来了,看看handleMessage方法,代码略长:
public void handleMessage(Message msg) {
NetworkInfo info;
switch (msg.what) {
case NetworkStateTracker.EVENT_STATE_CHANGED: {
info = (NetworkInfo) msg.obj;
NetworkInfo.State state = info.getState();
if (VDBG || (state == NetworkInfo.State.CONNECTED) ||
(state == NetworkInfo.State.DISCONNECTED) ||
(state == NetworkInfo.State.SUSPENDED)) {
log("ConnectivityChange for " +
info.getTypeName() + ": " +
state + "/" + info.getDetailedState());
}
if (ConnectivityManager.isNetworkTypeMobile(info.getType())
&;&; (0 != Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0))
&;&; (((state == NetworkInfo.State.CONNECTED)
&;&; (info.getType() == ConnectivityManager.TYPE_MOBILE))
|| info.isConnectedToProvisioningNetwork())) {
log("ConnectivityChange checkMobileProvisioning for"
+ " TYPE_MOBILE or ProvisioningNetwork");
checkMobileProvisioning(CheckMp.MAX_TIMEOUT_MS);
}
EventLogTags.writeConnectivityStateChanged(
info.getType(), info.getSubtype(), info.getDetailedState().ordinal());
if (info.getDetailedState() ==
NetworkInfo.DetailedState.FAILED) {
log("NetworkInfo.DetailedState.FAILED....");
handleConnectionFailure(info);
} else if (info.getDetailedState() ==
DetailedState.CAPTIVE_PORTAL_CHECK) {
handleCaptivePortalTrackerCheck(info);
} else if (info.isConnectedToProvisioningNetwork()) {
LinkProperties lp = getLinkProperties(info.getType());
if (DBG) {
log("EVENT_STATE_CHANGED: connected to provisioning network, lp=" + lp);
}
for (RouteInfo r : lp.getRoutes()) {
removeRoute(lp, r, TO_DEFAULT_TABLE);
}
} else if (state == NetworkInfo.State.DISCONNECTED) {
handleDisconnect(info);
} else if (state == NetworkInfo.State.SUSPENDED) {
handleDisconnect(info);
} else if (state == NetworkInfo.State.CONNECTED) {
log("state == NetworkInfo.State.CONNECTED,then handle connect");
handleConnect(info);
}
if (mLockdownTracker != null) {
mLockdownTracker.onNetworkInfoChanged(info);
}
break;
}
case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: {
info = (NetworkInfo) msg.obj;
// MStar Android Patch Begin
if (info == null) {
loge("ERROR: No network info for EVENT_CONFIGURATION_CHANGED ");
return;
}
// MStar Android Patch End
handleConnectivityChange(info.getType(), false);
break;
}
case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED: {
info = (NetworkInfo) msg.obj;
int type = info.getType();
if (mNetConfigs[type].isDefault()) updateNetworkSettings(mNetTrackers[type]);
break;
}
}
}
这里处理了多种系统网络状态变化,在这里,分析一下
EVENT_STATE_CHANGED。当网络状态为state == NetworkInfo.State.CONNECTED时,会执行handleConnect(info);
在该方法中,会继续调用handleConnectivityChange(newNetType, false);
这个方法的实现比较长,
private void handleConnectivityChange(int netType, boolean doReset) {
int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0;
boolean exempt = ConnectivityManager.isNetworkTypeExempt(netType);
/*
* If a non-default network is enabled, add the host routes that
* will allow it's DNS servers to be accessed.
*/
handleDnsConfigurationChange(netType);//处理DNS配置变化
//....此处省略,以下代码主要处理新连接的网络信息与之前的信息比较
if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
//当前是已经连接上,获取新接入的链接配置信息
newLp = mNetTrackers[netType].getLinkProperties();
if (curLp != null) {//当前链路信息存在
if (curLp.isIdenticalInterfaceName(newLp)) {
CompareResult car = curLp.compareAddresses(newLp);
if ((car.removed.size() != 0) || (car.added.size() != 0)) {
for (LinkAddress linkAddr : car.removed) {
if (linkAddr.getAddress() instanceof Inet4Address) {
resetMask |= NetworkUtils.RESET_IPV4_ADDRESSES;
}
if (linkAddr.getAddress() instanceof Inet6Address) {
resetMask |= NetworkUtils.RESET_IPV6_ADDRESSES;
}
}
}
} else {
resetMask = NetworkUtils.RESET_ALL_ADDRESSES;
}
}
if (mNetConfigs[netType].isDefault()) {//如果是默认网关
handleApplyDefaultProxy(newLp.getHttpProxy());
}
}
...
boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault(), exempt, newLpPrefered); //更新路由
....
if (resetMask != 0 || resetDns) {
if (VDBG) log("handleConnectivityChange: resetting");
if (curLp != null) {
if (VDBG) log("handleConnectivityChange: resetting curLp=" + curLp);
for (String iface : curLp.getAllInterfaceNames()) {
if (TextUtils.isEmpty(iface) == false) {
if (resetMask != 0) {
//modify by dq start
LinkProperties tmpLp = getLinkProperties(mActiveDefaultNetwork);
if(tmpLp != null) log("current active iface:" + tmpLp.getInterfaceName());
log("ready to reset: " + iface);
if(WIFI_ETHERNET_COEXIST_ENABLED
&;&; (tmpLp != null) &;&; (iface != null)
&;&; (iface.equals(tmpLp.getInterfaceName()))) {
// not reset connection
log("handleConnectivityChange: netcoexist and network " +
mActiveDefaultNetwork +" is active, not reset");
} else {
if (DBG) log("resetConnections(" + iface + ", " + resetMask + ")");
// MStar Android Patch Begin
// do not reset ppp interface
if (iface != null &;&; iface.startsWith("ppp") == false) {
NetworkUtils.resetConnections(iface, resetMask);//对网卡重置连接
}
// MStar Android Patch End
// Tell VPN the interface is down. It is a temporary
// but effective fix to make VPN aware of the change.
if ((resetMask &; NetworkUtils.RESET_IPV4_ADDRESSES) != 0) {
synchronized(mVpns) {
for (int i = 0; i < mVpns.size(); i++) {
mVpns.valueAt(i).interfaceStatusChanged(iface, false);
}
}
}
}
}
//modify by dq end
if (resetDns) {
flushVmDnsCache();//刷新DNS缓存
if (VDBG) log("resetting DNS cache for " + iface);
try {
mNetd.flushInterfaceDnsCache(iface);//调用netd进程去刷新dns
} catch (Exception e) {
// never crash - catch them all
if (DBG) loge("Exception resetting dns cache: " + e);
}
}
} else {
loge("Can't reset connection for type "+netType);
}
}
}
}
//。。。省略
这个方法的代码很长,但是从上面的注释中,我们可以大致看出来是怎样的一种执行过程。