安卓14移植以太网framework-connectivity-t 编译问题
目录
- 前言
- 一、Android14 以太网变更
- 1.1 限制设置有线网参数设置接口方法
- 1.2 新增有线网开启关闭接口方法
- 1.3 新增了 updateConfiguration 接口方法
- 1.4 有线网设置的静态ip和代理信息重启后无效
- 1.5 EthernetManager相关代码位置移动
- 1.5.1 你的模块需要引入 libs: ["framework-connectivity.impl"]
- 1.5.2 显式添加可见性
- 二、移植适配思路
前言
一、Android14 以太网变更
之前只负责过安卓12平台及以下的以太网功能移植(移植到Settings),Android12 到Android 14 网络部分无论是代码存放目录和代码逻辑都是有较多修改的,主要包括以下几个部分。(后续发现部分Android12平台 相对于其他低版本和Android 14也很相似)
1.1 限制设置有线网参数设置接口方法
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 新增有线网开启关闭接口方法
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 接口方法
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 增加了限制!
//packages\modules\Connectivity\service-t\src\com\android\server\ethernet\EthernetServiceImpl.java@Overridepublic 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和代理信息重启后无效
//查看有线网配置信息保存的类:
packages\modules\Connectivity\service-t\src\com\android\server\ethernet\EthernetConfigStore.javaprivate 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@VisibleForTestingvoid 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/ethernetfinal 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下面对应的模块添加你需要引入的模块位置,显式添加可见性。
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",],
}
否则会编译报错
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方法:
IpConfiguration.Builder build = new IpConfiguration.Builder();EthernetNetworkUpdateRequest.Builder requestBuilder = new EthernetNetworkUpdateRequest.Builder();build.setHttpProxy(proxyinfo);//如果是静态ip,需要创建对应的静态staticIpConfigurationbuild.setStaticIpConfiguration(staticIpConfiguration);requestBuilder.setIpConfiguration(build.build());mEthManager.updateConfiguration("eth0", requestBuilder.build(), null, null);
旧版本的很多接口在新版本是没有的,但是都能被新的接口适配替代!
