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
/**
* 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 中的函数映射关系。
/*
* 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():
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():
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);
}
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():
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 中的一些函数:
extern "C" {
int ifc_enable(const char *ifname);
int ifc_disable(const char *ifname);
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 address,
in_addr_t prefixLength,
in_addr_t gateway,
in_addr_t dns1,
in_addr_t dns2);
int dhcp_do_request(const char *ifname,
const char *ipaddr,
const char *gateway,
uint32_t *prefixLength,
const char *dns1,
const char *dns2,
const char *server,
uint32_t *lease);
int dhcp_do_request_renew(const char *ifname,
const char *ipaddr,
const char *gateway,
uint32_t *prefixLength,
const char *dns1,
const char *dns2,
const char *server,
uint32_t *lease);
int dhcp_stop(const char *ifname);
int dhcp_release_lease(const char *ifname);
char *dhcp_get_errmsg();
}