Android 13 有线以太网静态ip保存逻辑梳理分析

源码环境:高通Android 13

这里特别说明,Android13中,ipconfig.txt配置文件目录有改变

以前:/data/misc/ethernet/ipconfig.txt

最新的有线网配置文件保存目录:

/data/misc/apexdata/com.android.tethering/misc/ethernet/ipconfig.txt

一、Android 版本影响

首先就是Android 11 与 12 的有线网络版本差距还是比较大的,源码目录也变了,之前目录frameworks/opt/net/ethernet/java/com/android/server/ethernet ,现在改成了packages/modules/Connectivity/service-t/src/com/android/server/ethernet,所以如果之前只在11上面适配过,那么对于12来说,适配还是需要花费一点功夫,具体的差异在之后的部分会记录,但是12与13的有线网络差异就较小了,并且看起来,13的以太网接口以及逻辑比12来说更为完善。

二、配置以太网所需要的类

配置以太网所需要的java类大概有以下几个,其实这几个类从Android9开始就是以太网配置的主要java类了

(1)、frameworks/base/core/java/android/net/EthernetManager.java

EthernetManager.java此是上层管理以太网的类,我们常通过context.getSystemService(Context.ETHERNET_SERVICE)获得他的实例对象

(2)、packages/modules/Connectivity/framework/src/android/net/IpConfiguration.java

这个类主要就是用来配置IP状态的,包括动态和静态

(3)、packages/modules/Connectivity/framework/src/android/net/StaticIpConfiguration.java

这个类主要就是用来配置静态IP的,这个类之前也是在frameworks/base/core/java/android/net/路径下,12里面也移到了packages/modules/Connectivity/framework/src/android/net/下

三、有线以太网静态ip保存逻辑从源码逐步分析

java 复制代码
1、packages/modules/Connectivity/framework-t/src/android/net/EthernetManager.java 
 public void setConfiguration(@NonNull String iface, @NonNull IpConfiguration config) {
        try {
            mService.setConfiguration(iface, config);//这里调用的是EthernetServiceImpl.java中的setConfiguration
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }



2、packages/modules/Connectivity/service-t/src/com/android/server/ethernet/EthernetServiceImpl.java
  /**
     * Set Ethernet configuration
     */
    @Override
    public void setConfiguration(String iface, IpConfiguration config) {
        throwIfEthernetNotStarted();

        PermissionUtils.enforceNetworkStackPermission(mContext);
        if (mTracker.isRestrictedInterface(iface)) {
            PermissionUtils.enforceRestrictedNetworkPermission(mContext, TAG);
        }

        // TODO: this does not check proxy settings, gateways, etc.
        // Fix this by making IpConfiguration a complete representation of static configuration.
        mTracker.updateIpConfiguration(iface, new IpConfiguration(config));//这里更新保存
    }


3、packages/modules/Connectivity/service-t/src/com/android/server/ethernet/EthernetTracker.java
EthernetTracker中主要做了以下两件事 :
(1). 首先更新 ip config的,这个和静态ip相关;
(2). 根据iface,调用addInterface创建interface

   void updateIpConfiguration(String iface, IpConfiguration ipConfiguration) {
        if (DBG) {
            Log.i(TAG, "updateIpConfiguration, iface: " + iface + ", cfg: " + ipConfiguration);
        }
        writeIpConfiguration(iface, ipConfiguration);
        mHandler.post(() -> {
            mFactory.updateInterface(iface, ipConfiguration, null, null);
            broadcastInterfaceStateChange(iface);
        });
    }


   private void writeIpConfiguration(@NonNull final String iface,
            @NonNull final IpConfiguration ipConfig) {
        mConfigStore.write(iface, ipConfig);//这里调用了EthernetConfigStore.java中的write
        mIpConfigurations.put(iface, ipConfig);
    }


4、packages/modules/Connectivity/service-t/src/com/android/server/ethernet/EthernetConfigStore.java
  private static final String CONFIG_FILE = "ipconfig.txt";
  private static final String FILE_PATH = "/misc/ethernet/";
  private static final String APEX_IP_CONFIG_FILE_PATH = ApexEnvironment.getApexEnvironment(
            TETHERING_MODULE_NAME).getDeviceProtectedDataDir() + FILE_PATH;


 public void write(String iface, IpConfiguration config) {
        write(iface, config, APEX_IP_CONFIG_FILE_PATH + CONFIG_FILE);//注意:这里Android13调整了保存路径,全路径:/data/misc/apexdata/com.android.tethering/misc/ethernet/ipconfig.txt
        //Android 10版本保存路径为:/data/misc/ethernet/ipconfig.txt
    }



 void write(String iface, IpConfiguration config, String filepath) {
        boolean modified;

        synchronized (mSync) {
            if (config == null) {
                modified = mIpConfigurations.remove(iface) != null;
            } else {
                IpConfiguration oldConfig = mIpConfigurations.put(iface, config);
                modified = !config.equals(oldConfig);
            }

            if (modified) {
                mStore.writeIpConfigurations(filepath, mIpConfigurations);//这里调用的是IpConfigStore.java
            }
        }
    }



5、packages/modules/Connectivity/service-t/src/com/android/server/net/IpConfigStore.java
 /**
     *  Write the IP configuration associated to the target networks to the destination path.
     */
    public void writeIpConfigurations(String filePath,
                                      ArrayMap<String, IpConfiguration> networks) {
        mWriter.write(filePath, out -> {
            out.writeInt(IPCONFIG_FILE_VERSION);
            for (int i = 0; i < networks.size(); i++) {
                writeConfig(out, networks.keyAt(i), networks.valueAt(i));
            }
        });
    }



  private static boolean writeConfig(DataOutputStream out, String configKey,
            IpConfiguration config) throws IOException {
        return writeConfig(out, configKey, config, IPCONFIG_FILE_VERSION);
    }



//这里最终完成静态ip写到配置文件:/data/misc/apexdata/com.android.tethering/misc/ethernet/ipconfig.txt
  public static boolean writeConfig(DataOutputStream out, String configKey,
                                IpConfiguration config, int version) throws IOException {
        boolean written = false;

        try {
            switch (config.getIpAssignment()) {
                case STATIC:
                    out.writeUTF(IP_ASSIGNMENT_KEY);
                    out.writeUTF(config.getIpAssignment().toString());
                    StaticIpConfiguration staticIpConfiguration = config.getStaticIpConfiguration();
                    if (staticIpConfiguration != null) {
                        if (staticIpConfiguration.getIpAddress() != null) {
                            LinkAddress ipAddress = staticIpConfiguration.getIpAddress();
                            out.writeUTF(LINK_ADDRESS_KEY);
                            out.writeUTF(ipAddress.getAddress().getHostAddress());
                            out.writeInt(ipAddress.getPrefixLength());
                        }
                        if (staticIpConfiguration.getGateway() != null) {
                            out.writeUTF(GATEWAY_KEY);
                            out.writeInt(0);  // Default route.
                            out.writeInt(1);  // Have a gateway.
                            out.writeUTF(staticIpConfiguration.getGateway().getHostAddress());
                        }
                        for (InetAddress inetAddr : staticIpConfiguration.getDnsServers()) {
                            out.writeUTF(DNS_KEY);
                            out.writeUTF(inetAddr.getHostAddress());
                        }
                    }
                    written = true;
                    break;
                case DHCP:
                    out.writeUTF(IP_ASSIGNMENT_KEY);
                    out.writeUTF(config.getIpAssignment().toString());
                    written = true;
                    break;
                case UNASSIGNED:
                /* Ignore */
                    break;
                default:
                    loge("Ignore invalid ip assignment while writing");
                    break;
            }

            switch (config.getProxySettings()) {
                case STATIC:
                    ProxyInfo proxyProperties = config.getHttpProxy();
                    String exclusionList = ProxyUtils.exclusionListAsString(
                            proxyProperties.getExclusionList());
                    out.writeUTF(PROXY_SETTINGS_KEY);
                    out.writeUTF(config.getProxySettings().toString());
                    out.writeUTF(PROXY_HOST_KEY);
                    out.writeUTF(proxyProperties.getHost());
                    out.writeUTF(PROXY_PORT_KEY);
                    out.writeInt(proxyProperties.getPort());
                    if (exclusionList != null) {
                        out.writeUTF(EXCLUSION_LIST_KEY);
                        out.writeUTF(exclusionList);
                    }
                    written = true;
                    break;
                case PAC:
                    ProxyInfo proxyPacProperties = config.getHttpProxy();
                    out.writeUTF(PROXY_SETTINGS_KEY);
                    out.writeUTF(config.getProxySettings().toString());
                    out.writeUTF(PROXY_PAC_FILE);
                    out.writeUTF(proxyPacProperties.getPacFileUrl().toString());
                    written = true;
                    break;
                case NONE:
                    out.writeUTF(PROXY_SETTINGS_KEY);
                    out.writeUTF(config.getProxySettings().toString());
                    written = true;
                    break;
                case UNASSIGNED:
                    /* Ignore */
                    break;
                default:
                    loge("Ignore invalid proxy settings while writing");
                    break;
            }

            if (written) {
                out.writeUTF(ID_KEY);
                if (version < 3) {
                    out.writeInt(Integer.valueOf(configKey));
                } else {
                    out.writeUTF(configKey);
                }
            }
        } catch (NullPointerException e) {
            loge("Failure in writing " + config + e);
        }
        out.writeUTF(EOS);

        return written;
    }
相关推荐
潜龙952710 小时前
第3.2.3节 Android动态调用链路的获取
android·调用链路
追随远方11 小时前
Android平台FFmpeg音视频开发深度指南
android·ffmpeg·音视频
撰卢12 小时前
MySQL 1366 - Incorrect string value:错误
android·数据库·mysql
恋猫de小郭12 小时前
Flutter 合并 ‘dot-shorthands‘ 语法糖,Dart 开始支持交叉编译
android·flutter·ios
牛马程序小猿猴12 小时前
15.thinkphp的上传功能
android
林家凌宇13 小时前
Flutter 3.29.3 花屏问题记录
android·flutter·skia
时丶光13 小时前
Android 查看 Logcat (可纯手机方式 无需电脑)
android·logcat
血手人屠喵帕斯13 小时前
事务连接池
android·adb
恋猫de小郭14 小时前
React Native 前瞻式重大更新 Skia & WebGPU & ThreeJS,未来可期
android·javascript·flutter·react native·react.js·ios
一人一萧十只猫�15 小时前
MySQL 从入门到精通(三):日志管理详解 —— 从排错到恢复的核心利器
android·mysql·adb