[Network]Android N Ethernet新IP获取机制—IpManager

本文介绍了Android N中 Ethernet IP获取机制的变化,从依赖于/system/bin/dhcpcd到使用DhcpClient并通过IpManager进行管理。IpManager是一个用于获取IP的管理器,它涉及到了IPv4和IPv6的配置与处理过程,为ipv6的支持奠定了基础。在新机制下,Android N直接通过UDP请求包与DHCP Server交互,增强了IP获取的稳定性。
摘要由CSDN通过智能技术生成

android N之前 Ethernet旧的ip获取

Android N之前,即android 5.0和android 6.0的IP获取机制都是通过/system/bin下面的dhcpcd的bin档去拿的ip

//EthernetNetworkFactory.java (frameworks\opt\net\ethernet\java\com\android\server\ethernet)

    public void onRequestNetwork() {
        // TODO: Handle DHCP renew.
        Thread dhcpThread = new Thread(new Runnable() {
            public void run() {
                        ...

                    DhcpResults dhcpResults = new DhcpResults();
                    // TODO: Handle DHCP renewals better.
                    // In general runDhcp handles DHCP renewals for us, because
                    // the dhcp client stays running, but if the renewal fails,
                    // we will lose our IP address and connectivity without
                    // noticing.
                    //通过这个函数call到jni之后,最后run /system/bin/dhcpcd
                    if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {
                        Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
                        // set our score lower than any network could go
                        // so we get dropped.
                        mFactory.setScoreFilter(-1);
                        return;
                    }

不知道是不是dhcpcd本身的问题,这段code其实不是稳定,超时拿不到ip的现象经常可以遇到。只能在这里多加几次try runDhcp。

android N新的拿IP的机制

android N不要了runDhcpcd(),而是通过DhcpClient,这个是android M引入的wifi那边另外一种获得ip的方式,DhcpClient是通过framework发送dhcpcd协议的UDP请求包直接去拿IP,不再使用开源的dhcpcd。在调用DhcpClient的基础之前,google还用了一个状态机IpManager来管理dhcpcd成功还是失败等状态,将ip赋值给IpConfiguration和LinkProperties传递到上层的framework。还有就是加入ipv6的支持,不过ipv6的部分目前还没做好。

//EthernetNetworkFactory.java (frameworks\opt\net\ethernet\java\com\android\server\ethernet)    

        final Thread ipProvisioningThread = new Thread(new Runnable() {
            public void run() {
                if (DBG) {
                    Log.d(TAG, String.format("starting ipProvisioningThread(%s): mNetworkInfo=%s",
                            mIface, mNetworkInfo));
                }

                LinkProperties linkProperties;

                IpConfiguration config = mEthernetManager.getConfiguration();

                if (config.getIpAssignment() == IpAssignment.STATIC) {
                    if (!setStaticIpAddress(config.getStaticIpConfiguration())) {
                        // We've already logged an error.
                        return;
                    }
                    linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface);
                } else {

                    mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);
                    WaitForProvisioningCallback ipmCallback = new WaitForProvisioningCallback() {
                        @Override
                        public void onLinkPropertiesChange(LinkProperties newLp) {
                            synchronized(EthernetNetworkFactory.this) {
                                if (mNetworkAgent != null && mNetworkInfo.isConnected()) {
                                    mLinkProperties = newLp;
                                    mNetworkAgent.sendLinkProperties(newLp);
                                }
                            }
                        }
                    };

                    synchronized(EthernetNetworkFactory.this) {
                        stopIpManagerLocked();
                        //IPManger,用这个代替之前的runDhcpcd()
                        mIpManager = new IpManager(mContext, mIface, ipmCallback);

                        if (config.getProxySettings() == ProxySettings.STATIC ||
                                config.getProxySettings() == ProxySettings.PAC) {
                            mIpManager.setHttpProxy(config.getHttpProxy());
                        }

                        final String tcpBufferSizes = mContext.getResources().getString(
                                com.android.internal.R.string.config_ethernet_tcp_buffers);
                        if (!TextUtils.isEmpty(tcpBufferSizes)) {
                            mIpManager.setTcpBufferSizes(tcpBufferSizes);
                        }

                        final ProvisioningConfiguration provisioningConfiguration =
                                mIpManager.buildProvisioningConfiguration()
                                        .withProvisioningTimeoutMs(0)
                                        .build();
                        //start
                        mIpManager.startProvisioning(provisioningConfiguration);
                    }
                    //通过callback去拿到新的IP
                    linkProperties = ipmCallback.waitForProvisioning();
                    if (linkProperties == null) {
                        Log.e(TAG, "IP provisioning error");
                        // set our score lower than any network could go
                        // so we get dropped.
                        mFactory.setScoreFilter(-1);
                        synchronized(EthernetNetworkFactory.this) {
                            stopIpManagerLocked();
                        }
                        return;
                    }
                }

IpManager

IpManager,是wifi和Ethernet都会用到。把它定义为获取ip的管理器好了。

1.构造函数

    public IpManager(Context context, String ifName, Callback callback)
                throws IllegalArgumentException {
        this(context, ifName, callback, INetworkManagementService.Stub.asInterface(
                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)));
    }

    /**
     * An expanded constructor, useful for dependency injection.
     */
    public IpManager(Context context, String ifName, Callback callback,
            INetworkManagementService nwService) throws IllegalArgumentException {
        super(IpManager.class.getSimpleName() + "." + ifName);
        mTag = getName();

        mContext = context;
        //网口的名字,eth0 or wlan0
        mInterfaceName = ifName;
        mClatInterfaceName = CLAT_PREFIX + ifName;
        mCallback = new LoggingCallbackWrapper(callback);
        //NetworkManagementService对象,可以对Interface做一些操作
        mNwService = nwService;

        //检测Interface的状态变化
        mNetlinkTracker = new NetlinkTracker(
                mInterfaceName,
                new NetlinkTracker.Callback() {
                    @Override
                    public void update() {
                        sendMessage(EVENT_NETLINK_LINKPROPERTIES_CHANGED);
                    }
                }) {
            @Override
            public void interfaceAdded(String iface) {
   
                super.interfaceAdded(iface);
                if (mClatInterfaceName.equals(iface)) {
                    mCallback.setNeighborDiscoveryOffload(false);
                }
            }

    
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值