EthernetMornitor 与 EthernetStateTracker

EthernetMornitor 这个类位于: frameworks/base/ethernet/java/android/net/ethernet/EthernetMonitor.java

 它会监听底层ethernet 状态 的 event.

1. EthernetMonitor :

/**
 * Listens for events from kernel, and passes them on
 * to the {@link EtherentStateTracker} for handling. Runs in its own thread.
 *
 * @hide
 */
public class EthernetMonitor {
    private static final String TAG = "EthernetMonitor";
    private static final int CONNECTED = 1;
    private static final int DISCONNECTED = 2;
    private static final int PHYUP = 3;
    private static final String connectedEvent = "CONNECTED";
    private static final String disconnectedEvent = "DISCONNECTED";
    private static final int ADD_ADDR = 20;
    private static final int RM_ADDR = 21;
    private static final int NEW_LINK = 16;
    private static final int DEL_LINK = 17;
    private static final boolean localLOGV = false;

    private EthernetStateTracker mTracker;

    //EthernetMonitor 是 EthernetStateTraker 的一个辅助
    public EthernetMonitor(EthernetStateTracker tracker) {
        mTracker = tracker;
    }


a. startMonitoring(): 会在 EthernetStateTracker.StartPolling()中 调用此函数。

    public void startMonitoring() {
        new MonitorThread().start(); //线程开始
    }

    class MonitorThread extends Thread {
        public MonitorThread() {
            super("EthMonitor");
        }

        public void run() {
            //noinspection InfiniteLoopStatement
            for (;;) {     //不断的在监听 kernel event
                int index;
                int i;
                int cmd;
                String dev;

                if (localLOGV) Slog.v(TAG, "go poll events");

                String eventName = EthernetNative.waitForEvent(); //wait for event

                if (eventName == null) {
                    continue;
                }

                if (localLOGV) Slog.v(TAG, "get event " + eventName);

                /*
                 * Map event name into event enum
                 */
                i = 0;
                while (i < eventName.length()) {
                    index = eventName.substring(i).indexOf(":");
                    if (index == -1)
                        break;
                    dev = eventName.substring(i, index);
                    i += index + 1;
                    index = eventName.substring(i).indexOf(":");
                    if (index == -1)
                        break;
                    cmd = Integer.parseInt(eventName.substring(i, i+index));
                    i += index + 1;
                    //dev 指eth0, cmd 是event参数。  
                    if (localLOGV) Slog.v(TAG, "dev: " + dev + " ev " + cmd);
                    switch (cmd) {
                        case DEL_LINK: //断开连接
                            handleEvent(dev, DISCONNECTED);
                            break;
                        case ADD_ADDR:  //添加IP address,即链接成功
                            handleEvent(dev, CONNECTED);
                            break;
                        case NEW_LINK:  //phy up 状态
                            handleEvent(dev, PHYUP);
                            break;
                    }
                }
            }
        }


b. handleEvent(String ifname,int event)

        /**
         * Handle all supplicant events except STATE-CHANGE
         * @param event the event type
         * @param remainder the rest of the string following the
         * event name and " — "
         */
        void handleEvent(String ifname,int event) {
            switch (event) {
                case DISCONNECTED:
                    mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.DISCONNECTED);
                    break;
                case CONNECTED:
                    mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.CONNECTED);
                    break;
                case PHYUP:
                    mTracker.notifyPhyConnected(ifname);
                    break;
                default:
                    mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.FAILED);
                    break;
            }
        }

c. EthernetStateTraker.notifyStateChange():

    public void notifyStateChange(String ifname,DetailedState state) {
        if (localLOGV) Slog.i(TAG, "report new state " + state.toString() + " on dev " + ifname);
        if (ifname.equals(mInterfaceName)) { //判断eth0名称是否正确
            if (localLOGV) Slog.v(TAG, "update network state tracker");
            synchronized(this) { //发送 Connected or Disconnected 消息
                this.sendEmptyMessage(state.equals(DetailedState.CONNECTED)
                    ? EVENT_HW_CONNECTED : EVENT_HW_DISCONNECTED);
            }
        }
    }

d. EthernetStateTraker.notifyPhyConnected():

    public void notifyPhyConnected(String ifname) {
        if (localLOGV) Slog.v(TAG, "report interface is up for " + ifname);
        synchronized(this) { //发送Phy connected 消息
            this.sendEmptyMessage(EVENT_HW_PHYCONNECTED); 
        }
    }


2. 发送消息之后,EthernetStateTraker 会handleMessage():

    public void handleMessage(Message msg) {

        synchronized (this) {
            switch (msg.what) {
            case EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:  //连接成功
                if (localLOGV) Slog.i(TAG, "received configured succeeded, stack=" + mStackConnected + " HW=" + mHWConnected);
                mStackConnected = true;
                if (mHWConnected)
                    setState(true, msg.what);
                break;
            case EVENT_INTERFACE_CONFIGURATION_FAILED:  //链接失败
                mStackConnected = false;
                //start to retry ?
                break;
            case EVENT_HW_CONNECTED:  //HW连接上了
                if (localLOGV) Slog.i(TAG, "received HW connected, stack=" + mStackConnected + " HW=" + mHWConnected);
                mHWConnected = true;
                if (mStackConnected)
                    setState(true, msg.what);
                break;
            case EVENT_HW_DISCONNECTED: //hw断开
                if (localLOGV) Slog.i(TAG, "received disconnected events, stack=" + mStackConnected + " HW=" + mHWConnected);
                setState(false, msg.what);
                break;
            case EVENT_HW_PHYCONNECTED: //phy 连上
                if (localLOGV) Slog.i(TAG, "interface up event, kick off connection request");
                if (!mStartingDhcp) {
                    int state = mEM.getState();
                    if (state != mEM.ETHERNET_STATE_DISABLED) {
                        EthernetDevInfo info = mEM.getSavedConfig(); //获得以前已有的连接IP
                        if (info != null && mEM.isConfigured()) {
                            try {
                                configureInterface(info); //配置IP
                            } catch (UnknownHostException e) {
                                 // TODO Auto-generated catch block
                                 //e.printStackTrace();
                                 Slog.e(TAG, "Cannot configure interface");
                            }
                        }
                    }
                }

                setState(true, msg.what);
                break;
            }
        }
    }

3. setState(boolean state, int event):

    private void setState(boolean state, int event) {
        if (mNetworkInfo.isConnected() != state) {
            if (state) { //connected or disconnected.
                mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
            } else {
                mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null);
                stopInterface(true);
            }
            mNetworkInfo.setIsAvailable(state);
            postNotification(event);
        }
    }

a. stopInterface():

    /**
     * Stop etherent interface
     * @param suspend {@code false} disable the interface {@code true} only reset the connection without disable the interface
     * @return true
     */
    public boolean stopInterface(boolean suspend) {
        if (mEM != null) {

            EthernetDevInfo info = mEM.getSavedConfig();
            if (info != null && mEM.isConfigured()) {
                synchronized (mDhcpTarget) {
                    mInterfaceStopped = true;
                    if (localLOGV) Slog.i(TAG, "stop dhcp and interface");

                    // stop DhcpHandler Looper
                    mDhcpTarget.removeMessages(EVENT_DHCP_START);
                    String ifname = info.getIfName(); // eth0

                    if (!NetworkUtils.stopDhcp(ifname)) { //stop dhcpcd_eth0 service
                        if (localLOGV) Slog.w(TAG, "Could not stop DHCP");
                    }

                    //reset eth0, remove route and ip
                    NetworkUtils.resetConnections(ifname, NetworkUtils.RESET_ALL_ADDRESSES);
                    NetworkUtils.removeDefaultRoute(ifname);
                    mStartingDhcp = false;

                    if (!suspend) // if suspend = false, turn eth0 to down.
                        NetworkUtils.disableInterface(ifname);

                    mLinkProperties.clear();
                }
            }
        }
        return true;
    }

b.  postNotification(int event), 给ConnectivityService 发送 event state changed 消息.

    private void postNotification(int event) {
        Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, new NetworkInfo(mNetworkInfo));
        msg.sendToTarget();
    }

4. configureInterface(EthernetDevInfo info),  配置 IP 函数:

    private boolean configureInterface(EthernetDevInfo info) throws UnknownHostException {
        mStackConnected = false;
        mHWConnected = false;
        mInterfaceStopped = false;
        mStartingDhcp = true;

      //DHCP 方式获得 IP
      if (info.getConnectMode().equals(EthernetDevInfo.ETHERNET_CONN_MODE_DHCP)) {
            if (localLOGV) Slog.i(TAG, "trigger dhcp for device " + info.getIfName());
            sDnsPropNames = new String[] {
                "dhcp." + mInterfaceName + ".dns1",
                "dhcp." + mInterfaceName + ".dns2"
             };

            mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);
        } else {  //static IP 设置方式
            int event;
            sDnsPropNames = new String[] {
                "net." + mInterfaceName + ".dns1",
                "net." + mInterfaceName + ".dns2"
             };

             //从输入栏获取 ip, gateway, netmask, dns 值
             mDhcpInfo1.ipAddress = lookupHost(info.getIpAddress()); 
             mDhcpInfo1.gateway = lookupHost(info.getRouteAddr()); 
             mDhcpInfo1.netmask = lookupHost(info.getNetMask());
             mDhcpInfo1.dns1 = lookupHost(info.getDnsAddr());
             mDhcpInfo1.dns2 = 0;
             if (localLOGV) Slog.i(TAG, "set ip manually " + mDhcpInfo1.toString());

             //配置之前擦除以前的route
             NetworkUtils.removeDefaultRoute(info.getIfName()); 

             //配置成功
             if (NetworkUtils.configureInterface(info.getIfName(), mDhcpInfo1)) {
             event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;
             SystemProperties.set("net.dns1", info.getDnsAddr());
             SystemProperties.set("net." + info.getIfName() + ".dns1", info.getDnsAddr());
             SystemProperties.set("net." + info.getIfName() + ".dns2", "0.0.0.0");

             if (localLOGV)
                  Slog.v(TAG, "Static IP configuration succeeded");
             } else { //配置失败
                  event = EVENT_INTERFACE_CONFIGURATION_FAILED;
                  if (localLOGV) Slog.w(TAG, "Static IP configuration failed");
             }
             this.sendEmptyMessage(event); //给EthernetStateTracker发送message
         }
         return true;
    }



5. resetInterface(), 这个和stopInterface 差不多:

    /**
     * reset ethernet interface
     * @return true
     * @throws UnknownHostException
     */
    public boolean resetInterface()  throws UnknownHostException{
        /*
         * This will guide us to enabled the enabled device
         */
        if (mEM != null) {
            EthernetDevInfo info = mEM.getSavedConfig();
            if (info != null && mEM.isConfigured()) {
                synchronized (this) {
                    mInterfaceName = info.getIfName();
                    if (localLOGV) Slog.i(TAG, "reset device " + mInterfaceName);
                    NetworkUtils.resetConnections(mInterfaceName, NetworkUtils.RESET_ALL_ADDRESSES);
                     // Stop DHCP
                    if (mDhcpTarget != null) {
                        mDhcpTarget.removeMessages(EVENT_DHCP_START);
                    }
                    if (!NetworkUtils.stopDhcp(mInterfaceName)) {
                        if (localLOGV) Slog.w(TAG, "Could not stop DHCP");
                    }
                    mLinkProperties.clear();
                    configureInterface(info); //比stopInterface 多了一步 重新配置IP。
                }
            }
        }
        return true;
    }






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值