基于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,故后续修改成如下:
// 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, prefixLengt h , 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。
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中的第一点。
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即可。
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