目录
- 前言
- [一、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);
旧版本的很多接口在新版本是没有的,但是都能被新的接口适配替代!