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;
    }
相关推荐
拭心5 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王7 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡8 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道8 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库9 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道10 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe10 小时前
Android Hook - 动态加载so库
android
居居飒10 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He13 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗14 小时前
Android笔试面试题AI答之Android基础(1)
android