android系統 Ethernet 解析

在公司一款產品上需要需要添加有線網口,所以系統需要做相應的支持,找到一個支持的有線網口的系統,將其中軟件部分做簡單分析:

首先:功能方面,要能夠設置有線網絡的IP地址,子網掩碼,網關,DNS等信息,這些功能由 Etnernet 這個 APP實現;

系統方面,對於已經設置好的信息,斷電重啓之後不能丟失,還能繼續保持有效,所以需要添加一個系統服務 EthernetService


其次,EthernetService的啓動入口, \frameworks\base\services\java\com\android\server\ConnectivityService.java 其構造類

public ConnectivityService(Context context, INetworkManagementService netManager,
            INetworkStatsService statsService, INetworkPolicyManager policyManager,
            NetworkFactory netFactory)

for (int targetNetworkType : mPriorityList) {
           final NetworkConfig config = mNetConfigs[targetNetworkType];
           final NetworkStateTracker tracker;
           try {
tracker = netFactory.createTracker(targetNetworkType, config);
mNetTrackers[targetNetworkType] = tracker;
if (targetNetworkType == ConnectivityManager.TYPE_ETHERNET) {
EthernetService ethernet = new EthernetService(context, (EthernetStateTracker)tracker);
ServiceManager.addService(Context.ETH_SERVICE, ethernet);

}
Slog.d(TAG, "*******targetNetworkType="+targetNetworkType);
           } catch (IllegalArgumentException e) {
               Slog.e(TAG, "Problem creating " + getNetworkTypeName(targetNetworkType)
                       + " tracker: " + e);
               continue;
           }

           tracker.startMonitoring(context, mTrackerHandler); 

           
           if (config.isDefault()) {
               tracker.reconnect();
           }
       }


上面的黑體字代碼是實現Ethernet 功能的核心,具體分析如下

1. tracker = netFactory.createTracker(targetNetworkType, config); 

創建 網絡狀態追蹤器 

@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();
return new EthernetStateTracker(targetNetworkType, config.name);
               default:
                   throw new IllegalArgumentException(
                           "Trying to create a NetworkStateTracker for an unknown radio type: "
                           + config.radio);
           }
       }
   }    

2. 創建並添加網絡服務

EthernetService ethernet = new EthernetService(context, (EthernetStateTracker)tracker);
ServiceManager.addService(Context.ETH_SERVICE, ethernet);


    \frameworks\base\services\java\com\android\server\EthernetService.java


private int mEthState= EthernetManager.ETH_STATE_UNKNOWN;
//public static final int ETH_STATE_UNKNOWN = 0;

public EthernetService(Context context, EthernetStateTracker Tracker){
       mTracker = Tracker;
       mContext = context;

       isEthEnabled = getPersistedState();
       Slog.v(TAG,"Ethernet dev enabled " + isEthEnabled );
    getDeviceNameList();
    setEthState(isEthEnabled);
       //registerForBroadcasts();
       Slog.v(TAG, "Trigger the ethernet monitor");
       mTracker.StartPolling();
       mDelayedHandler = new Handler();  
       isEthernetServiceInited = true;
   }

其核心是 setEthState,即開關網絡


3.  tracker.startMonitoring(context, mTrackerHandler); 

啓動網絡狀態監控,核心是

frameworks\base\ethernet\java\android\net\ethernet\EthernetMonitor.java

   class MonitorThread extends Thread {


        public MonitorThread() {
            super("EthMonitor");
        }


        public void run() {
            int index;
            int i;


            //noinspection InfiniteLoopStatement
            for (;;) {
                if (DEBUG) Slog.i(TAG, "go poll events");
                String eventName = EthernetNative.waitForEvent();


                if (eventName == null) {
                    continue;
                }
                if (DEBUG) Slog.i(TAG, "got event " + eventName);
                /*
                 * Map event name into event enum
                 */
                String [] events = eventName.split(":");
                index = events.length;
                if (index < 2)
                    continue;
                i = 0;
                while (index != 0 && i < index-1) {


                    int event = 0;
                    if (DEBUG) Slog.i(TAG,"dev: " + events[i] + " ev " + events[i+1]);
                    int cmd =Integer.parseInt(events[i+1]);
                    if ( cmd == DEL_LINK) {
                        event = DISCONNECTED;
                        handleEvent(events[i],event);
                    }
                    else if (cmd == ADD_ADDR ) {
                        event = CONNECTED;
                        handleEvent(events[i],event);
                    } else if (cmd == NEW_LINK) {
                        event = PHYUP;
                        handleEvent(events[i],event);
                    }
                    i = i + 2;
                }
            }
        }
        /**
         * Handle all supplicant events except STATE-CHANGE
         * @param event the event type
         * @param remainder the rest of the string following the
         * event name and &quot;&#8195;&#8212;&#8195;&quot;
         */
        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);
            }
        }


監控程序啓動一個線程,調用native方法  String eventName = EthernetNative.waitForEvent();

通過 handleEvent(events[i],event);  將不同的網絡狀態消息傳到 mTracker ,mTracker對消息作出響應


4. 實現真正的網絡設置,

tracker.reconnect();  其核心是 EthernetStateTracker ->resetInterface,在調用本地方法,

system/core/libnetutils/ifc_utils.c

(libcutils---ifc_utils.c)int ifc_reset_connections(const char *ifname, const int reset_mask)


這個文件還包含一些網絡接口,詳見 另一篇博客

http://blog.csdn.net/liufuliang163/article/details/72729901


上面提到的相關代碼:

http://download.csdn.net/detail/liufuliang163/9853456


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章