做Box,以太网就比较常用了,我们看下 以太网的打开流程:
通过Setting里面的选项,我们勾选以太网时,不管是dhcp获取ip,还是静态配置的ip,都会启动以太网并获取ip,启动以太网通过setEnabled来启动,这里会调用到EthernetManager,EthernetManager调用EthernetService的setState
public synchronized void setState(int state) {
if (mEthState != state) {
mEthState = state;
if (state == EthernetManager.ETHERNET_STATE_DISABLED) {
if(DBG) Slog.d(TAG, "setState: disable ethernet.");
persistEnabled(false);
mTracker.teardown();
} else if (state == EthernetManager.ETHERNET_STATE_ENABLED) {
if(DBG) Slog.d(TAG, "setState: enable ethernet.");
persistEnabled(true);
mTracker.reconnect();
}
}
}
public boolean reconnect() {
mTeardownRequested.set(false);
ConnectNetwork(true);
return true;
}
public void ConnectNetwork(boolean up) {
if(DBG) Slog.d(TAG, "ConnectNetwork: Up is " + up + ", mLinkUp is " + mLinkUp +
", On is " + mEthManage.isOn() + ", mIface " + mIface);
if(!mEthManage.isConfigured()) {
if(mIface != null)
Log.d(TAG, "no configuration for " + mIface);
return;
}
/* connect */
if(up && mEthManage.isOn()) {
EthernetDevInfo ifaceInfo = mEthManage.getSavedConfig();
if(ifaceInfo == null) {
Log.e(TAG, "get configuration failed.");
return;
}
synchronized(mIface) {
if(!mIface.equals(ifaceInfo.getIfName())) {
if(!mIface.isEmpty()) {
NetworkUtils.stopDhcp("eth_" + mIface);
NetworkUtils.disableInterface(mIface);
}
mIface = ifaceInfo.getIfName();
}
}
NetworkUtils.enableInterface(mIface);
if(mLinkUp == false)
return;
/* dhcp way */
if(mEthManage.isDhcp()) {
/* make sure iface to 0.0.0.0 */
try{
mNMService.clearInterfaceAddresses(mIface);
NetworkUtils.resetConnections(mIface, 0);
} catch (RemoteException e) {
Log.e(TAG, "ERROR: " + e);
}
/* stop dhcp if already running */
if(SystemProperties.get("dhcp." + mIface + ".result").equals("ok")) {
NetworkUtils.stopDhcp("eth_" + mIface);
sendStateBroadcast(EthernetManager.EVENT_CONFIGURATION_FAILED);
}
if(DBG) Slog.d(TAG, "connecting and running dhcp.");
runDhcp();
} else {
/* static ip way */
NetworkUtils.stopDhcp("eth_" + mIface);
/* read configuration from usr setting */
DhcpInfoInternal dhcpInfoInternal = getIpConfigure(ifaceInfo);
mLinkProperties = dhcpInfoInternal.makeLinkProperties();
mLinkProperties.setInterfaceName(mIface);
InterfaceConfiguration ifcg = new InterfaceConfiguration();
ifcg.setLinkAddress(dhcpInfoInternal.makeLinkAddress());
ifcg.setInterfaceUp();
try{
mNMService.setInterfaceConfig(mIface, ifcg);
} catch (Exception e) {
Log.e(TAG, "ERROR: " + e);
sendStateBroadcast(EthernetManager.EVENT_CONFIGURATION_FAILED);
return;
}
if(DBG) Slog.d(TAG, "connecting and confgure static ip address.");
mNetworkInfo.setIsAvailable(true);
mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
msg.sendToTarget();
sendStateBroadcast(EthernetManager.EVENT_CONFIGURATION_SUCCEEDED);
}
} else if(isTeardownRequested()) {
/* disconnect */
Slog.d(TAG, "teardown network.");
NetworkUtils.stopDhcp("eth_" + mIface);
mLinkProperties.clear();
NetworkUtils.disableInterface(mIface);
mNetworkInfo.setIsAvailable(false);
mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
msg.sendToTarget();
sendStateBroadcast(EthernetManager.EVENT_DISCONNECTED);
}
}
这里会调用getSavedConfig或去以太网的一些信息,如地址掩码,网关等,接着调用NetworkUtils.enableInterface使能网卡设备,这个时候mLinkUp为false,函数就返回了,但是NetworkUtils.enableInterface使能网卡设备的时候会和下层的netd通信,并通过notifyInterfaceLinkStateChanged回调到EthernetDataTracker的interfaceLinkStateChanged
private void interfaceLinkStateChanged(String iface, boolean up) {
int tmpStatus = 0;
int i=0;
if (mIface.matches(iface)) {
for(i = 0; i < 3; i++) {
try {
Thread.sleep(100);
} catch(Exception e){ }
tmpStatus = mEthManage.checkLink(iface);
if(tmpStatus == 0 && mFirstLinkUp == true) {
Slog.d(TAG, "link entry exist,but no any value,bring up.");
NetworkUtils.enableInterface(iface);
mFirstLinkUp = false;
}
}
Slog.d(TAG, "interfaceLinkStateChanged: ["+ iface + "], up [" + up + "]");
if(tmpStatus == -1) {
//checkLink return -1 means no entry
Slog.d(TAG, "checkLink return -1 means no entry.");
return;
}
up = (tmpStatus == 1) ? true : false;
if(mLinkUp == up)
return;
mLinkUp = up;
if (up) {
reconnect();
/* modified by chenjd, 2013-08-01,
* when the broadcast send before boot complete, it will throw exception, this will make
* the ethernet can't update its state when its interface link state changes.To fix it,
* the broadcast intent must add flag FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT */
Intent upIntent = new Intent(EthernetManager.ETHERNET_LINKED_ACTION);
upIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcast(upIntent);
} else {
if(DBG) Slog.d(TAG, "interfaceLinkStateChanged: teardown network.");
NetworkUtils.stopDhcp("eth_" + mIface);
mLinkProperties.clear();
mNetworkInfo.setIsAvailable(false);
mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
msg.sendToTarget();
sendStateBroadcast(EthernetManager.EVENT_DISCONNECTED);
/* modified by chenjd, 2013-08-01,
* when the broadcast send before boot complete, it will throw exception, this will make
* the ethernet can't update its state when its interface link state changes.To fix it,
* the broadcast intent must add flag FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT */
Intent downIntent = new Intent(EthernetManager.ETHERNET_DISLINKED_ACTION);
downIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcast(downIntent);
pppoe_ok = false;
}
}
}
该函数设置mLinkUp,并调用reconnect重新连接网络,这里就会到了ConnectNetwork的如下代码出
{
EthernetDevInfo ifaceInfo = mEthManage.getSavedConfig();
if(ifaceInfo == null) {
Log.e(TAG, "get configuration failed.");
return;
}
synchronized(mIface) {
if(!mIface.equals(ifaceInfo.getIfName())) {
if(!mIface.isEmpty()) {
NetworkUtils.stopDhcp("eth_" + mIface);
NetworkUtils.disableInterface(mIface);
}
mIface = ifaceInfo.getIfName();
}
}
NetworkUtils.enableInterface(mIface);
if(mLinkUp == false)
return;
/* dhcp way */
if(mEthManage.isDhcp()) {
/* make sure iface to 0.0.0.0 */
try{
mNMService.clearInterfaceAddresses(mIface);
NetworkUtils.resetConnections(mIface, 0);
} catch (RemoteException e) {
Log.e(TAG, "ERROR: " + e);
}
/* stop dhcp if already running */
if(SystemProperties.get("dhcp." + mIface + ".result").equals("ok")) {
NetworkUtils.stopDhcp("eth_" + mIface);
sendStateBroadcast(EthernetManager.EVENT_CONFIGURATION_FAILED);
}
if(DBG) Slog.d(TAG, "connecting and running dhcp.");
runDhcp();
} else {
/* static ip way */
NetworkUtils.stopDhcp("eth_" + mIface);
/* read configuration from usr setting */
DhcpInfoInternal dhcpInfoInternal = getIpConfigure(ifaceInfo);
mLinkProperties = dhcpInfoInternal.makeLinkProperties();
mLinkProperties.setInterfaceName(mIface);
InterfaceConfiguration ifcg = new InterfaceConfiguration();
ifcg.setLinkAddress(dhcpInfoInternal.makeLinkAddress());
ifcg.setInterfaceUp();
try{
mNMService.setInterfaceConfig(mIface, ifcg);
} catch (Exception e) {
Log.e(TAG, "ERROR: " + e);
sendStateBroadcast(EthernetManager.EVENT_CONFIGURATION_FAILED);
return;
}
if(DBG) Slog.d(TAG, "connecting and confgure static ip address.");
mNetworkInfo.setIsAvailable(true);
mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
msg.sendToTarget();
sendStateBroadcast(EthernetManager.EVENT_CONFIGURATION_SUCCEEDED);
}
}
区分dhcp还是静态设置,我们这里看静态设置ip,首先停止dhcp,最后调用NetworkManagementService的setInterfaceConfig设置静态ip,setInterfaceConfig最终也是通过cmd的方式与netd通信,传送命令setcfg,这里还会发送一个EVENT_STATE_CHANGED广播,他的处理在NetworkStateTrackerHandler中,对于NetworkInfo.State.CONNECTED消息,会调用handleConnect
private void handleConnect(NetworkInfo info) {
final int newNetType = info.getType();
setupDataActivityTracking(newNetType);
// snapshot isFailover, because sendConnectedBroadcast() resets it
boolean isFailover = info.isFailover();
final NetworkStateTracker thisNet = mNetTrackers[newNetType];
final String thisIface = thisNet.getLinkProperties().getInterfaceName();
// if this is a default net and other default is running
// kill the one not preferred
if (mNetConfigs[newNetType].isDefault()) {
if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != newNetType) {
if (isNewNetTypePreferredOverCurrentNetType(newNetType)) {
// tear down the other
NetworkStateTracker otherNet =
mNetTrackers[mActiveDefaultNetwork];
if (DBG) {
log("Policy requires " + otherNet.getNetworkInfo().getTypeName() +
" teardown");
}
if (!teardown(otherNet)) {
loge("Network declined teardown request");
teardown(thisNet);
return;
}
} else {
// don't accept this one
if (VDBG) {
log("Not broadcasting CONNECT_ACTION " +
"to torn down network " + info.getTypeName());
}
teardown(thisNet);
return;
}
}
synchronized (ConnectivityService.this) {
// have a new default network, release the transition wakelock in a second
// if it's held. The second pause is to allow apps to reconnect over the
// new network
if (mNetTransitionWakeLock.isHeld()) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(
EVENT_CLEAR_NET_TRANSITION_WAKELOCK,
mNetTransitionWakeLockSerialNumber, 0),
1000);
}
}
mActiveDefaultNetwork = newNetType;
// this will cause us to come up initially as unconnected and switching
// to connected after our normal pause unless somebody reports us as reall
// disconnected
mDefaultInetConditionPublished = 0;
mDefaultConnectionSequence++;
mInetConditionChangeInFlight = false;
// Don't do this - if we never sign in stay, grey
//reportNetworkCondition(mActiveDefaultNetwork, 100);
}
thisNet.setTeardownRequested(false);
updateNetworkSettings(thisNet);
handleConnectivityChange(newNetType, false);
sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
// notify battery stats service about this network
if (thisIface != null) {
try {
BatteryStatsService.getService().noteNetworkInterfaceType(thisIface, newNetType);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
}
}
一下是一个以太网跟wifi并存的方案补丁包:
http://download.csdn.net/detail/new_abc/7730099