Android 4.2 Ethernet启动流程

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

对于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





  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: Android 9.0是一款广泛应用于移动设备的操作系统,它提供了强大的连接功能,包括无线和有线网络。而ethernet模块是其中一个重要的组成部分。 在Android 9.0中,ethernet模块是用于连接有线网络的功能。它允许用户通过有线网络连接设备,以获取更稳定和高速的数据传输。与无线网络相比,有线网络具有更高的带宽和更低的延迟,适用于一些对网络稳定性有更高要求的场景。比如,在办公室或家庭中,用户可以通过ethernet模块将设备连接到路由器或交换机上,以提供更稳定的网络连接。 ethernet模块的设置非常简单。用户只需将网线插入设备的ethernet接口,然后在系统设置中进行一些简单的配置即可。一般来说,用户需要指定IP地址、子网掩码、网关等网络参数。此外,用户还可以设置DNS服务器地址,以便设备能够正确解析域名。 通过ethernet模块连接有线网络后,用户可以享受到更快速的网络体验。无论是浏览网页、观看视频还是进行在线游戏,都能够感受到更低的延迟和更稳定的连接。此外,ethernet模块还可以用于实现局域网共享,用户可以在局域网内共享文件、打印机和其他资源。 总的来说,Android 9.0的ethernet模块提供了一种可靠稳定的有线网络连接方式,使用户可以更好地利用有线网络资源,以获取更高速的数据传输和更稳定的网络连接。无论是在家庭、办公室还是其他需要高稳定性网络场景中,ethernet模块都能够为用户带来更好的网络体验。 ### 回答2: Android 9.0引入了Ethernet模块,使得Android设备可以通过有线网络连接。Ethernet模块提供了一套API,供开发者在Android应用中操控有线网络。 在Android 9.0及以上版本中,Ethernet模块可以通过“EthernetManager”类相关的API进行控制。开发者可以使用这些API来管理设备的Ethernet连接,包括获取当前连接状态、启用或禁用有线网络、获取有线网络的IP地址等。 在代码中,可以通过获取EthernetManager实例,然后调用相关方法来操作Ethernet连接。例如,可以通过“getEthernetState()”方法获取Ethernet的当前连接状态,返回值为“EthernetManager.ETHERNET_STATE_DISABLED”表示有线网络已禁用,返回值为“EthernetManager.ETHERNET_STATE_ENABLED”表示有线网络已启用。 除了控制有线网络的连接状态,Ethernet模块还提供了获取有线网络的IP地址的功能。通过“getIpAddress()”方法可以获取当前有线网络的IP地址信息。 虽然Ethernet模块在Android 9.0中引入,但需要注意的是,并非所有的Android设备都支持有线网络连接。因此,在使用Ethernet模块相关功能之前,建议开发者先检查设备是否支持有线网络连接,以避免在不支持的设备上使用导致错误。 总之,Android 9.0的Ethernet模块为开发者提供了方便的API,用于管理和控制Android设备的有线网络连接。通过使用相关的API,开发者可以轻松地获取和操控有线网络的连接状态和IP地址等信息。这一功能为Android设备的网络连接提供了更多选择和灵活性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值