Android4.0.3/Android4.2.2 添加 Ethernet

基于Android4.0.3系统上:

在网上在网上查找ethernet移植相关资料时发现,若要移植的是android-xxx的版本的ethernet,就需要android-x86在xxx版本上的相关源码。但是查看android-x86 4.0版本的源码(目前没找到android-x86 4.0.3版本),发现android-x86 4.0版本中也没包含有ethernet相关代码,故下载了ethernet 补丁文件。

下载地址:http://www.android-x86.org/download

下载: Patch下的ethernet.diff.tar.gz。

把下载的补丁放至linux中解压,用patch命令分别给build、framework、package相关目录打补丁,如:

把frameworks-base.diff放到\frameworks\base下,用命令 patch -p1 <frameworks-base.diff即可打好该目录下的补丁。(注:补丁一定要打全,否则编译很容易报错)

打好补丁后,还要做些修改:

1. 在EthernetStateTracker.java的 

public void defaultRouteSet(boolean enabled) {
        mDefaultRouteSet.set(enabled);
    }后加上下面两个继承接口函数:

@Override
 public void setPolicyDataEnable(boolean enabled){
  
 }

 @Override
 public void setUserDataEnable(boolean arg0) {
  // TODO Auto-generated method stub
  
 }


2. system\core\libnetutils\dhcp_utils.c的 dhcp_do_request函数中,把


snprintf(daemon_cmd,sizeof(daemon_cmd),"%s","dhcpcd_wlan0");改成

snprintf(daemon_cmd,sizeof(daemon_cmd),"%s","dhcpcd_eth0");


不过这样修改会导致连接WiFi的时候获取不到IP,故后续修改成如下:


  if (property_get(HOSTNAME_PROP_NAME, prop_value, NULL) && (prop_value[0] != '\0'))
       // snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:-h %s %s", DAEMON_NAME, daemon_suffix,
        //         prop_value, interface);
          snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s", DAEMON_NAME, interface);
    else
     snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s", DAEMON_NAME, interface);
     //   snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:%s", DAEMON_NAME, daemon_suffix, interface);
/// add by Leslie Xiao  ///
   //  snprintf(daemon_cmd,sizeof(daemon_cmd),"%s","dhcpcd_wlan0");
//     snprintf(daemon_cmd,sizeof(daemon_cmd),"%s","dhcpcd_eth0");

3.在device\samsung\xxxx\init.rc最后添加DHCP服务:


service dhcpcd_eth0 /system/bin/dhcpcd -ABKL -d eth0
class main
disabled
oneshot 

service iprenew_eth0 /system/bin/dhcpcd -n
disabled
oneshot


同时确保WiFi的DHCP也写成相应的格式以匹配dhcp_utils.c中的修改,如:


service dhcpcd_wlan0 /system/bin/dhcpcd -ABKL -d wlan0
    class main
    disabled
    oneshot


编译源码,期间会提示有提示要 make-update api,执行后即可。到此,即可通过setting界面自动获取IP连接上ethernet。

目前分析理解:

 EthernetManager:以太网配置的Android API接口,可通过getSystemService接口获取

 NetWorkStateTracker: 每种网络都有各自NetWorkStateTracker的子类, 来负责以太网状态的监听, ConnectivityService统一管理它们。

 EthernetService:负责配置信息的保存和读取

 EthernetStateTracker:继承NetWorkStateTracker, 负责以太网状态的监听和配置

系统启动时EthernetStateTracker就会创建EthernetMonitor线程来监听网络状态信息, 监听的通过jni调用c代码完成的, 原理就是监听NetLink Socket, 网络连接或断开时这个socket端口就会接收到信息。当有网线连接上时,EthernetMonitor线程就会给EthernetStateTracker发送EVENT_HW_PHYCONNECT消息, EthernetStateTracker读取配置信息, 由于我们在Settings设置为DHCP, 就会通过DhcpHandle给DhcpThread发送EVENT_DHCP_START信息, DhcpThread就会运行NetUtil.runDhcp()来自动获取网络地址。接下来EthernetMonitor线程又会收到网络已通的消息, 并通过EVENT_HW_CONNECTED通知EthernetStateTracker EthernetStateTracker接着会发送EVENT_STATE_CHANGED消息给ConnectivityService。


4.静态ip部分(+表示要添加的内容)


(1)frameworks\base\ethernet\java\android\net\ethernet\EthernetStateTracker.java
a.   import android.net.DhcpInfoInternal;
   + import android.net.DhcpInfo;

b.   private DhcpInfoInternal  mDhcpInfo;
   + private DhcpInfo  nDhcpInfo;

c.   mDhcpInfo = new DhcpInfoInternal ();
   + nDhcpInfo = new DhcpInfo ();

d. 把 mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);
        } else 后被注释掉的部分还原,同时把该部分的mDhcpInfo都改成 nDhcpInfo,如下:
            nDhcpInfo.ipAddress = lookupHost(info.getIpAddress());
            nDhcpInfo.gateway = lookupHost(info.getRouteAddr());
            nDhcpInfo.netmask = lookupHost(info.getNetMask());
            nDhcpInfo.dns1 = lookupHost(info.getDnsAddr());
            nDhcpInfo.dns2 = 0;

            if (localLOGV) Slog.i(TAG, "set ip manually " + nDhcpInfo.toString());
            NetworkUtils.removeDefaultRoute(info.getIfName());
            if (NetworkUtils.configureInterface(info.getIfName(), nDhcpInfo)) {

(2)frameworks\base\core\java\android\net\NetworkUtils.java
a. import android.util.Log;
  +import android.net.DhcpInfo;

b.  public native static int resetConnections(String interfaceName, int mask);
+ /** Remove the default route for the named interface. */
+  public native static int removeDefaultRoute(String interfaceName);

c.    public static int netmaskIntToPrefixLength(int netmask) {
        return Integer.bitCount(netmask);
    }
   + public static boolean configureInterface(String interfaceName, DhcpInfo ipInfo) {
   +     return configureNative(interfaceName,
   +        ipInfo.ipAddress,
   +        netmaskIntToPrefixLength(ipInfo.netmask),
   +         ipInfo.gateway,
   +         ipInfo.dns1,
   +         ipInfo.dns2);
   + }
   + private native static boolean configureNative(
   +     String interfaceName, int ipAddress, int prefixLength, int gateway, int dns1, int dns2);

(3) frameworks\base\core\jni\android_net_NetUtils.cpp
a. int ifc_reset_connections(const char *ifname, int reset_mask);
  +int ifc_remove_default_route(const char *ifname);
  +int ifc_configure(const char *ifname, in_addr_t ipaddr, uint32_t prefixLength,in_addr_t gateway, in_addr_t dns1, in_addr_t   dns2);

b.
   static jstring android_net_utils_getDhcpError(JNIEnv* env, jobject clazz)
   {
      return env->NewStringUTF(::dhcp_get_errmsg());
    }
  +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 prefixLength,
  +     jint gateway,
  +      jint dns1,
  +      jint dns2)
+{
  +  int result;
  +  uint32_t lease;
  +  const char *nameStr = env->GetStringUTFChars(ifname, NULL);
  +  result = ::ifc_configure(nameStr, ipaddr,prefixLength, gateway, dns1, dns2);
  +  env->ReleaseStringUTFChars(ifname, nameStr);
  +  return (jboolean)(result == 0);
+}

c.
  static JNINativeMethod gNetworkUtilMethods[] = {
    /* name, signature, funcPtr */
     { "enableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_enableInterface },
   + { "removeDefaultRoute", "(Ljava/lang/String;)I",  (void *)android_net_utils_removeDefaultRoute },
   + { "configureNative", "(Ljava/lang/String;IIIII)Z",  (void *)android_net_utils_configureInterface },

编译烧写完成后,在界面上可以设置静态ip且正常上网了。同时在也不影响在终端中用netcfg eth0 up ,netcfg eth0 dhcp打开自动获取ip。

注:在Android4.0.3版本中,在ethernet为打开状态时,DHCP或static方式获取IP好像都不成功,若要切换,需先关了ethernet再进行切换即可,或者切换后再重启一下ethernet也可。具体大家可以试试。



基于Android4.2.2系统上:

在基于Android4.0.3版本移植的基础上,针对Android4.2.2版本还需做如下修改:

1.在\bionic\libc\kernel\common\linux\socket.h中添加定义:


typedef unsigned short sa_family_t;


不加此定义会报错如下:


target thumb C++: libandroid_runtime <= frameworks/base/core/jni/android_net_ethernet.cpp
In file included from frameworks/base/core/jni/android_net_ethernet.cpp:27:0:
bionic/libc/kernel/common/linux/netlink.h:52:2: error: 'sa_family_t' does not name a type
frameworks/base/core/jni/android_net_ethernet.cpp: In function '_jstring* android::android_net_ethernet_waitForEvent(JNIEnv*, jobject)':
frameworks/base/core/jni/android_net_ethernet.cpp:122:49: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
frameworks/base/core/jni/android_net_ethernet.cpp: In function 'int android::netlink_send_dump_request(int, int, int)':
frameworks/base/core/jni/android_net_ethernet.cpp:176:13: error: 'struct sockaddr_nl' has no member named 'nl_family'
frameworks/base/core/jni/android_net_ethernet.cpp: In function 'jint android::android_net_ethernet_initEthernetNative(JNIEnv*, jobject)':
frameworks/base/core/jni/android_net_ethernet.cpp:290:18: error: 'struct sockaddr_nl' has no member named 'nl_family'
frameworks/base/core/jni/android_net_ethernet.cpp:292:19: error: 'struct sockaddr_nl' has no member named 'nl_family'
make: *** [out/target/product/smdk4x12/obj/SHARED_LIBRARIES/libandroid_runtime_intermediates/android_net_ethernet.o] Error 1


跟着Android4.0.3版本netlink.h中看sa_family_t定义,但是定义sa_family_t的地方太多了,看看netlink.h中发现有包含#include <linux/socket.h> 头文件,发现sa_family_t的定义在socket.h中,typedef unsigned short sa_family_t; 但是在Android4.2.2版本中却没有,故加上继续编译。


2. 在EthernetStateTracker.java后面加


@Override
public void captivePortalCheckComplete(){

}


否则报错:


 target Java: framework (out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes)
frameworks/base/ethernet/java/android/net/ethernet/EthernetStateTracker.java:60: android.net.ethernet.EthernetStateTracker is not abstract and does not override abstract method captivePortalCheckComplete() in android.net.NetworkStateTracker
public   class EthernetStateTracker extends Handler implements NetworkStateTracker {
         ^
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
make: *** [out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes-full-debug.jar] Error 41

原理同Android4.0.3中的第一点。

3.  \frameworks\base\services\java\com\android\server\ConnectivityService.java
添加 
import android.net.ethernet.EthernetStateTracker;

同时在public NetworkStateTracker createTracker(int targetNetworkType, NetworkConfig config) {}函数中,因为架构与Android4.0.3不太一样,故该文件更新如下:

……
……
        case TYPE_WIMAX:
                 return makeWimaxStateTracker(mContext, mTrackerHandler);
        case TYPE_ETHERNET:
  //return EthernetDataTracker.getInstance();
                EthernetStateTracker est = new EthernetStateTracker(mContext, mTrackerHandler);
                EthernetService ethService = new EthernetService(mContext, est);
                ServiceManager.addService(Context.ETHERNET_SERVICE, ethService);
               // mNetTrackers[ConnectivityManager.TYPE_ETHERNET] = est;   //注释掉,否则编译报错
                est.startMonitoring(mContext, mTrackerHandler);
return est;
  
        default:
……
……

编译烧写后,可以在Android4.2.2上界面打开,自动获取ip 或静态设置以太网ip了。但其中还有一个bug暂时还未有时间解决,具体如下:(因时间问题没有画图,但不影响阅读,如有不明之处望指出。)

测试一:


  开机 
  
打开  Ethernet   --eth ok
  


打开 WiFi         --- WiFi ok  eth down


关闭 WiFi         ---- WiFi down  eth ok


关闭 Ethernet    ---- eth down




测试二:


开机


打开 WiFi             ---WiFi ok


打开 Ethernet         --- WiFi ok   eth down


关闭 WiFi             --- WiFi down   eth显示up,但获取不到ip,设置静态ip,netcfg显示所设ip,但ping不通网络


关闭Ethernet         --- eth down




测试三:


开机


打开 wifi            ---WiFi ok


关闭 WiFi           ---WiFi down
 
打开 Ethernet    --- eth ok


关闭 Ethernet       --- eth down


测试四:


开机


打开 Ethernet     ---eth ok


关闭 Ethernet     --- eth down

打开 WiFi         ---WiFi ok


打开Ethernet      --- WiFi ok  eth down


关闭 WiFi         --- WiFi down   eth ok


关闭 Ethernet     ---eth down




结论:
  1. 只要开机后于WiFi 打开之前打开Ethernet,之后无论怎么操作WiFi与Ethernet均正常,否则就会出现测试二那样的例子。
  2. 在手册中强调若要打开Ethernet,则需先关闭WiFi即可。

. 以上纯属个人理解,如有出错之处,望指明,谢谢。

附录:(本移植中所涉及到的文件)

1. Modify \build\core\pathmap.mk
2. Modify \device\samsung\xxxx\init.rc
3. Modify \frameworks\base\core\java\android\app\ContextImpl.java
4. Modify \frameworks\base\core\java\android\app\DownloadManager.java
5. Modify \frameworks\base\core\java\android\content\Context.java
6. Modify \frameworks\base\core\java\android\net\NetworkUtils.java
7. Modify \frameworks\base\core\java\android\provider\Settings.java
8. Modify \frameworks\base\core\jni\Android.mk
9. Add \frameworks\base\core\jni\android_net_ethernet.cpp
10. Modify \frameworks\base\core\jni\android_net_NetUtils.cpp
11. Modify \frameworks\base\core\jni\AndroidRuntime.cpp
12. Modify \frameworks\base\core\res\res\values\config.xml
13. Add \frameworks\base\ethernet\
14. Add \frameworks\base\services\java\com\android\server\EthernetService.java
15. Modify \frameworks\base\services\java\com\android\server\ConnectivityService.java
16. Modify \frameworks\base\Android.mk
17. Add \packages\apps\Settings\res\drawable-hdpi\ic_settings_ethernet.png
18. Add \packages\apps\Settings\res\drawable-mdpi\ic_settings_ethernet.png
19. Add \packages\apps\Settings\res\layout\eth_configure.xml
20. Modify \packages\apps\Settings\res\values\strings.xml
21. Modify \packages\apps\Settings\res\values-de\strings.xml
22. Add \packages\apps\Settings\res\xml\ethernet_settings.xml
23. Modify \packages\apps\Settings\res\xml\settings_headers.xml
24. Add \packages\apps\Settings\src\com\android\settings\ethernet\
25. Add \packages\apps\Settings\src\com\android\settings\EthernetSettings.java
26. Modify \packages\apps\Settings\AndroidManifest.xml
27. Modify \packages\providers\DownloadProvider\src\com\android\providers\downloads\DownloadInfo.java
28. Modify \system\core\libnetutils\dhcp_utils.c
29 Modify \bionic\libc\kernel\common\linux\socket.h

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值