EthernetNative 和 android_net_ethernet.cpp

除了android_net_netutils.cpp 外 还有一个JNI : android_net_ethernet.cpp

1. frameworks/base/ethernet/java/android/net/ethernet/EthernetNative.java 代码会调用这个JNI

package android.net.ethernet;

/**
 * Native calls for sending requests to the kernel,
 * {@hide}
 */
public class EthernetNative {
    public native static String getInterfaceName(int i); //get eth0, sit0
    public native static int getInterfaceCnt();  //
    public native static int initEthernetNative(); 
    public native static String waitForEvent();
}

2. JNINativeMethod gEthernetMethods[]:

    static JNINativeMethod gEthernetMethods[] = {
        {"waitForEvent", "()Ljava/lang/String;",
         (void *)android_net_ethernet_waitForEvent},
        {"getInterfaceName", "(I)Ljava/lang/String;",
         (void *)android_net_ethernet_getInterfaceName},
        {"initEthernetNative", "()I",
         (void *)android_net_ethernet_initEthernetNative},
        {"getInterfaceCnt","()I",
         (void *)android_net_ethernet_getInterfaceCnt}
    };

3. AndroidRuntime 运行时,会注册 这个NativeMethod:

    int register_android_net_ethernet_EthernetManager(JNIEnv* env)
    {
        jclass eth = env->FindClass(ETH_PKG_NAME);
        LOGI("Loading ethernet jni class");
        LOG_FATAL_IF(eth == NULL, "Unable to find class " ETH_PKG_NAME);
        dhcpInfoFieldIds.dhcpInfoClass =
            env->FindClass("android/net/DhcpInfo");

        if (dhcpInfoFieldIds.dhcpInfoClass != NULL) {
            dhcpInfoFieldIds.constructorId =
                env->GetMethodID(dhcpInfoFieldIds.dhcpInfoClass,
                                 "<init>", "()V");
            dhcpInfoFieldIds.ipaddress =
                env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
                                "ipAddress", "I");
            dhcpInfoFieldIds.gateway =
                env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
                                "gateway", "I");
            dhcpInfoFieldIds.netmask =
                env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
                                "netmask", "I");
            dhcpInfoFieldIds.dns1 =
                env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns1", "I");
            dhcpInfoFieldIds.dns2 =
                env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns2", "I");
            dhcpInfoFieldIds.serverAddress =
                env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
                                "serverAddress", "I");
            dhcpInfoFieldIds.leaseDuration =
                env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass,
                                "leaseDuration", "I");
        }

        //注册gEthernetMethods[]
        return AndroidRuntime::registerNativeMethods(env,
                                                     ETH_PKG_NAME,
                                                     gEthernetMethods,
                                                     NELEM(gEthernetMethods));
    }

4. waitForEvent():

    static jstring android_net_ethernet_waitForEvent(JNIEnv *env, jobject clazz)
    {
        char *buff;
        struct nlmsghdr *nh;
        struct ifinfomsg *einfo;
        struct iovec iov;
        struct msghdr msg;
        char *result = NULL;
        char rbuf[4096];
        unsigned int left;
        interface_info_t *info;
        int len;

        LOGV("Poll events from ethernet devices");
        /*
         *wait on uevent netlink socket for the ethernet device
         */
        buff = (char *)malloc(NL_POLL_MSG_SZ);
        if (!buff) {
            LOGE("Allocate poll buffer failed");
            goto error;
        }

        iov.iov_base = buff;
        iov.iov_len = NL_POLL_MSG_SZ;
        msg.msg_name = (void *)&addr_msg;
        msg.msg_namelen =  sizeof(addr_msg);
        msg.msg_iov =  &iov;
        msg.msg_iovlen =  1;
        msg.msg_control =  NULL;
        msg.msg_controllen =  0;
        msg.msg_flags =  0;

        if ((len = recvmsg(nl_socket_poll, &msg, 0)) >= 0) {
            LOGV("recvmsg get data");
            result = rbuf;
            left = 4096;
            rbuf[0] = '\0';
            for (nh = (struct nlmsghdr *) buff; NLMSG_OK (nh, len);
                 nh = NLMSG_NEXT (nh, len)) {

                if (nh->nlmsg_type == NLMSG_DONE) {
                    LOGE("Did not find useful eth interface information");
                    goto error;
                }

                if (nh->nlmsg_type == NLMSG_ERROR) {
                    /* Do some error handling. */
                    LOGE("Read device name failed");
                    goto error;
                }

                LOGV(" event :%d  found", nh->nlmsg_type);
                einfo = (struct ifinfomsg *)NLMSG_DATA(nh);
                LOGV("the device flag :%X", einfo->ifi_flags);
                if (nh->nlmsg_type == RTM_DELLINK ||
                    nh->nlmsg_type == RTM_NEWLINK ||
                    nh->nlmsg_type == RTM_DELADDR ||
                    nh->nlmsg_type == RTM_NEWADDR) {
                    int type = nh->nlmsg_type;
                    if (type == RTM_NEWLINK &&
                        (!(einfo->ifi_flags & IFF_LOWER_UP))) {
                        type = RTM_DELLINK;
                    }
                    if ((info = find_info_by_index
                          (((struct ifinfomsg*) NLMSG_DATA(nh))->ifi_index)) != NULL)
                        snprintf(result,left, "%s:%d:",info->name,type);
                    left = left - strlen(result);
                    result =(char *)(result+ strlen(result));
                }

            }
            LOGV("Done parsing");
            rbuf[4096 - left] = '\0';
            LOGV("poll state :%s, left:%d", rbuf, left);
        }


    error:
        free(buff);
        return env->NewStringUTF(rbuf);
    }


5. initEthernetNative():
    static jint android_net_ethernet_initEthernetNative(JNIEnv *env,
                                                        jobject clazz)
    {
        int ret = -1;

    LOGI("==>%s",__FUNCTION__);
        memset(&addr_msg, 0, sizeof(sockaddr_nl));
        addr_msg.nl_family = AF_NETLINK;
        memset(&addr_poll, 0, sizeof(sockaddr_nl));
        addr_poll.nl_family = AF_NETLINK;
        addr_poll.nl_pid = 0;//getpid();
        addr_poll.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;

        /*
         *Create connection to netlink socket
         */
        nl_socket_msg = socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
        if (nl_socket_msg <= 0) {
            LOGE("Can not create netlink msg socket");
            goto error;
        }
        if (bind(nl_socket_msg, (struct sockaddr *)(&addr_msg),
                 sizeof(struct sockaddr_nl))) {
            LOGE("Can not bind to netlink msg socket");
            goto error;
        }

        nl_socket_poll = socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
        if (nl_socket_poll <= 0) {
            LOGE("Can not create netlink poll socket");
            goto error;
        }

        errno = 0;
        if (bind(nl_socket_poll, (struct sockaddr *)(&addr_poll),
                sizeof(struct sockaddr_nl))) {
            LOGE("Can not bind to netlink poll socket,%s", strerror(errno));

            goto error;
        }

        if ((ret = netlink_init_interfaces_list()) < 0) {
            LOGE("Can not collect the interface list");
            goto error;
        }
        LOGE("%s exited with success", __FUNCTION__);
        return ret;

    error:
        LOGE("%s exited with error", __FUNCTION__);
        if (nl_socket_msg > 0)
            close(nl_socket_msg);
        if (nl_socket_poll > 0)
            close(nl_socket_poll);
        return ret;
    }

6. getInterfaceName() 和 getInterfaceCnt():

    static jstring android_net_ethernet_getInterfaceName(JNIEnv *env,
                                                         jobject clazz,
                                                         jint index)
    {
        int i = 0;
        interface_info_t *info;
        LOGI("User ask for device name on %d, list:%X, total:%d",
             index, (unsigned int)interfaces, total_int);
        info = interfaces;
        if (total_int != 0 && index <= (total_int - 1)) {
            while (info) {
                if (index == i) {
                    LOGV("Found: %s", info->name);
                    return env->NewStringUTF(info->name);
                }
                info = info->next;
                i++;
            }
        }
        LOGI("No device name found");
        return env->NewStringUTF(NULL);
    }


    static jint android_net_ethernet_getInterfaceCnt()
    {
        return total_int;
    }








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值