Android 4.2 Ethernet启动流程

做Box,以太网就比较常用了,我们看下 以太网的打开流程:

Android 4.2 Ethernet启动流程_第1张图片

通过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();
			}
		}
	}

对于enable,调用mTracker.reconnect()

    public boolean reconnect() {
        mTeardownRequested.set(false);
		ConnectNetwork(true);
        return true;
    }

继续调用ConnectNetwork

	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
            }
        }
    }


    handleConnect会对网络的优先级进行判断,如果网络的优先级小于现有网络,则断开该网络,否则断开以前的网络。

一下是一个以太网跟wifi并存的方案补丁包:

http://download.csdn.net/detail/new_abc/7730099





你可能感兴趣的:(Android 4.2 Ethernet启动流程)