android Ethernet移植小記

android網絡代碼主要都在/framewrok/base下面,其中網絡的配置在frameworks\base\core\res\res\values\config.xml中。

1.
在 ConnectivityManager.java 中定義的有以下類型:
    public static final int TYPE_MOBILE      = 0;
    public static final int TYPE_WIFI        = 1;
    public static final int TYPE_MOBILE_MMS  = 2;
    public static final int TYPE_MOBILE_SUPL = 3;
    public static final int TYPE_MOBILE_DUN  = 4;
    public static final int TYPE_MOBILE_HIPRI = 5;
    
    public static final int TYPE_WIMAX = 6;
    
    /* 這是在機頂盒上爲android系統添加的網絡類型 */
    public static final int TYPE_PPPOE = 7;
    public static final int TYPE_ETHERNET = 8;
    public static final int TYPE_CABLEMODEM = 9;

    
2.系統對網絡的判斷大多都是在 ConnectivityService.java中處理的,用戶操做的類是 ConnectivityManager.java 經過aidl訪問
     ConnectivityService.java提供的服務。而啓動在SystemServer.java中:
 
try {  
    Slog.i(TAG, "Connectivity Service");  
    connectivity = ConnectivityService.getInstance(context);  
    ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);  
    } catch (Throwable e) {  
    Slog.e(TAG, "Failure starting Connectivity Service", e);  
    }

3.啓動以後再ConnectivityService構造函數裏會判斷是哪一種類型:
    注:這裏我就用Ethernet網線接口分析,cable貓的流程相似網線和wifi的。
...
    case ConnectivityManager.TYPE_ETHERNET:          
        if (DBG) Slog.v(TAG, "Starting Ethernet Service.");
            EthernetStateTracker est = new EthernetStateTracker(context, mHandler);
            EthernetService ethService = new EthernetService(context, est);
        ServiceManager.addService(Context.ETHERNET_SERVICE, ethService);
        ethService.startEthernet();
        mNetTrackers[ConnectivityManager.TYPE_ETHERNET] = est;
        est.startMonitoring();              
        
    break;    
    ...

    
4.new EthernetStateTracker對象時會初始化一個對應的監聽線程和消息handler等:
 
mMonitor = new EthernetMonitor(this);    
    mDhcpTarget = new DhcpHandler(dhcpThread.getLooper(), this);    
        
    new EthernetService(context, est)會啓動剛開始那個監聽線程,不停的向android_net_ethernet.cpp獲取
    String eventName = EthernetNative.waitForEvent();
    而後處理,發送對應的消息handleEvent(String ifname,int event)
    ...
    ethService.startEthernet();//這裏會跟着設置網絡獲取模式有dhcp方式和手動設置的靜態方式
    ---> setEthernetEnabled(2);//方法在EthernetService.java
             --->mTracker.startDhcpMode();//startDhcpMode這個方法EthernetStateTracker.java
    ...
    est.startMonitoring();//真正啓動,reset下
    --->resetInterface();
        --->mInterfaceName = info.getIfName();//獲得設備名字如:eth0
        若是以前的有地址,這發送消息remove掉
        mDhcpTarget.removeMessages(EVENT_DHCP_START);
        以後從新配置:
        configureInterface(info);
            這個接口裏有2種方式:
            if (info.getConnectMode().equals(EthernetDevInfo.ETHERNET_CONN_MODE_DHCP)) {
            Slog.i(TAG, "trigger dhcp for device " + info.getIfName());
            mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);
            } else {
                //手動配置
            }
        配置完了以後發送一個消息
        this.sendEmptyMessage(event);    
        這個消息處理在handleMessage裏。注意這裏下面還有一個DhcpHandler內部類也是消息處理,區分時看前面的調用對象

    
5.此時,java部分配置已大部分完成,而那個Monitor監聽線程在不停的獲取
    EthernetNative.waitForEvent();
    到C++層
    android_net_ethernet_waitForEvent中獲得,返回形式如:eth0:20:
    20表示connected,而後發送成功消息:
  
case EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:
                Slog.i(TAG, "received configured succeeded, stack=" + mStackConnected + " HW=" + mHWConnected);
                /**send enabled*/
                final Intent succIntent = new Intent(EthernetManager.ETHERNET_STATE_CHANGED_ACTION);
                succIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
            succIntent.putExtra(EthernetManager.EXTRA_ETHERNET_STATE, EthernetManager.ETHERNET_STATE_ENABLED);
            mContext.sendStickyBroadcast(succIntent);
                mStackConnected = true;
                if (mHWConnected)
                    setEthState(true, msg.what);

    若是mHWConnected這個值爲true的話:
private void setEthState(boolean state, int event) {
        
        Slog.d(TAG,"mNetworkInfo.isConnected() = "+mNetworkInfo.isConnected() +"state = "+state);
        
        if (mNetworkInfo.isConnected() != state) {
            if (state) {
                setDetailedState(DetailedState.CONNECTED);
                //mTarget.sendEmptyMessage(EVENT_CONFIGURATION_CHANGED);
                Message msg = mTarget.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo);
                msg.sendToTarget();
            } else {
                setDetailedState(DetailedState.DISCONNECTED);
                stopInterface(true);
            }
            mNetworkInfo.setIsAvailable(state);
            postNotification(event);
        }
    }


6.以後回到ConnectivityService.java中,會發送一個消息爲NetworkStateTracker.EVENT_STATE_CHANGED調用
 
else if (state == NetworkInfo.State.CONNECTED) {
       handleConnect(info);
  }
................ 大體就這樣,若是cable modem或wifi獲取的應該差很少 O(∩_∩)O~
相關文章
相關標籤/搜索