因为这次用到以太网模块无需自己移植供应商的驱动,只需要在内核中配置选项中加入CONFIG_USB_USBNET=y 即可。
主要修改的是系统层的代码,这里主要是讲ethernet的流程。
android4.3 本身是支持以太网的,不过需要修改一些代码。
1. frameworks/base/services/java/com/android/server/ConnectivityService.java
mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
com.android.internal.R.integer.config_networkTransitionTimeout);
mNetTrackers = new NetworkStateTracker[
ConnectivityManager.MAX_NETWORK_TYPE+1];
mCurrentLinkProperties = new LinkProperties[ConnectivityManager.MAX_NETWORK_TYPE+1];
mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
// Load device network attributes from resources
String[] raStrings = context.getResources().getStringArray(
com.android.internal.R.array.radioAttributes);
for (String raString : raStrings) {
RadioAttributes r = new RadioAttributes(raString);
if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
loge("Error in radioAttributes - ignoring attempt to define type " + r.mType);
continue;
}
if (mRadioAttributes[r.mType] != null) {
loge("Error in radioAttributes - ignoring attempt to redefine type " +
r.mType);
continue;
}
mRadioAttributes[r.mType] = r;
}
// TODO: What is the "correct" way to do determine if this is a wifi only device?
boolean wifiOnly = SystemProperties.getBoolean("ro.radio.noril", false);
log("wifiOnly=" + wifiOnly);
String[] naStrings = context.getResources().getStringArray(
com.android.internal.R.array.networkAttributes);
for (String naString : naStrings) {
try {
NetworkConfig n = new NetworkConfig(naString);
if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
loge("yl Error in networkAttributes - ignoring attempt to define type " +
n.type);
continue;
}
if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) {
loge("yl networkAttributes - ignoring mobile as this dev is wifiOnly " +
n.type);
continue;
}
if (mNetConfigs[n.type] != null) {
loge("yl Error in networkAttributes - ignoring attempt to redefine type " +
n.type);
continue;
}
if (mRadioAttributes[n.radio] == null) {
loge("yl Error in networkAttributes - ignoring attempt to use undefined " +
"radio " + n.radio + " in network type " + n.type);
continue;
}
mNetConfigs[n.type] = n;
mNetworksDefined++;
} catch(Exception e) {
// ignore it - leave the entry null
}
}
上面代码可以看出,ConnectivityService,会读取radioAttributes的网络配置,所以这里会把所有的网络类型读出来,并调用startMonitoring,然而默认的代码并没有添加ethernet的配置。所以需要添加下面的代码:
2.frameworks/base/core/res/res/values/config.xml
<span style="font-size:14px;">--- a/frameworks/base/core/res/res/values/config.xml
+++ b/frameworks/base/core/res/res/values/config.xml
@@ -152,6 +152,7 @@
<item>"mobile_ims,11,0,2,60000,true"</item>
<item>"mobile_cbs,12,0,2,60000,true"</item>
<item>"wifi_p2p,13,1,0,-1,true"</item>
+ <item>"ethernet,9,9,0,-1,true"</item>
</string-array>
<!-- Array of ConnectivityManager.TYPE_xxxx constants for networks that may only
@@ -170,6 +171,7 @@
<string-array translatable="false" name="radioAttributes">
<item>"1,1"</item>
<item>"0,1"</item>
+ <item>"9,1"</item>
</string-array>
<!-- Set of NetworkInfo.getType() that reflect data usage. --></span>
3. frameworks/base/core/java/android/net/EthernetDataTracker.java
<span style="font-size:18px;"> </span><span style="font-size:14px;"> // already exists
sIfaceMatch = context.getResources().getString(
com.android.internal.R.string.config_ethernet_iface_regex);
try {
Log.e(TAG, "yl>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + "sIfaceMatch" + sIfaceMatch);
final String[] ifaces = mNMService.listInterfaces();
for (String iface : ifaces) {
Log.e(TAG, "yl>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + "iface" + iface);
if (iface.matches(sIfaceMatch)) {
mIface = iface;
mNMService.setInterfaceUp(iface);
InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
mLinkUp = config.hasFlag("up");
if (config != null && mHwAddr == null) {
mHwAddr = config.getHardwareAddress();
if (mHwAddr != null) {
mNetworkInfo.setExtraInfo(mHwAddr);
}
}
// if a DHCP client had previously been started for this interface, then stop it
NetworkUtils.stopDhcp(mIface);
reconnect();
break;
}
}</span>
startMonitoring,会找到第一个eth开头的
( <string translatable="false" name="config_ethernet_iface_regex">eth\\d</string>)
的有线网络设备。假设这里的网络设备为eth0,这里会把该设备up,并且rundhcp,如若成功,则通知上层,网络连接成功
4. frameworks\base\core\java\android\net\NetworkUtils.java
public native static boolean runDhcp(String interfaceName, DhcpResults dhcpResults);
frameworks\base\core\jni\android_net_NetUtils.cpp
android_net_utils_runDhcp
android_net_utils_runDhcpCommon
::dhcp_do_request_renew
::dhcp_do_request
system\core\libnetutils\Dhcp_utils.c (动态分配ip)
dhcp_do_request
system\core\libnetutils\Ifc_utils.c (静态分配ip,静态设置ip之前,需要动态dhcp成功后,才进行设置)
5.配置启动:init 里面需要添加 dhcp 和 ip renew 服务
+service dhcpcd_eth0 /system/bin/dhcpcd -ABKL
+ class main
+ disabled
+ oneshot
+
+service iprenew_eth0 /system/bin/dhcpcd -n
+ class main
+ disabled
+ oneshot
+
6. 配置的一个例子:
void configureInterface(EthernetDevInfo info) {
if (info.getConnectMode().equals(EthernetDevInfo.ETHERNET_CONN_MODE_DHCP)) {
try {
mNMService.setInterfaceDown(info.getIfName());
mNMService.clearInterfaceAddresses(info.getIfName());
mNMService.setInterfaceUp(info.getIfName());
} catch (RemoteException re){
Log.e(TAG,"DHCP configuration failed: " + re);
} catch (IllegalStateException e) {
Log.e(TAG,"DHCP configuration fialed: " + e);
}
} else {
InterfaceConfiguration ifcg = null;
Log.d(TAG, "Static IP =" + info.getIpAddress());
try {
ifcg = mNMService.getInterfaceConfig(info.getIfName());
ifcg.setLinkAddress(new LinkAddress(NetworkUtils.numericToInetAddress(
info.getIpAddress()), 24));
ifcg.setInterfaceUp();
InetAddress gatewayAddress = NetworkUtils.intToInetAddress(lookupHost(info.getRouteAddr()));
RouteInfo defaultRoute = new RouteInfo(gatewayAddress);
mNMService.addRoute(info.getIfName(),defaultRoute);
mNMService.setInterfaceConfig(info.getIfName(), ifcg);
Log.d(TAG,"Static IP configuration succeeded");
} catch (RemoteException re){
Log.e(TAG,"Static IP configuration failed: " + re);
} catch (IllegalStateException e) {
Log.e(TAG,"Static IP configuration fialed: " + e);
}catch (IllegalArgumentException e) {
Log.e(TAG,"Wrong Static IP: " + e);
Toast.makeText(mContext, "Illegal address inputed. You can not access the Internet.",Toast.LENGTH_SHORT).show();
}
Log.d(TAG, "set ip manually " + info.toString());
SystemProperties.set("net.dns1", info.getDnsAddr());
SystemProperties.set("net." + info.getIfName() + ".dns1",info.getDnsAddr());
SystemProperties.set("net." + info.getIfName() + ".dns2", "0.0.0.0");
updateDevInfo(info);
}
}
7. 上面主要是关于ethernet的流程,具体的开发还有许多细节需要处理:
如,设置里面加入ethernet的配置选项,网线插拔检测,网络的优先级等一些处理,这些可参考android4.0的移植。