android ethernet

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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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 plain copy print ?
  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(const struct options *options, const char *iface, const char *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

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

 

 


 

你可能感兴趣的:(android,android,android,android,android,ethernet,ethernet,ethernet,ethernet,ethernet)