安卓14移植以太网&&framework-connectivity-t 编译问题

目录

  • 前言
  • [一、Android14 以太网变更](#一、Android14 以太网变更)
    • [1.1 限制设置有线网参数设置接口方法](#1.1 限制设置有线网参数设置接口方法)
    • [1.2 新增有线网开启关闭接口方法](#1.2 新增有线网开启关闭接口方法)
    • [1.3 新增了 updateConfiguration 接口方法](#1.3 新增了 updateConfiguration 接口方法)
    • [1.4 有线网设置的静态ip和代理信息重启后无效](#1.4 有线网设置的静态ip和代理信息重启后无效)
    • [1.5 EthernetManager相关代码位置移动](#1.5 EthernetManager相关代码位置移动)
      • [1.5.1 你的模块需要引入 libs: ["framework-connectivity.impl"]](#1.5.1 你的模块需要引入 libs: ["framework-connectivity.impl"])
      • [1.5.2 显式添加可见性](#1.5.2 显式添加可见性)
  • 二、移植适配思路

前言

一、Android14 以太网变更

之前只负责过安卓12平台及以下的以太网功能移植(移植到Settings),Android12 到Android 14 网络部分无论是代码存放目录和代码逻辑都是有较多修改的,主要包括以下几个部分。(后续发现部分Android12平台 相对于其他低版本和Android 14也很相似)

1.1 限制设置有线网参数设置接口方法

c 复制代码
packages/modules/Connectivity/framework-t/src/android/net/EthernetManager.java

/**
     * Get Ethernet configuration.
     * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public IpConfiguration getConfiguration(String iface) {
        try {
            return mService.getConfiguration(iface);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Set Ethernet configuration.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public void setConfiguration(@NonNull String iface, @NonNull IpConfiguration config) {
        try {
            mService.setConfiguration(iface, config);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

主要是api加了限制 :maxTargetSdk = Build.VERSION_CODES.R //Android11

所以Android 12 或者更新的版本,在EthernetManager 是调用不到上面几个接口方法的,编译会直接报错:找不到对应的方法!

1.2 新增有线网开启关闭接口方法

c 复制代码
packages\modules\Connectivity\framework-t\src\android\net\EthernetManager.java

    /**
     * Change ethernet setting.
     *
     * @param enabled enable or disable ethernet settings.
     *
     * @hide
     */
    @RequiresPermission(anyOf = {
            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
            android.Manifest.permission.NETWORK_STACK,
            android.Manifest.permission.NETWORK_SETTINGS})
    @SystemApi(client = MODULE_LIBRARIES)
    public void setEthernetEnabled(boolean enabled) {
        try {
            mService.setEthernetEnabled(enabled);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

新增的接口方法 setEthernetEnabled ,之前是要自己实现有线网开关的。需要的权限上面已经说明的,基本是要系统签名的应用才能调用。

1.3 新增了 updateConfiguration 接口方法

c 复制代码
packages\modules\Connectivity\framework-t\src\android\net\EthernetManager.java
    @SystemApi
    @RequiresPermission(anyOf = {
            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
            android.Manifest.permission.NETWORK_STACK,
            android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
    public void updateConfiguration(
            @NonNull String iface,
            @NonNull EthernetNetworkUpdateRequest request,
            @Nullable @CallbackExecutor Executor executor,
            @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
        Objects.requireNonNull(iface, "iface must be non-null");
        Objects.requireNonNull(request, "request must be non-null");
        final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
                executor, callback);
        try {
            mService.updateConfiguration(iface, request, proxy);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

String iface 节点名称:eth0 / eth1

EthernetNetworkUpdateRequest request 对象是包含静态ip和代理信息对象和特征属性对象。

后面两个是回调监听,未要求非空,是可以传null 的。

在有线网服务,新api 增加了限制!

c 复制代码
//packages\modules\Connectivity\service-t\src\com\android\server\ethernet\EthernetServiceImpl.java

    @Override
    public void updateConfiguration(@NonNull final String iface,
            @NonNull final EthernetNetworkUpdateRequest request,
            @Nullable final INetworkInterfaceOutcomeReceiver listener) {
        Objects.requireNonNull(iface);
        Objects.requireNonNull(request);
        throwIfEthernetNotStarted();


        // TODO: validate that iface is listed in overlay config_ethernet_interfaces
        // only automotive devices are allowed to set the NetworkCapabilities using this API
        //only automotive devices 表明,只有 车载设备支持设置该方法
+        // 非车载项目必须注释调方法:enforceAdminPermission ,否则会报错,这里是校验是否是车载项目
+        //enforceAdminPermission(iface, request.getNetworkCapabilities() != null,
+         //       "updateConfiguration() with non-null capabilities");
+        Log.i(TAG, "  updateConfiguration with: iface=" + iface + ", listener=" + listener);
        maybeValidateTestCapabilities(iface, request.getNetworkCapabilities());

        mTracker.updateConfiguration(
                iface, request.getIpConfiguration(), request.getNetworkCapabilities(), listener);
    }

在自己项目中调用此api ,必须设置属性让自己的设备识别为车载项目

或者把车载判断的逻辑去除即可

1.4 有线网设置的静态ip和代理信息重启后无效

c 复制代码
//查看有线网配置信息保存的类:
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 LEGACY_IP_CONFIG_FILE_PATH = Environment.getDataDirectory() + FILE_PATH;
    //Android13 新增下面路径:
    private static final String APEX_IP_CONFIG_FILE_PATH = ApexEnvironment.getApexEnvironment(
            TETHERING_MODULE_NAME).getDeviceProtectedDataDir() + FILE_PATH; // TETHERING_MODULE_NAME --》com.android.tethering

/**
可以看到之前的路径是:
/data/misc/ethernet/ipconfig.txt
最新的有线网配置文件保存目录:
/data/misc/apexdata/com.android.tethering/misc/ethernet/ipconfig.txt
可能存在因为未成功保存本地配置文件,所以每次开机重启后,无法读取到静态ip和代理等信息。
所以出现 有线网设置的静态ip和代理信息重启后无效 问题。主要原因为开机读取的时候,目录未成功创建,故保存未成功。
可以参考如下:
*/

//packages\modules\Connectivity/service-t/src/com/android/server/ethernet/EthernetConfigStore.java

    @VisibleForTesting
    void read(final String newFilePath, final String oldFilePath, final String filename) {
        try {
            synchronized (mSync) {
                // Attempt to read the IP configuration from apex file path first.
                if (doesConfigFileExist(newFilePath + filename)) {
                    loadConfigFileLocked(newFilePath + filename);
                    return;
                }
                //ik-phoebe add for create dir data/misc/apexdata/com.android.tethering/misc/ethernet
                final File directory = new File(newFilePath);
                if (!directory.exists()) {
                    boolean mkdirs = directory.mkdirs();
                }
                // If the config file doesn't exist in the apex file path, attempt to read it from
                // the legacy file path, if config file exists, write the legacy IP configuration to
                // apex config file path, this should just happen on the first boot. New or updated
                // config entries are only written to the apex config file later.
                if (!doesConfigFileExist(oldFilePath + filename)) return;
                loadConfigFileLocked(oldFilePath + filename);
                writeLegacyIpConfigToApexPath(newFilePath, oldFilePath, filename);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, " for read exception:" + e.getMessage());
        }
    }

1.5 EthernetManager相关代码位置移动

从framework移到packages/modules/Connectivity/

(之前目录:frameworks\base\core\java\android\net\EthernetManager.java)

后面开发Android12 或新版本代码,会发现wifi 、蓝牙、热点 之前 framework 的源码都移动到了下面的package目录:

如果你在其他的framework包里调用Connectivity这个 模块里面的内容,大概率是会编译报错的!

你需要添加两处修改:

1.5.1 你的模块需要引入 libs: ["framework-connectivity.impl"]

framework-connectivity 只提供公共的 stub
libs: ["framework-connectivity.impl"]。将完整的实现(包括像 IConnectivityManager 这样的内部/隐藏类)包含在编译时的类路径中。

1.5.2 显式添加可见性

framework-connectivity-t 这个包不是你想用就能用的,需要在 Connectivity下面对应的模块添加你需要引入的模块位置,显式添加可见性

c 复制代码
java_sdk_library {
    name: "framework-connectivity-t",
    defaults: [
        "framework-connectivity-t-defaults",
        "enable-framework-connectivity-t-targets",
    ],
    // Do not add static_libs to this library: put them in framework-connectivity instead.
    // The jarjar rules are only so that references to jarjared utils in
    // framework-connectivity-pre-jarjar match at runtime.
    jarjar_rules: ":framework-connectivity-jarjar-rules",
    stub_only_libs: [
        // Use prebuilt framework-connectivity stubs to avoid circular dependencies
        "sdk_module-lib_current_framework-connectivity",
    ],
    libs: [
        "sdk_module-lib_current_framework-connectivity",
    ],
    permitted_packages: [
        "android.app.usage",
        "android.net",
        "android.net.nsd",
        "android.nearby",
        "com.android.connectivity",
        "com.android.nearby",
    ],

    hidden_api: {
        max_target_o_low_priority: [
            "hiddenapi/hiddenapi-max-target-o-low-priority-tiramisu.txt",
        ],
        max_target_r_low_priority: [
            "hiddenapi/hiddenapi-max-target-r-loprio.txt",
        ],
        unsupported: [
            "hiddenapi/hiddenapi-unsupported-tiramisu.txt",
        ],
    },

    impl_library_visibility: [
+        "//你需要引入的模块位置"
        "//packages/modules/Connectivity/Tethering/apex",
        // In preparation for future move
        "//packages/modules/Connectivity/apex",
        "//packages/modules/Connectivity/service", // For R8 only
        "//packages/modules/Connectivity/service-t",
        "//packages/modules/Connectivity/nearby:__subpackages__",
        "//frameworks/base",

        // Tests using hidden APIs
        "//cts/tests/netlegacy22.api",
        "//cts/tests/tests/app.usage", // NetworkUsageStatsTest
        "//external/sl4a:__subpackages__",
        "//frameworks/base/core/tests/bandwidthtests",
        "//frameworks/base/core/tests/benchmarks",
        "//frameworks/base/core/tests/utillib",
        "//frameworks/base/tests/vcn",
        "//frameworks/libs/net/common/testutils",
        "//frameworks/libs/net/common/tests:__subpackages__",
        "//frameworks/opt/net/ethernet/tests:__subpackages__",
        "//frameworks/opt/telephony/tests/telephonytests",
        "//packages/modules/CaptivePortalLogin/tests",
        "//packages/modules/Connectivity/Tethering/tests:__subpackages__",
        "//packages/modules/Connectivity/tests:__subpackages__",
        "//packages/modules/IPsec/tests/iketests",
        "//packages/modules/NetworkStack/tests:__subpackages__",
        "//packages/modules/Wifi/service/tests/wifitests",
    ],
}

否则会编译报错

c 复制代码
error: frameworks/base/packages/我的模块位置/Android.bp:11:1: module "我的模块" variant "android_common": depends on //packages/modules/Connectivity/framework:framework-connectivity.impl which is not visible to this module
You may need to add "//frameworks/base/packages/我的模块位置" to its visibility
13:54:17 soong bootstrap failed with: exit status 1

二、移植适配思路

主要是从以下两个方面:

(1)使用新api接口设置静态ip和代理信息

(2)移除源码中限制接口的版本号 目前我采用的是一,因为项目需要过gms认证,只能使用一,因为gms合入mainline,packages\modules\Connectivity生成的jar会被覆盖。

使用系统提供的更新ip方法:

c 复制代码
   IpConfiguration.Builder build = new IpConfiguration.Builder();
   EthernetNetworkUpdateRequest.Builder requestBuilder = new EthernetNetworkUpdateRequest.Builder();
   build.setHttpProxy(proxyinfo);
   //如果是静态ip,需要创建对应的静态staticIpConfiguration
   build.setStaticIpConfiguration(staticIpConfiguration);
   requestBuilder.setIpConfiguration(build.build());
   mEthManager.updateConfiguration("eth0", requestBuilder.build(), null, null);

旧版本的很多接口在新版本是没有的,但是都能被新的接口适配替代!

相关推荐
selt79114 小时前
Redisson之RedissonLock源码完全解析
android·java·javascript
Yao_YongChao15 小时前
Android MVI处理副作用(Side Effect)
android·mvi·mvi副作用
非凡ghost16 小时前
JRiver Media Center(媒体管理软件)
android·学习·智能手机·媒体·软件需求
席卷全城16 小时前
Android 推箱子实现(引流文章)
android
齊家治國平天下16 小时前
Android 14 系统中 Tombstone 深度分析与解决指南
android·crash·系统服务·tombstone·android 14
maycho12318 小时前
MATLAB环境下基于双向长短时记忆网络的时间序列预测探索
android
思成不止于此18 小时前
【MySQL 零基础入门】MySQL 函数精讲(二):日期函数与流程控制函数篇
android·数据库·笔记·sql·学习·mysql
brave_zhao19 小时前
达梦数据库(DM8)支持全文索引功能,但并不直接兼容 MySQL 的 FULLTEXT 索引语法
android·adb
sheji341619 小时前
【开题答辩全过程】以 基于Android的网上订餐系统为例,包含答辩的问题和答案
android
easyboot19 小时前
C#使用SqlSugar操作mysql数据库
android·sqlsugar