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 2012-06-08 17:18 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 2012-06-08 17:20 124人阅读 评论(0) 收藏 举报 1. netcfgnetcfg //查看ip情况
netcfg eth0 up dhcp //通过dhcp 自动获取ip和网关
2. ifconfig
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.304. 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 2012-06-09 16:14 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:
- caseConnectivityManager.TYPE_ETHERNET:
- //mNetTrackers[netType]=EthernetDataTracker.getInstance();
- //mNetTrackers[netType].startMonitoring(context,mHandler);
- if(DBG)log("StartingEthernetService.");
- //创建EthernetStateTracker
- EthernetStateTrackerest=newEthernetStateTracker(context,mHandler);
- //创建EthernetService
- EthernetServiceethService=newEthernetService(context,est);
- <PREclass=javaname="code">//向ServiceManager中添加ETHERNET_SERVICE服务
- ServiceManager.addService(Context.ETHERNET_SERVICE,ethService);
- mNetTrackers[ConnectivityManager.TYPE_ETHERNET]=est;//赋值EthernetStateTracker.
- //调用EthernetStateTracker的startMonitoring
- est.startMonitoring(context,mHandler);
- break;</PRE>
- <PRE></PRE>
- <P></P>
- <Pstyle="BACKGROUND-COLOR:rgb(255,255,255)"><SPANstyle="COLOR:#663300;FONT-SIZE:16px"><STRONG><SPANstyle="FONT-FAMILY:宋体">a.mNetTrackers定义:</SPAN></STRONG></SPAN></P>
- <P></P>
- <PREclass=javaname="code">/**
- *Sometimeswewanttorefertotheindividualnetworkstate
- *trackersseparately,andsometimeswejustwanttotreatthem
- *abstractly.
- */
- privateNetworkStateTrackermNetTrackers[];
- //网络状态跟踪,no_connected,connecting,connected,三种状态
- </PRE><BR>
- <P></P>
- <SPANstyle="FONT-FAMILY:宋体"><SPANstyle="FONT-SIZE:12px"><SPANstyle="COLOR:#990000"><STRONG><SPANstyle="FONT-SIZE:16px"><SPANstyle="BACKGROUND-COLOR:rgb(255,255,255);COLOR:#663300">b.EthernetStateTracker.startMonitoring():</SPAN><BR>
- </SPAN></STRONG></SPAN></SPAN></SPAN><PREclass=javaname="code">publicvoidstartMonitoring(Contextcontext,Handlertarget){
- if(localLOGV)Slog.v(TAG,"starttomonitortheethernetdevices");
- if(mServiceStarted){//获得systemService中ethernet_service的上下文
- mEM=(EthernetManager)context.getSystemService(Context.ETHERNET_SERVICE);
- mContext=context;
- mCsHandler=target;
- intstate=mEM.getState();
- if(state!=mEM.ETHERNET_STATE_DISABLED){
- if(state==mEM.ETHERNET_STATE_UNKNOWN){
- //maybethisisthefirsttimewerun,sosetittoenabled
- mEM.setEnabled(mEM.getDeviceNameList()!=null);//setmEMtoenabled.
- }else{
- try{
- //ifit'snotthefirsttimewerun,resettheinterface.
- resetInterface();
- }catch(UnknownHostExceptione){
- Slog.e(TAG,"Wrongethernetconfiguration");
- }
- }
- }
- }
- }
- </PRE><SPANstyle="COLOR:#ff0000"><STRONG><SPANstyle="FONT-SIZE:16px"><BR>
- 2.创建EthernetStateTracker:</SPAN></STRONG></SPAN><SPANstyle="FONT-SIZE:16px"><BR>
- </SPAN>frameworks/base/ethernet/java/android/net/ethernet/EthernetStateTracker.java<BR>
- <BR>
- <DIVid=codeTextclass=codeText><PREclass=javaname="code">publicEthernetStateTracker(Contextcontext,Handlertarget){
- //创建NetworkInfo,可以用来查看网络状况
- mNetworkInfo=newNetworkInfo(ConnectivityManager.TYPE_ETHERNET,0,"ETH","");
- mLinkProperties=newLinkProperties();//网络链接属性
- if(localLOGV)Slog.v(TAG,"Starts...");
- //EthernetNative通过JNI调用到libnetutil.so中去了。
- if(EthernetNative.initEthernetNative()!=0){
- Slog.e(TAG,"Cannotinitethernetdevicelayers");
- return;
- }
- if(localLOGV)Slog.v(TAG,"Successed");
- mServiceStarted=true;
- //创建DHCP线程
- HandlerThreaddhcpThread=newHandlerThread("DHCPHandlerThread");
- dhcpThread.start();
- mDhcpTarget=newDhcpHandler(dhcpThread.getLooper(),this);
- mMonitor=newEthernetMonitor(this);//创建EthernetMonitor
- mDhcpInfo=newDhcpInfoInternal();//创建DhcpInfoInternal,用来描述DHCPIP配置
- mDhcpInfo1=newDhcpInfo();//创建DhcpInfo,用来描述staticip配置
- }</PRE><BR>
- <SPANstyle="COLOR:#663300;FONT-SIZE:16px"><STRONG>a.DhcpHandler():<SPANstyle="FONT-SIZE:12px">
- 这个类不知道干啥的。。</SPAN></STRONG></SPAN><BR>
- <PREclass=javaname="code">privateclassDhcpHandlerextendsHandler{
- publicDhcpHandler(Looperlooper,Handlertarget){
- super(looper);
- mTrackerTarget=target;//赋值mTrackerTarget.
- }
- </PRE><BR>
- <SPANstyle="COLOR:#663300;FONT-SIZE:16px"><STRONG>b.EthernetMonitor():这个会单独介绍<BR>
- <BR>
- c.DhcpInfoInternal():这个应该是DhcpInfo的新一代。</STRONG></SPAN><BR>
- frameworks/base/core/java/android/net/DhcpInfoInternal.java<BR>
- <BR>
- <PREclass=javaname="code">/**
- *AsimpleobjectforretrievingtheresultsofaDHCPrequest.
- *Replaces(internally)theIPv4-onlyDhcpInfoclass.
- *@hide
- */
- publicclassDhcpInfoInternal{
- privatefinalstaticStringTAG="DhcpInfoInternal";
- publicStringipAddress;
- publicintprefixLength;
- publicStringdns1;
- publicStringdns2;
- publicStringserverAddress;
- publicintleaseDuration;
- privateCollection<RouteInfo>mRoutes;
- </PRE><BR>
- <SPANstyle="COLOR:#663300;FONT-SIZE:16px"><STRONG>d.DhcpInfo类内容明显和DhcpInfoInternal不同:</STRONG></SPAN><BR>
- frameworks/base/core/java/android/net/DhcpInfo.java<BR>
- <PREclass=javaname="code">/**
- *AsimpleobjectforretrievingtheresultsofaDHCPrequest.
- */
- publicclassDhcpInfoimplementsParcelable{
- publicintipAddress;
- publicintgateway;
- publicintnetmask;
- publicintdns1;
- publicintdns2;
- publicintserverAddress;
- publicintleaseDuration;
- </PRE><BR>
- <BR>
- </DIV>
- <SPANstyle="COLOR:#f00000;FONT-SIZE:16px"><STRONG>3.<SPANstyle="FONT-FAMILY:宋体">
- 创建</SPAN><SPANstyle="FONT-FAMILY:宋体">EthernetService</SPAN></STRONG></SPAN><SPANstyle="FONT-SIZE:16px">:</SPAN><BR>
- frameworks/base/services/java/com/android/server/EthernetService.java<BR>
- <BR>
- <PREclass=javaname="code">publicEthernetService(Contextcontext,EthernetStateTrackerTracker){
- mTracker=Tracker;
- mContext=context;
- isEnabled=getPersistedState();
- if(localLOGV==true)Slog.i(TAG,"Ethernetdevenabled"+isEnabled);
- getDeviceNameList();//从驱动获得设备表
- setState(isEnabled);//设置enabled状态
- Slog.d(TAG,"xxha:----------------------StartPolling()");
- mTracker.StartPolling();//开始监听驱动层的事件信号
- }</PRE><BR>
- <SPANstyle="COLOR:#663300"><STRONG><SPANstyle="FONT-SIZE:16px">a.getDeviceNameList():</SPAN></STRONG></SPAN><BR>
- <PREclass=javaname="code">/**
- *getalltheethernetdevicenames
- *@returninterfacenamelistonsuccess,{@codenull}onfailure
- */
- publicString[]getDeviceNameList(){
- return(scanDevice()>0)?DevName:null;//扫描设备
- }
- </PRE><BR>
- <PREclass=javaname="code">privateintscanDevice(){
- inti,j;
- if((i=EthernetNative.getInterfaceCnt())==0)
- return0;
- DevName=newString[i];
- for(j=0;j<i;j++){
- DevName[j]=EthernetNative.getInterfaceName(j);//获取设备名eth0,sit0
- if(DevName[j]==null)
- break;
- if(localLOGV)Slog.v(TAG,"device"+j+"name"+DevName[j]);
- }
- returni;
- }
- </PRE><SPANstyle="COLOR:#663300"><STRONG><SPANstyle="FONT-SIZE:16px"><BR>
- b.mTracker.StartPolling()</SPAN></STRONG></SPAN><BR>
- <PREclass=javaname="code">publicvoidStartPolling(){
- mMonitor.startMonitoring();//这个也会调到EthernetMonitor中的startMonitoring()去。
- }
- </PRE><BR>
- <BR>
- <BR>
- <BR>
- <SPANstyle="FONT-FAMILY:宋体"><BR>
- <BR>
- </SPAN>
- <P></P>
- <PRE></PRE>
EthernetMornitor 与 EthernetStateTracker
分类: Android ethernet 2012-06-11 15:14 173人阅读 评论(0) 收藏 举报EthernetMornitor 这个类位于: frameworks/base/ethernet/java/android/net/ethernet/EthernetMonitor.java
它会监听底层ethernet 状态 的 event.
1. EthernetMonitor :
[java] view plain copy print ?- /**
- *Listensforeventsfromkernel,andpassesthemon
- *tothe{@linkEtherentStateTracker}forhandling.Runsinitsownthread.
- *
- *@hide
- */
- publicclassEthernetMonitor{
- privatestaticfinalStringTAG="EthernetMonitor";
- privatestaticfinalintCONNECTED=1;
- privatestaticfinalintDISCONNECTED=2;
- privatestaticfinalintPHYUP=3;
- privatestaticfinalStringconnectedEvent="CONNECTED";
- privatestaticfinalStringdisconnectedEvent="DISCONNECTED";
- privatestaticfinalintADD_ADDR=20;
- privatestaticfinalintRM_ADDR=21;
- privatestaticfinalintNEW_LINK=16;
- privatestaticfinalintDEL_LINK=17;
- privatestaticfinalbooleanlocalLOGV=false;
- privateEthernetStateTrackermTracker;
- //EthernetMonitor是EthernetStateTraker的一个辅助
- publicEthernetMonitor(EthernetStateTrackertracker){
- mTracker=tracker;
- }
/** * Listens for events from kernel, and passes them on * to the {@link EtherentStateTracker} for handling. Runs in its own thread. * * @hide */public class EthernetMonitor { private static final String TAG = "EthernetMonitor"; private static final int CONNECTED = 1; private static final int DISCONNECTED = 2; private static final int PHYUP = 3; private static final String connectedEvent = "CONNECTED"; private static final String disconnectedEvent = "DISCONNECTED"; private static final int ADD_ADDR = 20; private static final int RM_ADDR = 21; private static final int NEW_LINK = 16; private static final int DEL_LINK = 17; private static final boolean localLOGV = false; private EthernetStateTracker mTracker; //EthernetMonitor 是 EthernetStateTraker 的一个辅助 public EthernetMonitor(EthernetStateTracker tracker) { mTracker = tracker; }
a. startMonitoring(): 会在 EthernetStateTracker.StartPolling()中 调用此函数。
[java] view plain copy print ?
- publicvoidstartMonitoring(){
- newMonitorThread().start();//线程开始
- }
- classMonitorThreadextendsThread{
- publicMonitorThread(){
- super("EthMonitor");
- }
- publicvoidrun(){
- //noinspectionInfiniteLoopStatement
- for(;;){//不断的在监听kernelevent
- intindex;
- inti;
- intcmd;
- Stringdev;
- if(localLOGV)Slog.v(TAG,"gopollevents");
- StringeventName=EthernetNative.waitForEvent();//waitforevent
- if(eventName==null){
- continue;
- }
- if(localLOGV)Slog.v(TAG,"getevent"+eventName);
- /*
- *Mapeventnameintoeventenum
- */
- i=0;
- while(i<eventName.length()){
- index=eventName.substring(i).indexOf(":");
- if(index==-1)
- break;
- dev=eventName.substring(i,index);
- i+=index+1;
- index=eventName.substring(i).indexOf(":");
- if(index==-1)
- break;
- cmd=Integer.parseInt(eventName.substring(i,i+index));
- i+=index+1;
- //dev指eth0,cmd是event参数。
- if(localLOGV)Slog.v(TAG,"dev:"+dev+"ev"+cmd);
- switch(cmd){
- caseDEL_LINK://断开连接
- handleEvent(dev,DISCONNECTED);
- break;
- caseADD_ADDR://添加IPaddress,即链接成功
- handleEvent(dev,CONNECTED);
- break;
- caseNEW_LINK://phyup状态
- handleEvent(dev,PHYUP);
- break;
- }
- }
- }
- }
public void startMonitoring() { new MonitorThread().start(); //线程开始 } class MonitorThread extends Thread { public MonitorThread() { super("EthMonitor"); } public void run() { //noinspection InfiniteLoopStatement for (;;) { //不断的在监听 kernel event int index; int i; int cmd; String dev; if (localLOGV) Slog.v(TAG, "go poll events"); String eventName = EthernetNative.waitForEvent(); //wait for event if (eventName == null) { continue; } if (localLOGV) Slog.v(TAG, "get event " + eventName); /* * Map event name into event enum */ i = 0; while (i < eventName.length()) { index = eventName.substring(i).indexOf(":"); if (index == -1) break; dev = eventName.substring(i, index); i += index + 1; index = eventName.substring(i).indexOf(":"); if (index == -1) break; cmd = Integer.parseInt(eventName.substring(i, i+index)); i += index + 1; //dev 指eth0, cmd 是event参数。 if (localLOGV) Slog.v(TAG, "dev: " + dev + " ev " + cmd); switch (cmd) { case DEL_LINK: //断开连接 handleEvent(dev, DISCONNECTED); break; case ADD_ADDR: //添加IP address,即链接成功 handleEvent(dev, CONNECTED); break; case NEW_LINK: //phy up 状态 handleEvent(dev, PHYUP); break; } } } }
b. handleEvent(String ifname,int event):
[java] view plain copy print ?- /**
- *HandleallsupplicanteventsexceptSTATE-CHANGE
- *@parameventtheeventtype
- *@paramremaindertherestofthestringfollowingthe
- *eventnameand" — "
- */
- voidhandleEvent(Stringifname,intevent){
- switch(event){
- caseDISCONNECTED:
- mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.DISCONNECTED);
- break;
- caseCONNECTED:
- mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.CONNECTED);
- break;
- casePHYUP:
- mTracker.notifyPhyConnected(ifname);
- break;
- default:
- mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.FAILED);
- break;
- }
- }
/** * Handle all supplicant events except STATE-CHANGE * @param event the event type * @param remainder the rest of the string following the * event name and " — " */ void handleEvent(String ifname,int event) { switch (event) { case DISCONNECTED: mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.DISCONNECTED); break; case CONNECTED: mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.CONNECTED); break; case PHYUP: mTracker.notifyPhyConnected(ifname); break; default: mTracker.notifyStateChange(ifname,NetworkInfo.DetailedState.FAILED); break; } }
c. EthernetStateTraker.notifyStateChange(): [java] view plain copy print ?
- publicvoidnotifyStateChange(Stringifname,DetailedStatestate){
- if(localLOGV)Slog.i(TAG,"reportnewstate"+state.toString()+"ondev"+ifname);
- if(ifname.equals(mInterfaceName)){//判断eth0名称是否正确
- if(localLOGV)Slog.v(TAG,"updatenetworkstatetracker");
- synchronized(this){//发送ConnectedorDisconnected消息
- this.sendEmptyMessage(state.equals(DetailedState.CONNECTED)
- ?EVENT_HW_CONNECTED:EVENT_HW_DISCONNECTED);
- }
- }
- }
public void notifyStateChange(String ifname,DetailedState state) { if (localLOGV) Slog.i(TAG, "report new state " + state.toString() + " on dev " + ifname); if (ifname.equals(mInterfaceName)) { //判断eth0名称是否正确 if (localLOGV) Slog.v(TAG, "update network state tracker"); synchronized(this) { //发送 Connected or Disconnected 消息 this.sendEmptyMessage(state.equals(DetailedState.CONNECTED) ? EVENT_HW_CONNECTED : EVENT_HW_DISCONNECTED); } } }
d. EthernetStateTraker.notifyPhyConnected():
[java] view plain copy print ?- publicvoidnotifyPhyConnected(Stringifname){
- if(localLOGV)Slog.v(TAG,"reportinterfaceisupfor"+ifname);
- synchronized(this){//发送Phyconnected消息
- this.sendEmptyMessage(EVENT_HW_PHYCONNECTED);
- }
- }
public void notifyPhyConnected(String ifname) { if (localLOGV) Slog.v(TAG, "report interface is up for " + ifname); synchronized(this) { //发送Phy connected 消息 this.sendEmptyMessage(EVENT_HW_PHYCONNECTED); } }
2. 发送消息之后,EthernetStateTraker 会handleMessage():
- publicvoidhandleMessage(Messagemsg){
- synchronized(this){
- switch(msg.what){
- caseEVENT_INTERFACE_CONFIGURATION_SUCCEEDED://连接成功
- if(localLOGV)Slog.i(TAG,"receivedconfiguredsucceeded,stack="+mStackConnected+"HW="+mHWConnected);
- mStackConnected=true;
- if(mHWConnected)
- setState(true,msg.what);
- break;
- caseEVENT_INTERFACE_CONFIGURATION_FAILED://链接失败
- mStackConnected=false;
- //starttoretry?
- break;
- caseEVENT_HW_CONNECTED://HW连接上了
- if(localLOGV)Slog.i(TAG,"receivedHWconnected,stack="+mStackConnected+"HW="+mHWConnected);
- mHWConnected=true;
- if(mStackConnected)
- setState(true,msg.what);
- break;
- caseEVENT_HW_DISCONNECTED://hw断开
- if(localLOGV)Slog.i(TAG,"receiveddisconnectedevents,stack="+mStackConnected+"HW="+mHWConnected);
- setState(false,msg.what);
- break;
- caseEVENT_HW_PHYCONNECTED://phy连上
- if(localLOGV)Slog.i(TAG,"interfaceupevent,kickoffconnectionrequest");
- if(!mStartingDhcp){
- intstate=mEM.getState();
- if(state!=mEM.ETHERNET_STATE_DISABLED){
- EthernetDevInfoinfo=mEM.getSavedConfig();//获得以前已有的连接IP
- if(info!=null&&mEM.isConfigured()){
- try{
- configureInterface(info);//配置IP
- }catch(UnknownHostExceptione){
- //TODOAuto-generatedcatchblock
- //e.printStackTrace();
- Slog.e(TAG,"Cannotconfigureinterface");
- }
- }
- }
- }
- setState(true,msg.what);
- break;
- }
- }
- }
public void handleMessage(Message msg) { synchronized (this) { switch (msg.what) { case EVENT_INTERFACE_CONFIGURATION_SUCCEEDED: //连接成功 if (localLOGV) Slog.i(TAG, "received configured succeeded, stack=" + mStackConnected + " HW=" + mHWConnected); mStackConnected = true; if (mHWConnected) setState(true, msg.what); break; case EVENT_INTERFACE_CONFIGURATION_FAILED: //链接失败 mStackConnected = false; //start to retry ? break; case EVENT_HW_CONNECTED: //HW连接上了 if (localLOGV) Slog.i(TAG, "received HW connected, stack=" + mStackConnected + " HW=" + mHWConnected); mHWConnected = true; if (mStackConnected) setState(true, msg.what); break; case EVENT_HW_DISCONNECTED: //hw断开 if (localLOGV) Slog.i(TAG, "received disconnected events, stack=" + mStackConnected + " HW=" + mHWConnected); setState(false, msg.what); break; case EVENT_HW_PHYCONNECTED: //phy 连上 if (localLOGV) Slog.i(TAG, "interface up event, kick off connection request"); if (!mStartingDhcp) { int state = mEM.getState(); if (state != mEM.ETHERNET_STATE_DISABLED) { EthernetDevInfo info = mEM.getSavedConfig(); //获得以前已有的连接IP if (info != null && mEM.isConfigured()) { try { configureInterface(info); //配置IP } catch (UnknownHostException e) { // TODO Auto-generated catch block //e.printStackTrace(); Slog.e(TAG, "Cannot configure interface"); } } } } setState(true, msg.what); break; } } }
3. setState(boolean state, int event):
- privatevoidsetState(booleanstate,intevent){
- if(mNetworkInfo.isConnected()!=state){
- if(state){//connectedordisconnected.
- mNetworkInfo.setDetailedState(DetailedState.CONNECTED,null,null);
- }else{
- mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED,null,null);
- stopInterface(true);
- }
- mNetworkInfo.setIsAvailable(state);
- postNotification(event);
- }
- }
private void setState(boolean state, int event) { if (mNetworkInfo.isConnected() != state) { if (state) { //connected or disconnected. mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); } else { mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); stopInterface(true); } mNetworkInfo.setIsAvailable(state); postNotification(event); } }
a. stopInterface():
[java] view plain copy print ?
- /**
- *Stopetherentinterface
- *@paramsuspend{@codefalse}disabletheinterface{@codetrue}onlyresettheconnectionwithoutdisabletheinterface
- *@returntrue
- */
- publicbooleanstopInterface(booleansuspend){
- if(mEM!=null){
- EthernetDevInfoinfo=mEM.getSavedConfig();
- if(info!=null&&mEM.isConfigured()){
- synchronized(mDhcpTarget){
- mInterfaceStopped=true;
- if(localLOGV)Slog.i(TAG,"stopdhcpandinterface");
- //stopDhcpHandlerLooper
- mDhcpTarget.removeMessages(EVENT_DHCP_START);
- Stringifname=info.getIfName();//eth0
- if(!NetworkUtils.stopDhcp(ifname)){//stopdhcpcd_eth0service
- if(localLOGV)Slog.w(TAG,"CouldnotstopDHCP");
- }
- //reseteth0,removerouteandip
- NetworkUtils.resetConnections(ifname,NetworkUtils.RESET_ALL_ADDRESSES);
- NetworkUtils.removeDefaultRoute(ifname);
- mStartingDhcp=false;
- if(!suspend)//ifsuspend=false,turneth0todown.
- NetworkUtils.disableInterface(ifname);
- mLinkProperties.clear();
- }
- }
- }
- returntrue;
- }
/** * Stop etherent interface * @param suspend {@code false} disable the interface {@code true} only reset the connection without disable the interface * @return true */ public boolean stopInterface(boolean suspend) { if (mEM != null) { EthernetDevInfo info = mEM.getSavedConfig(); if (info != null && mEM.isConfigured()) { synchronized (mDhcpTarget) { mInterfaceStopped = true; if (localLOGV) Slog.i(TAG, "stop dhcp and interface"); // stop DhcpHandler Looper mDhcpTarget.removeMessages(EVENT_DHCP_START); String ifname = info.getIfName(); // eth0 if (!NetworkUtils.stopDhcp(ifname)) { //stop dhcpcd_eth0 service if (localLOGV) Slog.w(TAG, "Could not stop DHCP"); } //reset eth0, remove route and ip NetworkUtils.resetConnections(ifname, NetworkUtils.RESET_ALL_ADDRESSES); NetworkUtils.removeDefaultRoute(ifname); mStartingDhcp = false; if (!suspend) // if suspend = false, turn eth0 to down. NetworkUtils.disableInterface(ifname); mLinkProperties.clear(); } } } return true; }
b. postNotification(int event), 给ConnectivityService 发送 event state changed 消息.
- privatevoidpostNotification(intevent){
- Messagemsg=mCsHandler.obtainMessage(EVENT_STATE_CHANGED,newNetworkInfo(mNetworkInfo));
- msg.sendToTarget();
- }
private void postNotification(int event) { Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, new NetworkInfo(mNetworkInfo)); msg.sendToTarget(); }
4. configureInterface(EthernetDevInfo info), 配置 IP 函数:
[java] view plain copy print ?
- privatebooleanconfigureInterface(EthernetDevInfoinfo)throwsUnknownHostException{
- mStackConnected=false;
- mHWConnected=false;
- mInterfaceStopped=false;
- mStartingDhcp=true;
- //DHCP方式获得IP
- if(info.getConnectMode().equals(EthernetDevInfo.ETHERNET_CONN_MODE_DHCP)){
- if(localLOGV)Slog.i(TAG,"triggerdhcpfordevice"+info.getIfName());
- sDnsPropNames=newString[]{
- "dhcp."+mInterfaceName+".dns1",
- "dhcp."+mInterfaceName+".dns2"
- };
- mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);
- }else{//staticIP设置方式
- intevent;
- sDnsPropNames=newString[]{
- "net."+mInterfaceName+".dns1",
- "net."+mInterfaceName+".dns2"
- };
- //从输入栏获取ip,gateway,netmask,dns值
- mDhcpInfo1.ipAddress=lookupHost(info.getIpAddress());
- mDhcpInfo1.gateway=lookupHost(info.getRouteAddr());
- mDhcpInfo1.netmask=lookupHost(info.getNetMask());
- mDhcpInfo1.dns1=lookupHost(info.getDnsAddr());
- mDhcpInfo1.dns2=0;
- if(localLOGV)Slog.i(TAG,"setipmanually"+mDhcpInfo1.toString());
- //配置之前擦除以前的route
- NetworkUtils.removeDefaultRoute(info.getIfName());
- //配置成功
- if(NetworkUtils.configureInterface(info.getIfName(),mDhcpInfo1)){
- event=EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;
- SystemProperties.set("net.dns1",info.getDnsAddr());
- SystemProperties.set("net."+info.getIfName()+".dns1",info.getDnsAddr());
- SystemProperties.set("net."+info.getIfName()+".dns2","0.0.0.0");
- if(localLOGV)
- Slog.v(TAG,"StaticIPconfigurationsucceeded");
- }else{//配置失败
- event=EVENT_INTERFACE_CONFIGURATION_FAILED;
- if(localLOGV)Slog.w(TAG,"StaticIPconfigurationfailed");
- }
- this.sendEmptyMessage(event);//给EthernetStateTracker发送message
- }
- returntrue;
- }
- <PRE></PRE><SPANstyle="COLOR:#ff0000"><STRONG><SPANstyle="FONT-SIZE:16px">5.resetInterface(),这个和stopInterface差不多:</SPAN></STRONG></SPAN>
- <P></P>
- <P></P>
- <PREclass=javaname="code">/**
- *resetethernetinterface
- *@returntrue
- *@throwsUnknownHostException
- */
- publicbooleanresetInterface()throwsUnknownHostException{
- /*
- *Thiswillguideustoenabledtheenableddevice
- */
- if(mEM!=null){
- EthernetDevInfoinfo=mEM.getSavedConfig();
- if(info!=null&&mEM.isConfigured()){
- synchronized(this){
- mInterfaceName=info.getIfName();
- if(localLOGV)Slog.i(TAG,"resetdevice"+mInterfaceName);
- NetworkUtils.resetConnections(mInterfaceName,NetworkUtils.RESET_ALL_ADDRESSES);
- //StopDHCP
- if(mDhcpTarget!=null){
- mDhcpTarget.removeMessages(EVENT_DHCP_START);
- }
- if(!NetworkUtils.stopDhcp(mInterfaceName)){
- if(localLOGV)Slog.w(TAG,"CouldnotstopDHCP");
- }
- mLinkProperties.clear();
- configureInterface(info);//比stopInterface多了一步重新配置IP。
- }
- }
- }
- returntrue;
- }
- </PRE><BR>
- <BR>
- <P></P>
- <PRE></PRE>
- <PRE></PRE>
- <PRE></PRE>
- <PRE></PRE>
NetWorkUtils 和 android_net_NetUtils.cpp
分类: Android ethernet 2012-06-11 18:20 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
- /**
- *Nativemethodsformanagingnetworkinterfaces.
- *
- *{@hide}
- */
- publicclassNetworkUtils{
- privatestaticfinalStringTAG="NetworkUtils";
- /**Bringthenamednetworkinterfaceup.*/
- publicnativestaticintenableInterface(StringinterfaceName);
- /**Bringthenamednetworkinterfacedown.*/
- publicnativestaticintdisableInterface(StringinterfaceName);
- /**Removethedefaultrouteforthenamedinterface.*/
- publicnativestaticintremoveDefaultRoute(StringinterfaceName);
- /**Settingbit0indicatesresetingofIPv4addressesrequired*/
- publicstaticfinalintRESET_IPV4_ADDRESSES=0x01;
- /**Settingbit1indicatesresetingofIPv4addressesrequired*/
- publicstaticfinalintRESET_IPV6_ADDRESSES=0x02;
- /**Resetalladdresses*/
- publicstaticfinalintRESET_ALL_ADDRESSES=RESET_IPV4_ADDRESSES|RESET_IPV6_ADDRESSES;
- /**
- *ResetIPv6orIPv4socketsthatareconnectedviathenamedinterface.
- *
- *@paraminterfaceNameistheinterfacetoreset
- *@parammask{@see#RESET_IPV4_ADDRESSES}and{@see#RESET_IPV6_ADDRESSES}
- */
- publicnativestaticintresetConnections(StringinterfaceName,intmask);
- /**
- *StarttheDHCPclientdaemon,inordertohaveitrequestaddresses
- *forthenamedinterface,andthenconfiguretheinterfacewiththose
- *addresses.Thiscallblocksuntilitobtainsaresult(eithersuccess
- *orfailure)fromthedaemon.
- *@paraminterfaceNamethenameoftheinterfacetoconfigure
- *@paramipInfoiftherequestsucceeds,thisobjectisfilledinwith
- *theIPaddressinformation.
- *@return{@codetrue}forsuccess,{@codefalse}forfailure
- */
- publicnativestaticbooleanrunDhcp(StringinterfaceName,DhcpInfoInternalipInfo);
- /**
- *InitiaterenewalontheDhcpclientdaemon.Thiscallblocksuntilitobtains
- *aresult(eithersuccessorfailure)fromthedaemon.
- *@paraminterfaceNamethenameoftheinterfacetoconfigure
- *@paramipInfoiftherequestsucceeds,thisobjectisfilledinwith
- *theIPaddressinformation.
- *@return{@codetrue}forsuccess,{@codefalse}forfailure
- */
- publicnativestaticbooleanrunDhcpRenew(StringinterfaceName,DhcpInfoInternalipInfo);
- /**
- *ShutdowntheDHCPclientdaemon.
- *@paraminterfaceNamethenameoftheinterfaceforwhichthedaemon
- *shouldbestopped
- *@return{@codetrue}forsuccess,{@codefalse}forfailure
- */
- publicnativestaticbooleanstopDhcp(StringinterfaceName);
- /**
- *WhenstaticIPconfigurationhasbeenspecified,configurethenetwork
- *interfaceaccordingtothevaluessupplied.
- *@paraminterfaceNamethenameoftheinterfacetoconfigure
- *@paramipInfotheIPaddress,defaultgateway,andDNSserveraddresses
- *withwhichtoconfiguretheinterface.
- *@return{@codetrue}forsuccess,{@codefalse}forfailure
- */
- publicstaticbooleanconfigureInterface(StringinterfaceName,DhcpInfoipInfo){
- returnconfigureNative(interfaceName,
- ipInfo.ipAddress,
- ipInfo.netmask,
- ipInfo.gateway,
- ipInfo.dns1,
- ipInfo.dns2);
- }
- privatenativestaticbooleanconfigureNative(
- StringinterfaceName,intipAddress,intnetmask,intgateway,intdns1,intdns2);
/** * Native methods for managing network interfaces. * * {@hide} */public class NetworkUtils { private static final String TAG = "NetworkUtils"; /** Bring the named network interface up. */ public native static int enableInterface(String interfaceName); /** Bring the named network interface down. */ public native static int disableInterface(String interfaceName); /** Remove the default route for the named interface. */ public native static int removeDefaultRoute(String interfaceName); /** Setting bit 0 indicates reseting of IPv4 addresses required */ public static final int RESET_IPV4_ADDRESSES = 0x01; /** Setting bit 1 indicates reseting of IPv4 addresses required */ public static final int RESET_IPV6_ADDRESSES = 0x02; /** Reset all addresses */ public static final int RESET_ALL_ADDRESSES = RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES; /** * Reset IPv6 or IPv4 sockets that are connected via the named interface. * * @param interfaceName is the interface to reset * @param mask {@see #RESET_IPV4_ADDRESSES} and {@see #RESET_IPV6_ADDRESSES} */ public native static int resetConnections(String interfaceName, int mask); /** * Start the DHCP client daemon, in order to have it request addresses * for the named interface, and then configure the interface with those * addresses. This call blocks until it obtains a result (either success * or failure) from the daemon. * @param interfaceName the name of the interface to configure * @param ipInfo if the request succeeds, this object is filled in with * the IP address information. * @return {@code true} for success, {@code false} for failure */ public native static boolean runDhcp(String interfaceName, DhcpInfoInternal ipInfo); /** * Initiate renewal on the Dhcp client daemon. This call blocks until it obtains * a result (either success or failure) from the daemon. * @param interfaceName the name of the interface to configure * @param ipInfo if the request succeeds, this object is filled in with * the IP address information. * @return {@code true} for success, {@code false} for failure */ public native static boolean runDhcpRenew(String interfaceName, DhcpInfoInternal ipInfo); /** * Shut down the DHCP client daemon. * @param interfaceName the name of the interface for which the daemon * should be stopped * @return {@code true} for success, {@code false} for failure */ public native static boolean stopDhcp(String interfaceName); /** * When static IP configuration has been specified, configure the network * interface according to the values supplied. * @param interfaceName the name of the interface to configure * @param ipInfo the IP address, default gateway, and DNS server addresses * with which to configure the interface. * @return {@code true} for success, {@code false} for failure */ public static boolean configureInterface(String interfaceName, DhcpInfo ipInfo) { return configureNative(interfaceName, ipInfo.ipAddress, ipInfo.netmask, ipInfo.gateway, ipInfo.dns1, ipInfo.dns2); } private native static boolean configureNative( String interfaceName, int ipAddress, int netmask, int gateway, int dns1, int dns2);
2. android_net_NetUtils.cpp JNI 中的函数映射关系。 [cpp] view plain copy print ?
- /*
- *JNIregistration.
- */
- staticJNINativeMethodgNetworkUtilMethods[]={
- /*name,signature,funcPtr*/
- {"enableInterface","(Ljava/lang/String;)I",(void*)android_net_utils_enableInterface},
- {"disableInterface","(Ljava/lang/String;)I",(void*)android_net_utils_disableInterface},
- {"resetConnections","(Ljava/lang/String;I)I",(void*)android_net_utils_resetConnections},
- {"removeDefaultRoute","(Ljava/lang/String;)I",(void*)android_net_utils_removeDefaultRoute},
- {"runDhcp","(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",(void*)android_net_utils_runDhcp},
- {"runDhcpRenew","(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",(void*)android_net_utils_runDhcpRenew},
- {"stopDhcp","(Ljava/lang/String;)Z",(void*)android_net_utils_stopDhcp},
- {"releaseDhcpLease","(Ljava/lang/String;)Z",(void*)android_net_utils_releaseDhcpLease},
- {"getDhcpError","()Ljava/lang/String;",(void*)android_net_utils_getDhcpError},
- {"configureNative","(Ljava/lang/String;IIIII)Z",(void*)android_net_utils_configureInterface},
- };
/* * JNI registration. */static JNINativeMethod gNetworkUtilMethods[] = { /* name, signature, funcPtr */ { "enableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_enableInterface }, { "disableInterface", "(Ljava/lang/String;)I", (void *)android_net_utils_disableInterface }, { "resetConnections", "(Ljava/lang/String;I)I", (void *)android_net_utils_resetConnections }, { "removeDefaultRoute", "(Ljava/lang/String;)I", (void *)android_net_utils_removeDefaultRoute }, { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z", (void *)android_net_utils_runDhcp }, { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z", (void *)android_net_utils_runDhcpRenew }, { "stopDhcp", "(Ljava/lang/String;)Z", (void *)android_net_utils_stopDhcp }, { "releaseDhcpLease", "(Ljava/lang/String;)Z", (void *)android_net_utils_releaseDhcpLease }, { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError }, { "configureNative", "(Ljava/lang/String;IIIII)Z", (void *)android_net_utils_configureInterface },};
3. enableInterface(), diableInterface() , resetConnection():
[cpp] view plain copy print ?
- staticjintandroid_net_utils_enableInterface(JNIEnv*env,jobjectclazz,jstringifname)
- {
- intresult;
- constchar*nameStr=env->GetStringUTFChars(ifname,NULL);
- result=::ifc_enable(nameStr);//这里就会调用到libnetutils中的ifc_utils.c去
- env->ReleaseStringUTFChars(ifname,nameStr);
- return(jint)result;
- }
- staticjintandroid_net_utils_disableInterface(JNIEnv*env,jobjectclazz,jstringifname)
- {
- intresult;
- constchar*nameStr=env->GetStringUTFChars(ifname,NULL);
- result=::ifc_disable(nameStr);
- env->ReleaseStringUTFChars(ifname,nameStr);
- return(jint)result;
- }
- staticjintandroid_net_utils_resetConnections(JNIEnv*env,jobjectclazz,
- jstringifname,jintmask)
- {
- intresult;
- constchar*nameStr=env->GetStringUTFChars(ifname,NULL);
- LOGD("android_net_utils_resetConnectionsinenv=%pclazz=%piface=%smask=0x%x\n",
- env,clazz,nameStr,mask);
- result=::ifc_reset_connections(nameStr,mask);
- env->ReleaseStringUTFChars(ifname,nameStr);
- return(jint)result;
- }
static jint android_net_utils_enableInterface(JNIEnv* env, jobject clazz, jstring ifname){ int result; const char *nameStr = env->GetStringUTFChars(ifname, NULL); result = ::ifc_enable(nameStr); //这里就会调用到 libnetutils 中的 ifc_utils.c 去 env->ReleaseStringUTFChars(ifname, nameStr); return (jint)result;}static jint android_net_utils_disableInterface(JNIEnv* env, jobject clazz, jstring ifname){ int result; const char *nameStr = env->GetStringUTFChars(ifname, NULL); result = ::ifc_disable(nameStr); env->ReleaseStringUTFChars(ifname, nameStr); return (jint)result;}static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, jstring ifname, jint mask){ int result; const char *nameStr = env->GetStringUTFChars(ifname, NULL); LOGD("android_net_utils_resetConnections in env=%p clazz=%p iface=%s mask=0x%x\n", env, clazz, nameStr, mask); result = ::ifc_reset_connections(nameStr, mask); env->ReleaseStringUTFChars(ifname, nameStr); return (jint)result;}
4. runDhcp() , stopDhcp(): [java] view plain copy print ?
- staticjbooleanandroid_net_utils_runDhcpCommon(JNIEnv*env,jobjectclazz,jstringifname,
- jobjectinfo,boolrenew)
- {
- intresult;
- charipaddr[PROPERTY_VALUE_MAX];
- uint32_tprefixLength;
- chargateway[PROPERTY_VALUE_MAX];
- chardns1[PROPERTY_VALUE_MAX];
- chardns2[PROPERTY_VALUE_MAX];
- charserver[PROPERTY_VALUE_MAX];
- uint32_tlease;
- constchar*nameStr=env->GetStringUTFChars(ifname,NULL);
- if(nameStr==NULL)return(jboolean)false;
- if(renew){
- result=::dhcp_do_request_renew(nameStr,ipaddr,gateway,&prefixLength,
- dns1,dns2,server,&lease);
- }else{
- result=::dhcp_do_request(nameStr,ipaddr,gateway,&prefixLength,
- dns1,dns2,server,&lease);//调用dhcp_utils.c中的函数,获取route
- }
- env->ReleaseStringUTFChars(ifname,nameStr);
- if(result==0){
- env->SetObjectField(info,dhcpInfoInternalFieldIds.ipaddress,env->NewStringUTF(ipaddr));
- //setthegateway
- jclasscls=env->FindClass("java/net/InetAddress");
- jmethodIDmethod=env->GetStaticMethodID(cls,"getByName",
- "(Ljava/lang/String;)Ljava/net/InetAddress;");
- jvalueargs[1];
- args[0].l=env->NewStringUTF(gateway);
- jobjectinetAddressObject=env->CallStaticObjectMethodA(cls,method,args);
- if(!env->ExceptionOccurred()){
- cls=env->FindClass("android/net/RouteInfo");
- method=env->GetMethodID(cls,"<init>","(Ljava/net/InetAddress;)V");
- args[0].l=inetAddressObject;
- jobjectrouteInfoObject=env->NewObjectA(cls,method,args);
- cls=env->FindClass("android/net/DhcpInfoInternal");
- method=env->GetMethodID(cls,"addRoute","(Landroid/net/RouteInfo;)V");
- args[0].l=routeInfoObject;
- env->CallVoidMethodA(info,method,args);
- }else{
- //ifwehaveanexception(hostnotfoundperhaps),justdon'taddtheroute
- env->ExceptionClear();
- }
- env->SetIntField(info,dhcpInfoInternalFieldIds.prefixLength,prefixLength);
- env->SetObjectField(info,dhcpInfoInternalFieldIds.dns1,env->NewStringUTF(dns1));
- env->SetObjectField(info,dhcpInfoInternalFieldIds.dns2,env->NewStringUTF(dns2));
- env->SetObjectField(info,dhcpInfoInternalFieldIds.serverAddress,
- env->NewStringUTF(server));
- env->SetIntField(info,dhcpInfoInternalFieldIds.leaseDuration,lease);
- }
- return(jboolean)(result==0);
- }
static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname, jobject info, bool renew){ int result; char ipaddr[PROPERTY_VALUE_MAX]; uint32_t prefixLength; char gateway[PROPERTY_VALUE_MAX]; char dns1[PROPERTY_VALUE_MAX]; char dns2[PROPERTY_VALUE_MAX]; char server[PROPERTY_VALUE_MAX]; uint32_t lease; const char *nameStr = env->GetStringUTFChars(ifname, NULL); if (nameStr == NULL) return (jboolean)false; if (renew) { result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength, dns1, dns2, server, &lease); } else { result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength, dns1, dns2, server, &lease); //调用 dhcp_utils.c 中的函数,获取route } env->ReleaseStringUTFChars(ifname, nameStr); if (result == 0) { env->SetObjectField(info, dhcpInfoInternalFieldIds.ipaddress, env->NewStringUTF(ipaddr)); // set the gateway jclass cls = env->FindClass("java/net/InetAddress"); jmethodID method = env->GetStaticMethodID(cls, "getByName", "(Ljava/lang/String;)Ljava/net/InetAddress;"); jvalue args[1]; args[0].l = env->NewStringUTF(gateway); jobject inetAddressObject = env->CallStaticObjectMethodA(cls, method, args); if (!env->ExceptionOccurred()) { cls = env->FindClass("android/net/RouteInfo"); method = env->GetMethodID(cls, "<init>", "(Ljava/net/InetAddress;)V"); args[0].l = inetAddressObject; jobject routeInfoObject = env->NewObjectA(cls, method, args); cls = env->FindClass("android/net/DhcpInfoInternal"); method = env->GetMethodID(cls, "addRoute", "(Landroid/net/RouteInfo;)V"); args[0].l = routeInfoObject; env->CallVoidMethodA(info, method, args); } else { // if we have an exception (host not found perhaps), just don't add the route env->ExceptionClear(); } env->SetIntField(info, dhcpInfoInternalFieldIds.prefixLength, prefixLength); env->SetObjectField(info, dhcpInfoInternalFieldIds.dns1, env->NewStringUTF(dns1)); env->SetObjectField(info, dhcpInfoInternalFieldIds.dns2, env->NewStringUTF(dns2)); env->SetObjectField(info, dhcpInfoInternalFieldIds.serverAddress, env->NewStringUTF(server)); env->SetIntField(info, dhcpInfoInternalFieldIds.leaseDuration, lease); } return (jboolean)(result == 0);}[cpp] view plain copy print ?
- staticjbooleanandroid_net_utils_runDhcp(JNIEnv*env,jobjectclazz,jstringifname,jobjectinfo)
- {
- returnandroid_net_utils_runDhcpCommon(env,clazz,ifname,info,false);
- }
- staticjbooleanandroid_net_utils_runDhcpRenew(JNIEnv*env,jobjectclazz,jstringifname,jobjectinfo)
- {
- returnandroid_net_utils_runDhcpCommon(env,clazz,ifname,info,true);
- }
- staticjbooleanandroid_net_utils_stopDhcp(JNIEnv*env,jobjectclazz,jstringifname)
- {
- intresult;
- constchar*nameStr=env->GetStringUTFChars(ifname,NULL);
- result=::dhcp_stop(nameStr);//这个调用libnetutils中的dhcp_utils.c
- env->ReleaseStringUTFChars(ifname,nameStr);
- return(jboolean)(result==0);
- }
static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info){ return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);}static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname, jobject info){ return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true);}static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname){ int result; const char *nameStr = env->GetStringUTFChars(ifname, NULL); result = ::dhcp_stop(nameStr); // 这个调用 libnetutils 中的 dhcp_utils.c env->ReleaseStringUTFChars(ifname, nameStr); return (jboolean)(result == 0);}
5. 新添加的2个函数: removeDefaultRoute() 和 configureInterface(): [cpp] view plain copy print ?
- staticjintandroid_net_utils_removeDefaultRoute(JNIEnv*env,jobjectclazz,jstringifname)
- {
- intresult;
- constchar*nameStr=env->GetStringUTFChars(ifname,NULL);
- result=::ifc_remove_default_route(nameStr);
- env->ReleaseStringUTFChars(ifname,nameStr);
- return(jint)result;
- }
- staticjbooleanandroid_net_utils_configureInterface(JNIEnv*env,
- jobjectclazz,
- jstringifname,
- jintipaddr,
- jintmask,
- jintgateway,
- jintdns1,
- jintdns2)
- {
- intresult;
- uint32_tlease;
- constchar*nameStr=env->GetStringUTFChars(ifname,NULL);
- result=::ifc_configure(nameStr,ipaddr,mask,gateway,dns1,dns2);
- env->ReleaseStringUTFChars(ifname,nameStr);
- return(jboolean)(result==0);
- }
static jint android_net_utils_removeDefaultRoute(JNIEnv* env, jobject clazz, jstring ifname){ int result; const char *nameStr = env->GetStringUTFChars(ifname, NULL); result = ::ifc_remove_default_route(nameStr); env->ReleaseStringUTFChars(ifname, nameStr); return (jint)result;}static jboolean android_net_utils_configureInterface(JNIEnv* env, jobject clazz, jstring ifname, jint ipaddr, jint mask, jint gateway, jint dns1, jint dns2){ int result; uint32_t lease; const char *nameStr = env->GetStringUTFChars(ifname, NULL); result = ::ifc_configure(nameStr, ipaddr, mask, gateway, dns1, dns2); env->ReleaseStringUTFChars(ifname, nameStr); return (jboolean)(result == 0);}
6. libnetutils.so C 库导出来的 函数名, 这里主要用到了 ifc_utils.c 和 dhcp_utils.c 中的一些函数: [cpp] view plain copy print ?
- extern"C"{
- intifc_enable(constchar*ifname);
- intifc_disable(constchar*ifname);
- intifc_reset_connections(constchar*ifname,intreset_mask);
- intifc_remove_default_route(constchar*ifname);
- intifc_configure(constchar*ifname,
- in_addr_taddress,
- in_addr_tprefixLength,
- in_addr_tgateway,
- in_addr_tdns1,
- in_addr_tdns2);
- intdhcp_do_request(constchar*ifname,
- constchar*ipaddr,
- constchar*gateway,
- uint32_t*prefixLength,
- constchar*dns1,
- constchar*dns2,
- constchar*server,
- uint32_t*lease);
- intdhcp_do_request_renew(constchar*ifname,
- constchar*ipaddr,
- constchar*gateway,
- uint32_t*prefixLength,
- constchar*dns1,
- constchar*dns2,
- constchar*server,
- uint32_t*lease);
- intdhcp_stop(constchar*ifname);
- intdhcp_release_lease(constchar*ifname);
- char*dhcp_get_errmsg();
- }
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看到能调到
- E/EthernetStateTracker( 185): DhcpHandler: DHCP request failed: Timed out waiting for dhcpcd to start
- D/EthernetStateTracker( 185): DhcpHandler: DHCP request started
说明patch是好的能正常工作,能正常掉用dhcp,只是DHCP运行不成功。
然后我查了 getprop: 显示 init.svc.dhcpcd_eth0 = stop
正常应该是running的,这样DHCP 才能运行成功。
最后调试了两天,才搞明白,原来是 init.rc 中 dhcpcd_eth0 守护进程的问题:
改成:
- on property:init.svc.dhcpcd_eth0=stopped
- start dhcpcd_eth0
- service dhcpcd_eth0 /system/bin/dhcpcd -ABKL -f /system/etc/dhcpcd/dhcpcd.conf -d eth0
- class main
- disabled
- oneshot
这样就可以了。
这时init.svc.dhcpcd_eth0 就会是 running 了。这时再点击Setting -> ethernet configuration, DHCP就能正常分配IP了。
libnetutils 和dhcpcd 调用过程如下:
1. libnetutils 调用过程:
- jni
- =>runDhcp
- =>android_net_utils_runDhcp
- libs/netutils/dhcp_utils.c
- =>dhcp_do_request
- =>
- static const char DAEMON_NAME[] = "dhcpcd";
- static const char DAEMON_PROP_NAME[] = "init.svc.dhcpcd";
- static const char DHCP_PROP_NAME_PREFIX[] = "dhcp";
- const char *ctrl_prop = "ctl.start";
- const char *desired_status = "running";
- snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result",
- DHCP_PROP_NAME_PREFIX,
- interface);
- property_set(result_prop_name, "");//设置dhcp.eth0.result="";等到成功完成dhcp之后,
- property_set(ctrl_prop, DAEMON_NAME);//向名字为dhcpcd的service,发送"ctrl.start"启动命令字,该service在init.rc中
- //init.rc中dhcpcd服务进程命令字
- //service dhcpcd /system/bin/dhcpcd eth0
- // disabled
- // oneshot
- wait_for_property(DAEMON_PROP_NAME, desired_status, 10);
- //init.c=>init进程
- //=>handle_property_set_fd因为是"ctrl.start"命令字,所以调用handle_control_message处理控制信息
- //=>handle_control_message
- //=>msg_start
- //=>
- // struct service *svc = service_find_by_name(name);
- // service_start(svc);//启动svc,即执行:/system/bin/dhcpcd eth0
- //=>service_start
- //=>pid = fork();
- // if(pid == 0)execve(svc->args[0], (char**) svc->args, (char**) ENV);子进程执行execve运行/system/bin/dhcpcd,参数为eth0
- //=>否则父进程,即init进程将
- //=>notify_service_state(svc->name, "running");设置该svc的状态prop
- // snprintf(pname, sizeof(pname), "init.svc.%s", name);
- // property_set(pname, state);//所以这样上面wait_for_property(DAEMON_PROP_NAME, desired_status, 10);也才能够正常pass[luther.gliethttp].
- wait_for_property(result_prop_name, NULL, 15);//等待dhcp.eth0.result=非空
2. dhcpcd 调用过程:
- system/extra/dhcpcd-4.0.0-beta9/dhcpcd.c
- dhcpcd
- =>main
- # define SYSCONFDIR "/system/etc/dhcpcd"
- #define PACKAGE "dhcpcd"
- # define CONFIG SYSCONFDIR "/" PACKAGE ".conf"
- # define LIBEXECDIR "/system/etc/dhcpcd"
- # define SCRIPT LIBEXECDIR "/" PACKAGE "-run-hooks"
- =>strlcpy(options->script, SCRIPT, sizeof(options->script));//默认的options->script="/system/etc/dhcpcd /dhcpcd-run-hooks"
- =>f = fopen(cf ? cf : CONFIG, "r");//如果没有指定.conf文件,那么使用默认.conf文件
- =>parse_config_line//解析"/system/etc/dhcpcd/dhcpcd.conf"默认配置文件
- =>parse_option
- =>如果在"/system/etc/dhcpcd/dhcpcd.conf"有"script"这个节
- =>那么执行strlcpy(options->script, oarg, sizeof(options->script));直接拷贝
- /*
- {"script", required_argument, NULL, 'c'},
- {"option", required_argument, NULL, 'o'},
- "/system/etc/dhcpcd/dhcpcd.conf"中的部分内容如下:
- ...
- option domain_name_servers, domain_name, domain_search, host_name
- ...
- */
- =>dhcp_run
- =>handle_dhcp_packet
- =>handle_dhcp
- =>bind_dhcp
- reason = "TIMEOUT";reason = "BOUND";reason = "REBIND";reason = "RENEW";
- system/extra/dhcpcd-4.0.0-beta9/configure.c
- => configure(iface, reason, state->new, state->old, &state->lease, options, 1);
- //如果dhcp超时或者dhcp成功,都会调用exec_script来执行脚本,
- //执行setprop dhcp.${interface}.result "failed"或者
- //执行setprop dhcp.${interface}.result "ok"
- =>exec_script(options, iface->name, reason, NULL, old);
- =>然后configure_env通过环境变量将reason传递到脚本中
- int exec_script(const struct options *options, const char *iface, const char *reason,
- const struct dhcp_message *dhcpn, const struct dhcp_message *dhcpo)
- =>pid = fork();
- =>if(pid == 0)execve(options->script, argv, env);//子进程执行脚本,默认"/system/etc/dhcpcd/dhcpcd-run-hooks"
- //dhcpcd-run-hooks脚本会根据level值,决定是否执行system/etc/dhcpcd/dhcpcd-hook/*目录下的相应文件
- //我们的系统在该system/etc/dhcpcd/dhcpcd-hook/*目录下有如下3个文件
- //95-configured
- //20-dns.conf
- //01-test
- =>父进程返回while (waitpid(pid, &status, 0) == -1)等待子进程脚本执行完成
- system/extra/dhcpcd-4.0.0-beta9/dhcpcd-hooks/20-dns.conf
- system/extra/dhcpcd-4.0.0-beta9/dhcpcd-hooks/95-configured
- ...
- setprop dhcp.${interface}.ipaddress "${new_ip_address}"
- setprop dhcp.${interface}.result "ok"//设置属性为ok
- 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
这里代码比较多,暂不细究了。
更多相关文章
- C语言函数以及函数的使用
- android selector 中的几个关键状态
- android aidl 进程通信 调用错误
- 知识梳理之Android进程
- Android多进程之Binder解绑监听的问题
- android状态栏工具类
- android检查手机网络状态
- 有关XML的点击状态背景图的设置