android ethernet

来源:互联网 发布:阿里云的机房 编辑:程序博客网 时间:2024/05/01 02:07

Lamdoc船长的宝藏http://blog.csdn.net/lamdoc/article/category/1164160

android ethernet unplug/plug enable/disable 管理

android ethernet 管理, 可以分为两类:


1. 是网线插拔,unplug/plug。

unplug 时, eth0 可以up, 但是IP 必须为0, 因为打开internel时,必须快速出现连不上页面,而不是延迟好几十秒,才出现连不上。

plug in之后,IP 能自动恢复。


2. 是Setting里EthernetConfiguration 的勾选项。enable/disable。

disable ethernet 时, eth0 必须是down的, enable之后,才up,然后能自动恢复IP。


3. 是static ip configuration


IP

NETMASK

DNS

GATEWAY

4个IP选项,静态IP设置。

android ethernet 设计的几个模块

分类: Android ethernet 218人阅读 评论(0)收藏 举报

ethernet related files:

1. packages/app/Settings/:    //Setting中添加选项代码
packages/apps/Settings/src/com/android/settings/ethernet/EthernetSettings.java
packages/apps/Settings/src/com/android/settings/ethernet/EthernetEnabler.java
packages/apps/Settings/src/com/android/settings/ethernet/EthernetConfigDialog.java


2. frameworks/base/ :

SystemUI:   //状态栏(status_bar)显示部分代码
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java    //现实statusbar

ConnectivityService:
frameworks/base/services/java/com/android/server/ConnectivityService.java   //这里是ethernet部分程序的起始点

jni:
frameworks/base/core/jni/android_net_ethernet.cpp  //新加的一些jni

本来就有的ethernet:
frameworks/base/services/java/com/android/server/EthernetService.java
frameworks/base/services/java/com/android/server/NetworkManagementService.java
frameworks/base/core/java/android/net/NetworkStats.java

新添加的ethernet:
frameworks/base/ethernet/*  // 这是主要ethernet部分,java api 代码。
frameworks/base/ethernet/java/android/net/ethernet/EthernetManager.java

调试android ethernet 的常用命令

分类: Android ethernet 124人阅读 评论(0)收藏 举报
1. netcfg

netcfg   //查看ip情况

netcfg eth0 up dhcp   //通过dhcp 自动获取ip和网关

2. ifconfig

ifconfig eth0 128.224.156.81 up

ifconfig eth0 128.224.156.81 netmask 255.255.255.0 up

3. gateway 配置

route add default gw 192.168.0.1 dev eth0

4. dns 配置

echo "nameserver 128.224.160.11" > resolv.conf

nameserver 128.224.160.11


setprop net.dns1 128.224.160.11

setprop net.dns2 147.11.100.30

4. mac adddr
ifconfig eth0 hw ether 00:11:22:33:44:55

android ethernet的2个辅助模块 libnetutils 和 dhcpcd

1. 一个是 system/core/libnetutils/* ,  即libnetutils.so 库. 这里面有两个.c经常会调用到

ifc_utils.c

dhcp_utils.c 


java会 通过 JNI (CPP)再调用到 C代码


2. 第二个是 /external/dhcpcd/*, 生成/system/bin/dhcpcd.

这个是 守护进程 dhcpcd_eth0 会用到的工具。

ConnectivityService 中调用 EthernetStateTracker 和 EthernetService

分类: Android ethernet 342人阅读 评论(2)收藏 举报

u最近在研究android 中的 ethernet 部分,主要集中在上层JAVA service 和java api。

整个 android 系统的mobile, wifi,wimax 和 bluetooth 都是通过ConnectivitySerivice 来提供服务的。
android本身不自带ethernet服务,需要新加 android-x86 里拿的ics-ethernet patch。

接下来分析 ConnectivityService 是怎么提供 ethernet 服务的。


1. 最开始,ConnectivityService 中会创建 EthernetStateTracker 和 EthernetService。
frameworks/base/services/java/com/android/server/ConnectivityService.java:

[java] view plaincopyprint?
  1.     case ConnectivityManager.TYPE_ETHERNET:  
  2.                     //mNetTrackers[netType] = EthernetDataTracker.getInstance();  
  3.                     //mNetTrackers[netType].startMonitoring(context, mHandler);  
  4.                     if(DBG) log("Starting Ethernet Service.");  
  5.                     //创建 EthernetStateTracker  
  6.                     EthernetStateTracker est=new EthernetStateTracker(context, mHandler);    
  7.                       
  8.                     //创建EthernetService   
  9.                     EthernetService ethService=new EthernetService(context, est);  
  10.  <PRE class=java name="code">                    //向ServiceManager 中添加 ETHERNET_SERVICE 服务  
  11.                     ServiceManager.addService(Context.ETHERNET_SERVICE, ethService);   
  12.   
  13.                     mNetTrackers[ConnectivityManager.TYPE_ETHERNET]= est; //赋值EthernetStateTracker.  
  14.                       
  15.                     //调用EthernetStateTracker 的startMonitoring  
  16.                     est.startMonitoring(context, mHandler);    
  17.                     break;</PRE>  
  18. <PRE></PRE>  
  19. <P></P>  
  20. <P style="BACKGROUND-COLOR: rgb(255,255,255)"><SPAN style="COLOR: #663300; FONT-SIZE: 16px"><STRONG><SPAN style="FONT-FAMILY: 宋体">a. mNetTrackers 定义:</SPAN></STRONG></SPAN></P>  
  21. <P></P>  
  22. <PRE class=java name="code">    /** 
  23.      * Sometimes we want to refer to the individual network state 
  24.      * trackers separately, and sometimes we just want to treat them 
  25.      * abstractly. 
  26.      */  
  27.     private NetworkStateTracker mNetTrackers[];    
  28.     //网络状态跟踪,no_connected, connecting, connected ,三种状态  
  29. </PRE><BR>  
  30. <P></P>  
  31. <SPAN style="FONT-FAMILY: 宋体"><SPAN style="FONT-SIZE: 12px"><SPAN style="COLOR: #990000"><STRONG><SPAN style="FONT-SIZE: 16px"><SPAN style="BACKGROUND-COLOR: rgb(255,255,255); COLOR: #663300">b. EthernetStateTracker.startMonitoring():</SPAN><BR>  
  32. </SPAN></STRONG></SPAN></SPAN></SPAN><PRE class=java name="code">    public void startMonitoring(Context context, Handler target) {  
  33.         if (localLOGV) Slog.v(TAG,"start to monitor the ethernet devices");  
  34.         if (mServiceStarted) {  //获得systemService 中 ethernet_service的上下文  
  35.             mEM = (EthernetManager)context.getSystemService(Context.ETHERNET_SERVICE);  
  36.             mContext = context;  
  37.             mCsHandler = target;  
  38.   
  39.             int state = mEM.getState();  
  40.             if (state != mEM.ETHERNET_STATE_DISABLED) {  
  41.                 if (state == mEM.ETHERNET_STATE_UNKNOWN) {  
  42.                     // maybe this is the first time we run, so set it to enabled  
  43.                     mEM.setEnabled(mEM.getDeviceNameList() != null);  //set mEM to enabled.  
  44.                 } else {  
  45.                     try {  
  46.                         //if it's not the first time we run, reset the interface.     
  47.                         resetInterface();  
  48.                     } catch (UnknownHostException e) {  
  49.                         Slog.e(TAG, "Wrong ethernet configuration");  
  50.                     }  
  51.                 }  
  52.             }  
  53.         }  
  54.     }  
  55.   
  56. </PRE><SPAN style="COLOR: #ff0000"><STRONG><SPAN style="FONT-SIZE: 16px"><BR>  
  57. 2.  创建 EthernetStateTracker :</SPAN></STRONG></SPAN><SPAN style="FONT-SIZE: 16px"><BR>  
  58. </SPAN>frameworks/base/ethernet/java/android/net/ethernet/EthernetStateTracker.java<BR>  
  59. <BR>  
  60. <DIV id=codeText class=codeText><PRE class=java name="code">    public EthernetStateTracker(Context context, Handler target){  
  61.   
  62.             //创建 NetworkInfo,可以用来查看网络状况   
  63.             mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0,"ETH","");  
  64.    
  65.             mLinkProperties = new LinkProperties();  //网络链接属性  
  66.   
  67.             if (localLOGV) Slog.v(TAG,"Starts...");  
  68.   
  69.             //EthernetNative 通过 JNI 调用到 libnetutil.so 中去了。  
  70.             if (EthernetNative.initEthernetNative()!= 0){    
  71.                 Slog.e(TAG,"Can not init ethernet device layers");  
  72.                 return;  
  73.             }  
  74.   
  75.             if (localLOGV) Slog.v(TAG,"Successed");  
  76.   
  77.             mServiceStarted = true;  
  78.   
  79.             //创建 DHCP 线程   
  80.             HandlerThread dhcpThread = new HandlerThread("DHCP Handler Thread");  
  81.             dhcpThread.start();  
  82.             mDhcpTarget = new DhcpHandler(dhcpThread.getLooper(),this);  
  83.             mMonitor = new EthernetMonitor(this); //创建 EthernetMonitor  
  84.             mDhcpInfo = new DhcpInfoInternal();   //创建 DhcpInfoInternal, 用来描述DHCP IP配置              
  85.             mDhcpInfo1 = new DhcpInfo();          //创建DhcpInfo, 用来描述static ip 配置   
  86.  }</PRE><BR>  
  87. <SPAN style="COLOR: #663300; FONT-SIZE: 16px"><STRONG>a.   DhcpHandler(): <SPAN style="FONT-SIZE: 12px">  
  88. 这个类不知道干啥的。。</SPAN></STRONG></SPAN><BR>  
  89. <PRE class=java name="code">    private class DhcpHandler extends Handler {  
  90.          public DhcpHandler(Looper looper, Handler target) {   
  91.              super(looper);  
  92.              mTrackerTarget = target; //赋值mTrackerTarget.  
  93.          }  
  94. </PRE><BR>  
  95. <SPAN style="COLOR: #663300; FONT-SIZE: 16px"><STRONG>b.   EthernetMonitor(): 这个会单独介绍<BR>  
  96. <BR>  
  97. c.   DhcpInfoInternal(): 这个应该是DhcpInfo的新一代。</STRONG></SPAN><BR>  
  98. frameworks/base/core/java/android/net/DhcpInfoInternal.java<BR>  
  99. <BR>  
  100. <PRE class=java name="code">/** 
  101.  * A simple object for retrieving the results of a DHCP request. 
  102.  * Replaces (internally) the IPv4-only DhcpInfo class. 
  103.  * @hide 
  104.  */  
  105. public class DhcpInfoInternal {  
  106.     private final static String TAG = "DhcpInfoInternal";  
  107.     public String ipAddress;  
  108.     public int prefixLength;  
  109.   
  110.     public String dns1;  
  111.     public String dns2;  
  112.   
  113.     public String serverAddress;  
  114.     public int leaseDuration;  
  115.   
  116.     private Collection<RouteInfo> mRoutes;  
  117. </PRE><BR>  
  118. <SPAN style="COLOR: #663300; FONT-SIZE: 16px"><STRONG>d. DhcpInfo 类内容明显 和 DhcpInfoInternal 不同:</STRONG></SPAN><BR>  
  119. frameworks/base/core/java/android/net/DhcpInfo.java<BR>  
  120. <PRE class=java name="code">/** 
  121.  * A simple object for retrieving the results of a DHCP request. 
  122.  */  
  123. public class DhcpInfo implements Parcelable {  
  124.     public int ipAddress;  
  125.     public int gateway;  
  126.     public int netmask;  
  127.   
  128.     public int dns1;  
  129.     public int dns2;  
  130.   
  131.     public int serverAddress;  
  132.     public int leaseDuration;  
  133.   
  134. </PRE><BR>  
  135. <BR>  
  136. </DIV>  
  137. <SPAN style="COLOR: #f00000; FONT-SIZE: 16px"><STRONG>3.    <SPAN style="FONT-FAMILY: 宋体">  
  138. 创建 </SPAN><SPAN style="FONT-FAMILY: 宋体">EthernetService</SPAN></STRONG></SPAN><SPAN style="FONT-SIZE: 16px">:</SPAN><BR>  
  139. frameworks/base/services/java/com/android/server/EthernetService.java<BR>  
  140. <BR>  
  141. <PRE class=java name="code">    public EthernetService(Context context, EthernetStateTracker Tracker){  
  142.             mTracker = Tracker;  
  143.             mContext = context;   
  144.             isEnabled = getPersistedState();  
  145.             if (localLOGV==true) Slog.i(TAG,"Ethernet dev enabled "+ isEnabled);  
  146.             getDeviceNameList();  //从驱动获得设备表  
  147.             setState(isEnabled);  //设置 enabled 状态  
  148.             Slog.d(TAG,"xxha: ---------------------- StartPolling()");  
  149.             mTracker.StartPolling(); //开始监听驱动层的事件信号  
  150.         }</PRE><BR>  
  151. <SPAN style="COLOR: #663300"><STRONG><SPAN style="FONT-SIZE: 16px">a. getDeviceNameList() :</SPAN></STRONG></SPAN><BR>  
  152. <PRE class=java name="code">    /** 
  153.      * get all the ethernet device names 
  154.      * @return interface name list on success, {@code null} on failure 
  155.      */  
  156.     public String[] getDeviceNameList() {  
  157.         return (scanDevice() > 0) ? DevName : null;  //扫描设备  
  158.     }  
  159. </PRE><BR>  
  160. <PRE class=java name="code">    private int scanDevice() {  
  161.         int i, j;  
  162.         if ((i = EthernetNative.getInterfaceCnt()) == 0)  
  163.             return 0;  
  164.   
  165.         DevName = new String[i];  
  166.   
  167.         for (j = 0; j < i; j++) {  
  168.             DevName[j] = EthernetNative.getInterfaceName(j); //获取设备名eth0,sit0  
  169.             if (DevName[j] == null)  
  170.                 break;  
  171.             if (localLOGV) Slog.v(TAG, "device " + j + " name " + DevName[j]);  
  172.         }  
  173.   
  174.         return i;  
  175.     }  
  176. </PRE><SPAN style="COLOR: #663300"><STRONG><SPAN style="FONT-SIZE: 16px"><BR>  
  177. b.  mTracker.StartPolling()</SPAN></STRONG></SPAN><BR>  
  178. <PRE class=java name="code">    public void StartPolling() {  
  179.         mMonitor.startMonitoring(); //这个也会调到EthernetMonitor 中的 startMonitoring() 去。  
  180.     }  
  181. </PRE><BR>  
  182. <BR>  
  183. <BR>  
  184. <BR>  
  185. <SPAN style="FONT-FAMILY: 宋体"><BR>  
  186. <BR>  
  187. </SPAN>  
  188. <P></P>  
  189. <PRE></PRE> 

    EthernetMornitor 与 EthernetStateTracker

    分类: Android ethernet 173人阅读 评论(0)收藏 举报

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

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

    1. EthernetMonitor :

    [java] view plaincopyprint?
    1. /** 
    2.  * Listens for events from kernel, and passes them on 
    3.  * to the {@link EtherentStateTracker} for handling. Runs in its own thread. 
    4.  * 
    5.  * @hide 
    6.  */  
    7. public class EthernetMonitor {  
    8.     private static final String TAG = "EthernetMonitor";  
    9.     private static final int CONNECTED = 1;  
    10.     private static final int DISCONNECTED = 2;  
    11.     private static final int PHYUP = 3;  
    12.     private static final String connectedEvent = "CONNECTED";  
    13.     private static final String disconnectedEvent = "DISCONNECTED";  
    14.     private static final int ADD_ADDR = 20;  
    15.     private static final int RM_ADDR = 21;  
    16.     private static final int NEW_LINK = 16;  
    17.     private static final int DEL_LINK = 17;  
    18.     private static final boolean localLOGV = false;  
    19.   
    20.     private EthernetStateTracker mTracker;  
    21.   
    22.     //EthernetMonitor 是 EthernetStateTraker 的一个辅助  
    23.     public EthernetMonitor(EthernetStateTracker tracker) {  
    24.         mTracker = tracker;  
    25.     }  

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

    [java] view plaincopyprint?
    1. public void startMonitoring() {  
    2.     new MonitorThread().start(); //线程开始  
    3. }  
    4.   
    5. class MonitorThread extends Thread {  
    6.     public MonitorThread() {  
    7.         super("EthMonitor");  
    8.     }  
    9.   
    10.     public void run() {  
    11.         //noinspection InfiniteLoopStatement  
    12.         for (;;) {     //不断的在监听 kernel event  
    13.             int index;  
    14.             int i;  
    15.             int cmd;  
    16.             String dev;  
    17.   
    18.             if (localLOGV) Slog.v(TAG, "go poll events");  
    19.   
    20.             String eventName = EthernetNative.waitForEvent(); //wait for event  
    21.   
    22.             if (eventName == null) {  
    23.                 continue;  
    24.             }  
    25.   
    26.             if (localLOGV) Slog.v(TAG, "get event " + eventName);  
    27.   
    28.             /* 
    29.              * Map event name into event enum 
    30.              */  
    31.             i = 0;  
    32.             while (i < eventName.length()) {  
    33.                 index = eventName.substring(i).indexOf(":");  
    34.                 if (index == -1)  
    35.                     break;  
    36.                 dev = eventName.substring(i, index);  
    37.                 i += index + 1;  
    38.                 index = eventName.substring(i).indexOf(":");  
    39.                 if (index == -1)  
    40.                     break;  
    41.                 cmd = Integer.parseInt(eventName.substring(i, i+index));  
    42.                 i += index + 1;  
    43.                 //dev 指eth0, cmd 是event参数。    
    44.                 if (localLOGV) Slog.v(TAG, "dev: " + dev + " ev " + cmd);  
    45.                 switch (cmd) {  
    46.                     case DEL_LINK: //断开连接  
    47.                         handleEvent(dev, DISCONNECTED);  
    48.                         break;  
    49.                     case ADD_ADDR:  //添加IP address,即链接成功  
    50.                         handleEvent(dev, CONNECTED);  
    51.                         break;  
    52.                     case NEW_LINK:  //phy up 状态  
    53.                         handleEvent(dev, PHYUP);  
    54.                         break;  
    55.                 }  
    56.             }  
    57.         }  
    58.     }  


    b. handleEvent(String ifname,int event)

    [java] view plaincopyprint?
    1. /** 
    2.  * Handle all supplicant events except STATE-CHANGE 
    3.  * @param event the event type 
    4.  * @param remainder the rest of the string following the 
    5.  * event name and " — " 
    6.  */  
    7. void handleEvent(String ifname,int event) {  
    8.     switch (event) {  
    9.         case DISCONNECTED:  
    10.             mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.DISCONNECTED);  
    11.             break;  
    12.         case CONNECTED:  
    13.             mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.CONNECTED);  
    14.             break;  
    15.         case PHYUP:  
    16.             mTracker.notifyPhyConnected(ifname);  
    17.             break;  
    18.         default:  
    19.             mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.FAILED);  
    20.             break;  
    21.     }  
    22. }  

    c. EthernetStateTraker.notifyStateChange():

    [java] view plaincopyprint?
    1. public void notifyStateChange(String ifname,DetailedState state) {  
    2.     if (localLOGV) Slog.i(TAG, "report new state " + state.toString() + " on dev " + ifname);  
    3.     if (ifname.equals(mInterfaceName)) { //判断eth0名称是否正确  
    4.         if (localLOGV) Slog.v(TAG, "update network state tracker");  
    5.         synchronized(this) { //发送 Connected or Disconnected 消息  
    6.             this.sendEmptyMessage(state.equals(DetailedState.CONNECTED)  
    7.                 ? EVENT_HW_CONNECTED : EVENT_HW_DISCONNECTED);  
    8.         }  
    9.     }  
    10. }  

    d. EthernetStateTraker.notifyPhyConnected():

    [java] view plaincopyprint?
    1. public void notifyPhyConnected(String ifname) {  
    2.     if (localLOGV) Slog.v(TAG, "report interface is up for " + ifname);  
    3.     synchronized(this) { //发送Phy connected 消息  
    4.         this.sendEmptyMessage(EVENT_HW_PHYCONNECTED);   
    5.     }  
    6. }  


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

    [java] view plaincopyprint?
    1. public void handleMessage(Message msg) {  
    2.   
    3.     synchronized (this) {  
    4.         switch (msg.what) {  
    5.         case EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:  //连接成功  
    6.             if (localLOGV) Slog.i(TAG, "received configured succeeded, stack=" + mStackConnected + " HW=" + mHWConnected);  
    7.             mStackConnected = true;  
    8.             if (mHWConnected)  
    9.                 setState(true, msg.what);  
    10.             break;  
    11.         case EVENT_INTERFACE_CONFIGURATION_FAILED:  //链接失败  
    12.             mStackConnected = false;  
    13.             //start to retry ?  
    14.             break;  
    15.         case EVENT_HW_CONNECTED:  //HW连接上了  
    16.             if (localLOGV) Slog.i(TAG, "received HW connected, stack=" + mStackConnected + " HW=" + mHWConnected);  
    17.             mHWConnected = true;  
    18.             if (mStackConnected)  
    19.                 setState(true, msg.what);  
    20.             break;  
    21.         case EVENT_HW_DISCONNECTED: //hw断开  
    22.             if (localLOGV) Slog.i(TAG, "received disconnected events, stack=" + mStackConnected + " HW=" + mHWConnected);  
    23.             setState(false, msg.what);  
    24.             break;  
    25.         case EVENT_HW_PHYCONNECTED: //phy 连上  
    26.             if (localLOGV) Slog.i(TAG, "interface up event, kick off connection request");  
    27.             if (!mStartingDhcp) {  
    28.                 int state = mEM.getState();  
    29.                 if (state != mEM.ETHERNET_STATE_DISABLED) {  
    30.                     EthernetDevInfo info = mEM.getSavedConfig(); //获得以前已有的连接IP  
    31.                     if (info != null && mEM.isConfigured()) {  
    32.                         try {  
    33.                             configureInterface(info); //配置IP  
    34.                         } catch (UnknownHostException e) {  
    35.                              // TODO Auto-generated catch block  
    36.                              //e.printStackTrace();  
    37.                              Slog.e(TAG, "Cannot configure interface");  
    38.                         }  
    39.                     }  
    40.                 }  
    41.             }  
    42.   
    43.             setState(true, msg.what);  
    44.             break;  
    45.         }  
    46.     }  
    47. }  

    3. setState(boolean state, int event):

    [java] view plaincopyprint?
    1. private void setState(boolean state, int event) {  
    2.     if (mNetworkInfo.isConnected() != state) {  
    3.         if (state) { //connected or disconnected.  
    4.             mNetworkInfo.setDetailedState(DetailedState.CONNECTED, nullnull);  
    5.         } else {  
    6.             mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, nullnull);  
    7.             stopInterface(true);  
    8.         }  
    9.         mNetworkInfo.setIsAvailable(state);  
    10.         postNotification(event);  
    11.     }  
    12. }  

    a. stopInterface():

    [java] view plaincopyprint?
    1. /** 
    2.  * Stop etherent interface 
    3.  * @param suspend {@code false} disable the interface {@code true} only reset the connection without disable the interface 
    4.  * @return true 
    5.  */  
    6. public boolean stopInterface(boolean suspend) {  
    7.     if (mEM != null) {  
    8.   
    9.         EthernetDevInfo info = mEM.getSavedConfig();  
    10.         if (info != null && mEM.isConfigured()) {  
    11.             synchronized (mDhcpTarget) {  
    12.                 mInterfaceStopped = true;  
    13.                 if (localLOGV) Slog.i(TAG, "stop dhcp and interface");  
    14.   
    15.                 // stop DhcpHandler Looper  
    16.                 mDhcpTarget.removeMessages(EVENT_DHCP_START);  
    17.                 String ifname = info.getIfName(); // eth0  
    18.   
    19.                 if (!NetworkUtils.stopDhcp(ifname)) { //stop dhcpcd_eth0 service  
    20.                     if (localLOGV) Slog.w(TAG, "Could not stop DHCP");  
    21.                 }  
    22.   
    23.                 //reset eth0, remove route and ip  
    24.                 NetworkUtils.resetConnections(ifname, NetworkUtils.RESET_ALL_ADDRESSES);  
    25.                 NetworkUtils.removeDefaultRoute(ifname);  
    26.                 mStartingDhcp = false;  
    27.   
    28.                 if (!suspend) // if suspend = false, turn eth0 to down.  
    29.                     NetworkUtils.disableInterface(ifname);  
    30.   
    31.                 mLinkProperties.clear();  
    32.             }  
    33.         }  
    34.     }  
    35.     return true;  
    36. }  

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

    [java] view plaincopyprint?
    1. private void postNotification(int event) {  
    2.     Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, new NetworkInfo(mNetworkInfo));  
    3.     msg.sendToTarget();  
    4. }  

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

    [java] view plaincopyprint?
    1.     private boolean configureInterface(EthernetDevInfo info) throws UnknownHostException {  
    2.         mStackConnected = false;  
    3.         mHWConnected = false;  
    4.         mInterfaceStopped = false;  
    5.         mStartingDhcp = true;  
    6.   
    7.       //DHCP 方式获得 IP   
    8.       if (info.getConnectMode().equals(EthernetDevInfo.ETHERNET_CONN_MODE_DHCP)) {  
    9.             if (localLOGV) Slog.i(TAG, "trigger dhcp for device " + info.getIfName());  
    10.             sDnsPropNames = new String[] {  
    11.                 "dhcp." + mInterfaceName + ".dns1",  
    12.                 "dhcp." + mInterfaceName + ".dns2"  
    13.              };  
    14.   
    15.             mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);  
    16.         } else {  //static IP 设置方式  
    17.             int event;  
    18.             sDnsPropNames = new String[] {  
    19.                 "net." + mInterfaceName + ".dns1",  
    20.                 "net." + mInterfaceName + ".dns2"  
    21.              };  
    22.   
    23.              //从输入栏获取 ip, gateway, netmask, dns 值  
    24.              mDhcpInfo1.ipAddress = lookupHost(info.getIpAddress());   
    25.              mDhcpInfo1.gateway = lookupHost(info.getRouteAddr());   
    26.              mDhcpInfo1.netmask = lookupHost(info.getNetMask());  
    27.              mDhcpInfo1.dns1 = lookupHost(info.getDnsAddr());  
    28.              mDhcpInfo1.dns2 = 0;  
    29.              if (localLOGV) Slog.i(TAG, "set ip manually " + mDhcpInfo1.toString());  
    30.   
    31.              //配置之前擦除以前的route   
    32.              NetworkUtils.removeDefaultRoute(info.getIfName());   
    33.   
    34.              //配置成功   
    35.              if (NetworkUtils.configureInterface(info.getIfName(), mDhcpInfo1)) {  
    36.              event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;  
    37.              SystemProperties.set("net.dns1", info.getDnsAddr());  
    38.              SystemProperties.set("net." + info.getIfName() + ".dns1", info.getDnsAddr());  
    39.              SystemProperties.set("net." + info.getIfName() + ".dns2""0.0.0.0");  
    40.   
    41.              if (localLOGV)  
    42.                   Slog.v(TAG, "Static IP configuration succeeded");  
    43.              } else { //配置失败  
    44.                   event = EVENT_INTERFACE_CONFIGURATION_FAILED;  
    45.                   if (localLOGV) Slog.w(TAG, "Static IP configuration failed");  
    46.              }  
    47.              this.sendEmptyMessage(event); //给EthernetStateTracker发送message  
    48.          }  
    49.          return true;  
    50.     }  
    51.   
    52.   
    53.   
    54. <PRE></PRE><SPAN style="COLOR: #ff0000"><STRONG><SPAN style="FONT-SIZE: 16px">5. resetInterface(), 这个和stopInterface 差不多:</SPAN></STRONG></SPAN>  
    55. <P></P>  
    56. <P></P>  
    57. <PRE class=java name="code">    /** 
    58.      * reset ethernet interface 
    59.      * @return true 
    60.      * @throws UnknownHostException 
    61.      */  
    62.     public boolean resetInterface()  throws UnknownHostException{  
    63.         /* 
    64.          * This will guide us to enabled the enabled device 
    65.          */  
    66.         if (mEM != null) {  
    67.             EthernetDevInfo info = mEM.getSavedConfig();  
    68.             if (info != null && mEM.isConfigured()) {  
    69.                 synchronized (this) {  
    70.                     mInterfaceName = info.getIfName();  
    71.                     if (localLOGV) Slog.i(TAG, "reset device " + mInterfaceName);  
    72.                     NetworkUtils.resetConnections(mInterfaceName, NetworkUtils.RESET_ALL_ADDRESSES);  
    73.                      // Stop DHCP  
    74.                     if (mDhcpTarget != null) {  
    75.                         mDhcpTarget.removeMessages(EVENT_DHCP_START);  
    76.                     }  
    77.                     if (!NetworkUtils.stopDhcp(mInterfaceName)) {  
    78.                         if (localLOGV) Slog.w(TAG, "Could not stop DHCP");  
    79.                     }  
    80.                     mLinkProperties.clear();  
    81.                     configureInterface(info); //比stopInterface 多了一步 重新配置IP。  
    82.                 }  
    83.             }  
    84.         }  
    85.         return true;  
    86.     }  
    87. </PRE><BR>  
    88. <BR>  
    89. <P></P>  
    90. <PRE></PRE>  
    91. <PRE></PRE>  
    92. <PRE></PRE>  
    93. <PRE></PRE> 

    NetWorkUtils 和 android_net_NetUtils.cpp

    分类: Android ethernet 249人阅读 评论(0)收藏 举报

    EthernetStateTracker 中会,用到 NetWorkUtils 类中的一些函数, 这些函数,会调用JNI: android_net_NetUtils.cpp, 然后调到 libnetutils 库中去。

    如:

    NetworkUtils.disableInterface(ifname);

    NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo);

    NetworkUtils.stopDhcp(mInterfaceName);

    NetworkUtils.resetConnections(mInterfaceName, NetworkUtils.RESET_ALL_ADDRESSES);

    NetworkUtils.configureInterface(info.getIfName(), mDhcpInfo1);

    NetworkUtils.removeDefaultRoute(ifname);

    等等。


    1. NetworkUtils 类: frameworks/base/core/java/android/net/NetworkUtils.java

    [java] view plaincopyprint?
    1. /** 
    2.  * Native methods for managing network interfaces. 
    3.  * 
    4.  * {@hide} 
    5.  */  
    6. public class NetworkUtils {  
    7.   
    8.     private static final String TAG = "NetworkUtils";  
    9.   
    10.     /** Bring the named network interface up. */  
    11.     public native static int enableInterface(String interfaceName);  
    12.   
    13.     /** Bring the named network interface down. */  
    14.     public native static int disableInterface(String interfaceName);  
    15.   
    16.     /** Remove the default route for the named interface. */  
    17.     public native static int removeDefaultRoute(String interfaceName);  
    18.   
    19.     /** Setting bit 0 indicates reseting of IPv4 addresses required */  
    20.     public static final int RESET_IPV4_ADDRESSES = 0x01;  
    21.   
    22.     /** Setting bit 1 indicates reseting of IPv4 addresses required */  
    23.     public static final int RESET_IPV6_ADDRESSES = 0x02;  
    24.   
    25.     /** Reset all addresses */  
    26.     public static final int RESET_ALL_ADDRESSES = RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES;  
    27.   
    28.     /** 
    29.      * Reset IPv6 or IPv4 sockets that are connected via the named interface. 
    30.      * 
    31.      * @param interfaceName is the interface to reset 
    32.      * @param mask {@see #RESET_IPV4_ADDRESSES} and {@see #RESET_IPV6_ADDRESSES} 
    33.      */  
    34.     public native static int resetConnections(String interfaceName, int mask);  
    35.   
    36.     /** 
    37.      * Start the DHCP client daemon, in order to have it request addresses 
    38.      * for the named interface, and then configure the interface with those 
    39.      * addresses. This call blocks until it obtains a result (either success 
    40.      * or failure) from the daemon. 
    41.      * @param interfaceName the name of the interface to configure 
    42.      * @param ipInfo if the request succeeds, this object is filled in with 
    43.      * the IP address information. 
    44.      * @return {@code true} for success, {@code false} for failure 
    45.      */  
    46.     public native static boolean runDhcp(String interfaceName, DhcpInfoInternal ipInfo);  
    47.   
    48.   
    49.     /** 
    50.      * Initiate renewal on the Dhcp client daemon. This call blocks until it obtains 
    51.      * a result (either success or failure) from the daemon. 
    52.      * @param interfaceName the name of the interface to configure 
    53.      * @param ipInfo if the request succeeds, this object is filled in with 
    54.      * the IP address information. 
    55.      * @return {@code true} for success, {@code false} for failure 
    56.      */  
    57.     public native static boolean runDhcpRenew(String interfaceName, DhcpInfoInternal ipInfo);  
    58.   
    59.     /** 
    60.      * Shut down the DHCP client daemon. 
    61.      * @param interfaceName the name of the interface for which the daemon 
    62.      * should be stopped 
    63.      * @return {@code true} for success, {@code false} for failure 
    64.      */  
    65.     public native static boolean stopDhcp(String interfaceName);  
    66.     /** 
    67.      * When static IP configuration has been specified, configure the network 
    68.      * interface according to the values supplied. 
    69.      * @param interfaceName the name of the interface to configure 
    70.      * @param ipInfo the IP address, default gateway, and DNS server addresses 
    71.      * with which to configure the interface. 
    72.      * @return {@code true} for success, {@code false} for failure 
    73.      */  
    74.     public static boolean configureInterface(String interfaceName, DhcpInfo ipInfo) {  
    75.         return configureNative(interfaceName,  
    76.             ipInfo.ipAddress,  
    77.             ipInfo.netmask,  
    78.             ipInfo.gateway,  
    79.             ipInfo.dns1,  
    80.             ipInfo.dns2);  
    81.     }  
    82.   
    83.     private native static boolean configureNative(  
    84.         String interfaceName, int ipAddress, int netmask, int gateway, int dns1, int dns2);  

    2. android_net_NetUtils.cpp JNI 中的函数映射关系。

    [cpp] view plaincopyprint?
    1. /* 
    2.  * JNI registration. 
    3.  */  
    4. static JNINativeMethod gNetworkUtilMethods[] = {  
    5.     /* name, signature, funcPtr */  
    6.   
    7.     { "enableInterface""(Ljava/lang/String;)I",  (void *)android_net_utils_enableInterface },  
    8.     { "disableInterface""(Ljava/lang/String;)I",  (void *)android_net_utils_disableInterface },  
    9.     { "resetConnections""(Ljava/lang/String;I)I",  (void *)android_net_utils_resetConnections },  
    10.     { "removeDefaultRoute""(Ljava/lang/String;)I",  (void *)android_net_utils_removeDefaultRoute },  
    11.     { "runDhcp""(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcp },  
    12.     { "runDhcpRenew""(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcpRenew },  
    13.     { "stopDhcp""(Ljava/lang/String;)Z",  (void *)android_net_utils_stopDhcp },  
    14.     { "releaseDhcpLease""(Ljava/lang/String;)Z",  (void *)android_net_utils_releaseDhcpLease },  
    15.     { "getDhcpError""()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },  
    16.     { "configureNative""(Ljava/lang/String;IIIII)Z",  (void *)android_net_utils_configureInterface },  
    17. };  

    3. enableInterface(), diableInterface() , resetConnection():

    [cpp] view plaincopyprint?
    1. static jint android_net_utils_enableInterface(JNIEnv* env, jobject clazz, jstring ifname)  
    2. {  
    3.     int result;  
    4.   
    5.     const char *nameStr = env->GetStringUTFChars(ifname, NULL);  
    6.     result = ::ifc_enable(nameStr); //这里就会调用到 libnetutils 中的 ifc_utils.c 去  
    7.     env->ReleaseStringUTFChars(ifname, nameStr);  
    8.     return (jint)result;  
    9. }  
    10.   
    11. static jint android_net_utils_disableInterface(JNIEnv* env, jobject clazz, jstring ifname)  
    12. {  
    13.     int result;  
    14.   
    15.     const char *nameStr = env->GetStringUTFChars(ifname, NULL);  
    16.     result = ::ifc_disable(nameStr);  
    17.     env->ReleaseStringUTFChars(ifname, nameStr);  
    18.     return (jint)result;  
    19. }  
    20.   
    21. static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz,  
    22.       jstring ifname, jint mask)  
    23. {  
    24.     int result;  
    25.   
    26.     const char *nameStr = env->GetStringUTFChars(ifname, NULL);  
    27.   
    28.     LOGD("android_net_utils_resetConnections in env=%p clazz=%p iface=%s mask=0x%x\n",  
    29.           env, clazz, nameStr, mask);  
    30.   
    31.     result = ::ifc_reset_connections(nameStr, mask);  
    32.     env->ReleaseStringUTFChars(ifname, nameStr);  
    33.     return (jint)result;  
    34. }  

    4. runDhcp() , stopDhcp():

    [java] view plaincopyprint?
    1. static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,  
    2.         jobject info, bool renew)  
    3. {  
    4.     int result;  
    5.     char  ipaddr[PROPERTY_VALUE_MAX];  
    6.     uint32_t prefixLength;  
    7.     char gateway[PROPERTY_VALUE_MAX];  
    8.     char    dns1[PROPERTY_VALUE_MAX];  
    9.     char    dns2[PROPERTY_VALUE_MAX];  
    10.     char  server[PROPERTY_VALUE_MAX];  
    11.     uint32_t lease;  
    12.   
    13.     const char *nameStr = env->GetStringUTFChars(ifname, NULL);  
    14.     if (nameStr == NULL) return (jboolean)false;  
    15.   
    16.     if (renew) {  
    17.         result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,  
    18.                 dns1, dns2, server, &lease);  
    19.     } else {  
    20.         result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,  
    21.                 dns1, dns2, server, &lease); //调用 dhcp_utils.c 中的函数,获取route  
    22.     }  
    23.   
    24.     env->ReleaseStringUTFChars(ifname, nameStr);  
    25.     if (result == 0) {  
    26.         env->SetObjectField(info, dhcpInfoInternalFieldIds.ipaddress, env->NewStringUTF(ipaddr));  
    27.   
    28.         // set the gateway   
    29.         jclass cls = env->FindClass("java/net/InetAddress");  
    30.         jmethodID method = env->GetStaticMethodID(cls, "getByName",  
    31.                 "(Ljava/lang/String;)Ljava/net/InetAddress;");  
    32.         jvalue args[1];  
    33.         args[0].l = env->NewStringUTF(gateway);  
    34.         jobject inetAddressObject = env->CallStaticObjectMethodA(cls, method, args);  
    35.   
    36.         if (!env->ExceptionOccurred()) {  
    37.             cls = env->FindClass("android/net/RouteInfo");  
    38.             method = env->GetMethodID(cls, "<init>""(Ljava/net/InetAddress;)V");  
    39.             args[0].l = inetAddressObject;  
    40.             jobject routeInfoObject = env->NewObjectA(cls, method, args);  
    41.   
    42.             cls = env->FindClass("android/net/DhcpInfoInternal");  
    43.             method = env->GetMethodID(cls, "addRoute""(Landroid/net/RouteInfo;)V");  
    44.             args[0].l = routeInfoObject;  
    45.             env->CallVoidMethodA(info, method, args);  
    46.         } else {  
    47.             // if we have an exception (host not found perhaps), just don't add the route  
    48.             env->ExceptionClear();  
    49.         }  
    50.   
    51.         env->SetIntField(info, dhcpInfoInternalFieldIds.prefixLength, prefixLength);  
    52.         env->SetObjectField(info, dhcpInfoInternalFieldIds.dns1, env->NewStringUTF(dns1));  
    53.         env->SetObjectField(info, dhcpInfoInternalFieldIds.dns2, env->NewStringUTF(dns2));  
    54.         env->SetObjectField(info, dhcpInfoInternalFieldIds.serverAddress,  
    55.                 env->NewStringUTF(server));  
    56.         env->SetIntField(info, dhcpInfoInternalFieldIds.leaseDuration, lease);  
    57.     }  
    58.     return (jboolean)(result == 0);  
    59. }  
    [cpp] view plaincopyprint?
    1. static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)  
    2. {  
    3.     return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);  
    4. }  
    5.   
    6. static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname, jobject info)  
    7. {  
    8.     return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true);  
    9. }  
    10.   
    11.   
    12. static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname)  
    13. {  
    14.     int result;  
    15.   
    16.     const char *nameStr = env->GetStringUTFChars(ifname, NULL);  
    17.     result = ::dhcp_stop(nameStr); // 这个调用 libnetutils 中的 dhcp_utils.c   
    18.     env->ReleaseStringUTFChars(ifname, nameStr);  
    19.     return (jboolean)(result == 0);  
    20. }  

    5. 新添加的2个函数: removeDefaultRoute() 和 configureInterface():

    [cpp] view plaincopyprint?
    1. static jint android_net_utils_removeDefaultRoute(JNIEnv* env, jobject clazz, jstring ifname)  
    2. {  
    3.     int result;  
    4.   
    5.     const char *nameStr = env->GetStringUTFChars(ifname, NULL);  
    6.     result = ::ifc_remove_default_route(nameStr);  
    7.     env->ReleaseStringUTFChars(ifname, nameStr);  
    8.     return (jint)result;  
    9. }  
    10.   
    11. static jboolean android_net_utils_configureInterface(JNIEnv* env,  
    12.         jobject clazz,  
    13.         jstring ifname,  
    14.         jint ipaddr,  
    15.         jint mask,  
    16.         jint gateway,  
    17.         jint dns1,  
    18.         jint dns2)  
    19. {  
    20.     int result;  
    21.     uint32_t lease;  
    22.   
    23.     const char *nameStr = env->GetStringUTFChars(ifname, NULL);  
    24.     result = ::ifc_configure(nameStr, ipaddr, mask, gateway, dns1, dns2);  
    25.     env->ReleaseStringUTFChars(ifname, nameStr);  
    26.     return (jboolean)(result == 0);  
    27. }  

    6. libnetutils.so C 库导出来的 函数名, 这里主要用到了 ifc_utils.c 和 dhcp_utils.c 中的一些函数:

    [cpp] view plaincopyprint?
    1. extern "C" {  
    2. int ifc_enable(const char *ifname);  
    3. int ifc_disable(const char *ifname);  
    4. int ifc_reset_connections(const char *ifname, int reset_mask);  
    5. int ifc_remove_default_route(const char *ifname);  
    6.   
    7. int ifc_configure(const char *ifname,  
    8.                   in_addr_t address,  
    9.                   in_addr_t prefixLength,  
    10.                   in_addr_t gateway,  
    11.                   in_addr_t dns1,  
    12.                   in_addr_t dns2);  
    13.   
    14. int dhcp_do_request(const char *ifname,  
    15.                     const char *ipaddr,  
    16.                     const char *gateway,  
    17.                     uint32_t  *prefixLength,  
    18.                     const char *dns1,  
    19.                     const char *dns2,  
    20.                     const char *server,  
    21.                     uint32_t  *lease);  
    22.   
    23. int dhcp_do_request_renew(const char *ifname,  
    24.                     const char *ipaddr,  
    25.                     const char *gateway,  
    26.                     uint32_t  *prefixLength,  
    27.                     const char *dns1,  
    28.                     const char *dns2,  
    29.                     const char *server,  
    30.                     uint32_t  *lease);  
    31.   
    32. int dhcp_stop(const char *ifname);  
    33. int dhcp_release_lease(const char *ifname);  
    34. char *dhcp_get_errmsg();  
    35. }  

    dhcpcd守护进程分析

    最近在调android ethernet功能,android本身不带 ethernet 功能,需要打patch。这个patch可以在setting里出来 ethernet configuration 选项。即添加了用户配置IP的功能。
    我打上patch之后,点击选上DHCP功能,结果路由器一直不能自动分配IP。

    经检测,命令行里运行 netcfg eth0 up dhcp 时,ethernet能被正常启动,DHCP能分配到IP。

    但是Setting里选上时,dhcp却不能正常分配IP。 这很费解,我先后查看了,
    /system/core/libnetutils/*
    /externel/dhcpcd/*
    发现都没什么问题。

    在Setting中点击turn on ethernet选项时,从log看到能调到

    1. E/EthernetStateTracker( 185): DhcpHandler: DHCP request failed: Timed out waiting for dhcpcd to start
    2. D/EthernetStateTracker( 185): DhcpHandler: DHCP request started

    说明patch是好的能正常工作,能正常掉用dhcp,只是DHCP运行不成功。

    然后我查了 getprop: 显示 init.svc.dhcpcd_eth0 = stop
    正常应该是running的,这样DHCP 才能运行成功。

    最后调试了两天,才搞明白,原来是 init.rc 中 dhcpcd_eth0 守护进程的问题:

    改成:

    1. on property:init.svc.dhcpcd_eth0=stopped
    2.     start dhcpcd_eth0

    3. service dhcpcd_eth0 /system/bin/dhcpcd-ABKL -f /system/etc/dhcpcd/dhcpcd.conf-d eth0
    4.     class main
    5.     disabled
    6.     oneshot

    这样就可以了。

    这时init.svc.dhcpcd_eth0 就会是 running 了。这时再点击Setting -> ethernet configuration, DHCP就能正常分配IP了。

    libnetutils 和dhcpcd 调用过程如下:

    1. libnetutils 调用过程:

    1. jni
    2. =>runDhcp
    3. =>android_net_utils_runDhcp
    4. libs/netutils/dhcp_utils.c
    5. =>dhcp_do_request
    6. =>
    7. static const char DAEMON_NAME[] = "dhcpcd";
    8. static const char DAEMON_PROP_NAME[] = "init.svc.dhcpcd";
    9. static const char DHCP_PROP_NAME_PREFIX[] = "dhcp";
    10. const char *ctrl_prop = "ctl.start";
    11. const char *desired_status = "running";
    12. snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result",
    13. DHCP_PROP_NAME_PREFIX,
    14. interface);
    15. property_set(result_prop_name, "");//设置dhcp.eth0.result="";等到成功完成dhcp之后,
    16. property_set(ctrl_prop, DAEMON_NAME);//向名字为dhcpcd的service,发送"ctrl.start"启动命令字,该service在init.rc中
    17. //init.rc中dhcpcd服务进程命令字
    18. //service dhcpcd /system/bin/dhcpcd eth0
    19. // disabled
    20. // oneshot
    21. wait_for_property(DAEMON_PROP_NAME, desired_status, 10);
    22. //init.c=>init进程
    23. //=>handle_property_set_fd因为是"ctrl.start"命令字,所以调用handle_control_message处理控制信息
    24. //=>handle_control_message
    25. //=>msg_start
    26. //=>
    27. // struct service *svc = service_find_by_name(name);
    28. // service_start(svc);//启动svc,即执行:/system/bin/dhcpcd eth0
    29. //=>service_start
    30. //=>pid = fork();
    31. // if(pid == 0)execve(svc->args[0], (char**) svc->args, (char**) ENV);子进程执行execve运行/system/bin/dhcpcd,参数为eth0
    32. //=>否则父进程,即init进程将
    33. //=>notify_service_state(svc->name, "running");设置该svc的状态prop
    34. // snprintf(pname, sizeof(pname), "init.svc.%s", name);
    35. // property_set(pname, state);//所以这样上面wait_for_property(DAEMON_PROP_NAME, desired_status, 10);也才能够正常pass[luther.gliethttp].
    36. wait_for_property(result_prop_name, NULL, 15);//等待dhcp.eth0.result=非空

    2. dhcpcd 调用过程:


    1. system/extra/dhcpcd-4.0.0-beta9/dhcpcd.c
    2. dhcpcd
    3. =>main
    4. # define SYSCONFDIR"/system/etc/dhcpcd"
    5. #define PACKAGE"dhcpcd"
    6. # define CONFIG SYSCONFDIR"/" PACKAGE ".conf"
    7. # define LIBEXECDIR"/system/etc/dhcpcd"
    8. # define SCRIPT LIBEXECDIR"/" PACKAGE "-run-hooks"
    9. =>strlcpy(options->script, SCRIPT,sizeof(options->script));//默认的options->script="/system/etc/dhcpcd /dhcpcd-run-hooks"
    10. =>f = fopen(cf ? cf : CONFIG,"r");//如果没有指定.conf文件,那么使用默认.conf文件
    11. =>parse_config_line//解析"/system/etc/dhcpcd/dhcpcd.conf"默认配置文件
    12. =>parse_option
    13. =>如果在"/system/etc/dhcpcd/dhcpcd.conf""script"这个节
    14. =>那么执行strlcpy(options->script, oarg,sizeof(options->script));直接拷贝
    15. /*
    16. {"script", required_argument, NULL, 'c'},
    17. {"option", required_argument, NULL, 'o'},
    18. "/system/etc/dhcpcd/dhcpcd.conf"中的部分内容如下:
    19. ...
    20. option domain_name_servers, domain_name, domain_search, host_name
    21. ...
    22. */
    23. =>dhcp_run
    24. =>handle_dhcp_packet
    25. =>handle_dhcp
    26. =>bind_dhcp
    27.   reason = "TIMEOUT";reason= "BOUND";reason= "REBIND";reason= "RENEW";
    28. system/extra/dhcpcd-4.0.0-beta9/configure.c
    29. => configure(iface, reason, state->new, state->old,&state->lease, options, 1);
    30. //如果dhcp超时或者dhcp成功,都会调用exec_script来执行脚本,
    31. //执行setprop dhcp.${interface}.result "failed"或者
    32. //执行setprop dhcp.${interface}.result "ok"
    33. =>exec_script(options, iface->name, reason, NULL, old);
    34. =>然后configure_env通过环境变量将reason传递到脚本中
    35. int exec_script(conststruct options *options,const char *iface, constchar *reason,
    36.      const struct dhcp_message*dhcpn, const struct dhcp_message *dhcpo)
    37. =>pid = fork();
    38. =>if(pid== 0)execve(options->script, argv, env);//子进程执行脚本,默认"/system/etc/dhcpcd/dhcpcd-run-hooks"
    39. //dhcpcd-run-hooks脚本会根据level值,决定是否执行system/etc/dhcpcd/dhcpcd-hook/*目录下的相应文件
    40. //我们的系统在该system/etc/dhcpcd/dhcpcd-hook/*目录下有如下3个文件
    41. //95-configured
    42. //20-dns.conf
    43. //01-test
    44. =>父进程返回while(waitpid(pid,&status, 0)== -1)等待子进程脚本执行完成

    45. system/extra/dhcpcd-4.0.0-beta9/dhcpcd-hooks/20-dns.conf
    46. system/extra/dhcpcd-4.0.0-beta9/dhcpcd-hooks/95-configured
    47.     ...
    48.     setprop dhcp.${interface}.ipaddress"${new_ip_address}"
    49.     setprop dhcp.${interface}.result"ok"//设置属性为ok
    50.     setprop dhcp.${interface}.result"failed"

    dhcpcd 工具

    dhcpcd 源代码 位于 external/dhcpcd/*

    这个目录的源代码生成 /system/bin/dhcpcd 命令工具和一些信息文件。

    0605/external/dhcpcd$ ls *
    android.conf  CleanSpec.mk  configure.h  dhcpcd.conf            dhcp.h     if-linux.c           logger.c                 NOTICE            ThirdPartyProject.prop
    Android.mk    client.c      control.c    dhcpcd.conf.5          duid.c     if-linux-wireless.c  logger.h                 platform-bsd.c
    arp.c         client.h      control.h    dhcpcd.conf.5.in       duid.h     if-options.c         lpf.c                    platform.h
    arp.h         common.c      defs.h       dhcpcd.h               eloop.c    if-options.h         Makefile                 platform-linux.c
    bind.c        common.h      dhcp.c       dhcpcd-run-hooks       eloop.h    if-pref.c            Makefile.inc             README
    bind.h        config.h      dhcpcd.8     dhcpcd-run-hooks.8     ifaddrs.c  if-pref.h            MODULE_LICENSE_BSD_LIKE  showlease.c
    bpf.c         config.mk     dhcpcd.8.in  dhcpcd-run-hooks.8.in  ifaddrs.h  ipv4ll.c             net.c                    signals.c
    bpf-filter.h  configure.c   dhcpcd.c     dhcpcd-run-hooks.in    if-bsd.c   ipv4ll.h             net.h                    signals.h

    compat:
    arc4random.c  arc4random.h  closefrom.c  closefrom.h  getline.c  getline.h  linkaddr.c  strlcpy.c  strlcpy.h

    dhcpcd-hooks:
    01-test  10-mtu       20-resolv.conf      30-hostname       50-ntp.conf  50-yp.conf         95-configured
    02-dump  20-dns.conf  29-lookup-hostname  50-dhcpcd-compat  50-ypbind    90-NetworkManager  Makefile

    mk:
    cc.mk  depend.mk  dist.mk  files.mk  man.mk  os-BSD.mk  os-Darwin.mk  os-Linux.mk  os.mk  prog.mk  scripts.mk  sys.mk

    这里代码比较多,暂不细究了。