Android13 有线网开关研究

Android13 有线网开关研究

本文对比 Android9 自己开发的有线网开关代码。

前言

1、api

Android13 的api 提供了有线网开关 EthernetManager.setEthernetEnabled(boolean),
Android9 如果要设置有线网开关,需要自己实现。

2、问题

Android13 上有出现打开有线网并且接入有线网无ip的情况,
并且调用开关有线网开关无作用(未移除节点eth0),ifconfig etho down/up 操作一次就有ip了。

3、目的

Android9 上有线网开关接口是会关闭节点的;Android13 上开关有线网节点一直是存在的。
所有决定研究一下有线网开关,希望能过解决问题。

主要研究代码是: EthernetTracker.java 的相关处理

之前Android 9 增加的有线网开关文章:
https://blog.csdn.net/wenzhi20102321/article/details/122243396

二、代码分析

1、Android13 上的 EthernetTracker

E:\982\code\android_source\packages\modules\Connectivity\service-t\src\com\android\server\ethernet\EthernetTracker.java


    private final INetd mNetd;

    @VisibleForTesting(visibility = PACKAGE)
    protected void setEthernetEnabled(boolean enabled) {
        mHandler.post(() -> {
            int newState = enabled ? ETHERNET_STATE_ENABLED : ETHERNET_STATE_DISABLED;

            //set state,by liwenzhi ,Start
            Log.i(TAG, "setEthernetEnabled newState = " +newState + ", old state = " + mEthernetState);
            setPersistedState(newState); //自己加的值,用于保存系统属性,不用关注
            //set state,by liwenzhi ,End
            
            if (mEthernetState == newState) return;

            mEthernetState = newState;

            //关键
            if (enabled) {
                trackAvailableInterfaces();//设置有线网可用
            } else {
                // TODO: maybe also disable server mode interface as well.
                untrackFactoryInterfaces();//设置有线网不可用
            }
            broadcastEthernetStateChange(mEthernetState);
        });
    }


    //开启网络
    private void trackAvailableInterfaces() {
        try {
            final String[] ifaces = mNetd.interfaceGetList();
            for (String iface : ifaces) {
                maybeTrackInterface(iface);
            }
        } catch (RemoteException | ServiceSpecificException e) {
            Log.e(TAG, "Could not get list of interfaces " + e);
        }
    }


    //添加有线网节点,一般是 eth0
    private void maybeTrackInterface(String iface) {
。。。

        addInterface(iface);
        broadcastInterfaceStateChange(iface);
    }


    //添加配置有线网节点
    private void addInterface(String iface) {
        InterfaceConfigurationParcel config = null;
        // Bring up the interface so we get link status indications.
        try {
            PermissionUtils.enforceNetworkStackPermission(mContext);
            NetdUtils.setInterfaceUp(mNetd, iface); // NetdUtils 是Android13 新增的工具类
            config = NetdUtils.getInterfaceConfigParcel(mNetd, iface);
        } catch (IllegalStateException e) {
            // Either the system is crashing or the interface has disappeared. Just ignore the
            // error; we haven't modified any state because we only do that if our calls succeed.
            Log.e(TAG, "Error upping interface " + iface, e);
        }

    }



    //关闭有线网网络
    private void untrackFactoryInterfaces() {
        for (String iface : mFactory.getAvailableInterfaces(true /* includeRestricted */)) {
            stopTrackingInterface(iface);
        }
    }

    //停止有线网节点,一般是eth0
    private void stopTrackingInterface(String iface) {
        removeInterface(iface);
        if (iface.equals(mDefaultInterface)) {
            mDefaultInterface = null;
        }
        broadcastInterfaceStateChange(iface); //发送广播通知该节点网络断开
    }

    //删除有线网节点的数据,应该是断开某个netId
    private void removeInterface(String iface) {
        mFactory.removeInterface(iface);
        maybeUpdateServerModeInterfaceState(iface, false);
    }

关注一下上面的 removeInterface 方法,这里是没移除节点的;

从串口看,ifconfig,不管关开有线网,都是会有eth0 节点的,只是调用关闭的情况是没有ip 的。

扫描二维码关注公众号,回复: 16145044 查看本文章

2、Android13 上的 EthernetTracker

E:\project_android11\code\android\frameworks\opt\net\ethernet\java\com\android\server\ethernet\EthernetTracker.java


private final INetworkManagementService mNMService;

//对比Android11 上开关有线网的最后实现,是通过mNMService 进行开关节点
+    public synchronized void setIntefaceState(boolean state) {
+        try {
+            String[] interfaces = getInterfaces(true);
+            for (String iface : interfaces) {
+                if (isTrackingInterface(iface)) {
+                    if (state) {
+                        mNMService.setInterfaceUp(iface);
+                    } else {
+                        mNMService.setInterfaceDown(iface);
+                    }
+                }
+            }
+            if (state) mHandler.post(this::trackAvailableInterfaces);
+        } catch (Exception e) {
+            Log.e(TAG, "Error change eth state : " + state); 
+        }
+    }

Android 原生没有上面的"+"的代码的,是自己加上去的;
这里的 mNMService.setInterfaceDown(iface) 关闭节点是会移除节点的。

3、对比开关过程

1、Android13 关闭有线网,未移除节点:

EthernetNetworkFactory mFactory;
mFactory.removeInterface(iface);

其实 Android9 的 EthernetTracker也是有 EthernetNetworkFactory 对象,只是没有调到 removeInterface;
Android11 原生代码上,有线网默认是开启的,没有关闭有线网的接口。

其实Android9 也可以参考Android13 只移除某个网络,不移除有线网节点。

2、Android9 关闭有线网,移除节点:

INetworkManagementService mNMService;
mNMService.setInterfaceDown(iface);

虽然Android13 EthernetNetworkFactory.java 没有 INetworkManagementService 对象,但是有类似意义的 INetd 对象。
Android13 上的 NetdUtils 包含了同样意义的 setInterfaceDown 方法。

3、NetdUtils

这个类是Android13 新增的工具类

framework\libs\net\client-libs\netd\com\android\net\module\util\NetdUtils.java

    /**
     * Set the given interface down.
     */
    public static void setInterfaceDown(INetd netd, String iface) {
        final InterfaceConfigurationParcel configParcel = getInterfaceConfigParcel(netd, iface);
        configParcel.flags = removeAndAddFlags(configParcel.flags, IF_STATE_UP /* remove */,
                IF_STATE_DOWN /* add */);
        setInterfaceConfig(netd, configParcel);
    }

    /**
     * Set interface configuration to netd by passing InterfaceConfigurationParcel.
     */
    public static void setInterfaceConfig(INetd netd, InterfaceConfigurationParcel configParcel) {
        try {
            netd.interfaceSetCfg(configParcel);
        } catch (RemoteException | ServiceSpecificException e) {
            throw new IllegalStateException(e);
        }
    }

三、总结

1、Android13 新增了有线网开关的api

 mEthernetManager.setEthernetEnabled(boolean);

但是没有提供查询开关状态的api !需要自己在开关后记录有线网状态。

2、有线网开关区别

Android9 自动的开关是会关闭有线网节点的,
Android13 自带的有线网开关是不会关闭有线网节点的。

移除有线网节点的做法,会耗时两三秒;
不移除有线网的做法,基本不耗时。

(1)Android9 中要参考 Android13 不移除节点

关闭有线网的时候,执行下面相关代码即可:

    //关闭有线网网络(Android13 复制过来的代码)
    private void untrackFactoryInterfaces() {
        for (String iface : mFactory.getAvailableInterfaces(true /* includeRestricted */)) {
            stopTrackingInterface(iface);
        }
    }

(2)Android13 中要参考 Android9 移除节点

在 removeInterface 方法中调用 NetdUtils.setInterfaceDown 即可。


    private void removeInterface(String iface) {
        mFactory.removeInterface(iface);
        //remove jiedian!by liwenzhi,Start
        NetdUtils.setInterfaceDown(mNetd, iface);
        //remove jiedian!by liwenzhi,End
        maybeUpdateServerModeInterfaceState(iface, false);
    }

在测试中发现,切换信源返回界面后, removeInterface 会移除到其他节点,这个多加个判断,只移除有线网相关节点就可以,比如是否eth0/eth1.

3、有线网出现没ip 问题

这里的移除有线网节点的解决方法,只能算是一种规避手段,要正在解决该文件估计要一整套系统流程分析。
因为是小概率问题,所以先规避解决。

猜你喜欢

转载自blog.csdn.net/wenzhi20102321/article/details/131871354