Android13 有线网开关研究
Android13 有线网开关研究
文章目录
本文对比 Android9 自己开发的有线网开关代码。
前言
1、api
Android13 的api 提供了有线网开关 EthernetManager.setEthernetEnabled(boolean),
Android9 如果要设置有线网开关,需要自己实现。
2、问题
Android13 上有出现打开有线网并且接入有线网无ip的情况,
并且调用开关有线网开关无作用(未移除节点eth0),ifconfig etho down/up 操作一次就有ip了。
3、目的
Android9 上有线网开关接口是会关闭节点的;Android13 上开关有线网节点一直是存在的。
所有决定研究一下有线网开关,希望能过解决问题。
主要研究代码是: EthernetTracker.java 的相关处理
之前Android 9 增加的有线网开关文章:
https://blog.csdn.net/wenzhi20102321/article/details/122243396
二、代码分析
1、Android13 上的 EthernetTracker
E:\982\code\android_source\packages\modules\Connectivity\service-t\src\com\android\server\ethernet\EthernetTracker.java
private final INetd mNetd;
@VisibleForTesting(visibility = PACKAGE)
protected void setEthernetEnabled(boolean enabled) {
mHandler.post(() -> {
int newState = enabled ? ETHERNET_STATE_ENABLED : ETHERNET_STATE_DISABLED;
//set state,by liwenzhi ,Start
Log.i(TAG, "setEthernetEnabled newState = " +newState + ", old state = " + mEthernetState);
setPersistedState(newState); //自己加的值,用于保存系统属性,不用关注
//set state,by liwenzhi ,End
if (mEthernetState == newState) return;
mEthernetState = newState;
//关键
if (enabled) {
trackAvailableInterfaces();//设置有线网可用
} else {
// TODO: maybe also disable server mode interface as well.
untrackFactoryInterfaces();//设置有线网不可用
}
broadcastEthernetStateChange(mEthernetState);
});
}
//开启网络
private void trackAvailableInterfaces() {
try {
final String[] ifaces = mNetd.interfaceGetList();
for (String iface : ifaces) {
maybeTrackInterface(iface);
}
} catch (RemoteException | ServiceSpecificException e) {
Log.e(TAG, "Could not get list of interfaces " + e);
}
}
//添加有线网节点,一般是 eth0
private void maybeTrackInterface(String iface) {
。。。
addInterface(iface);
broadcastInterfaceStateChange(iface);
}
//添加配置有线网节点
private void addInterface(String iface) {
InterfaceConfigurationParcel config = null;
// Bring up the interface so we get link status indications.
try {
PermissionUtils.enforceNetworkStackPermission(mContext);
NetdUtils.setInterfaceUp(mNetd, iface); // NetdUtils 是Android13 新增的工具类
config = NetdUtils.getInterfaceConfigParcel(mNetd, iface);
} catch (IllegalStateException e) {
// Either the system is crashing or the interface has disappeared. Just ignore the
// error; we haven't modified any state because we only do that if our calls succeed.
Log.e(TAG, "Error upping interface " + iface, e);
}
}
//关闭有线网网络
private void untrackFactoryInterfaces() {
for (String iface : mFactory.getAvailableInterfaces(true /* includeRestricted */)) {
stopTrackingInterface(iface);
}
}
//停止有线网节点,一般是eth0
private void stopTrackingInterface(String iface) {
removeInterface(iface);
if (iface.equals(mDefaultInterface)) {
mDefaultInterface = null;
}
broadcastInterfaceStateChange(iface); //发送广播通知该节点网络断开
}
//删除有线网节点的数据,应该是断开某个netId
private void removeInterface(String iface) {
mFactory.removeInterface(iface);
maybeUpdateServerModeInterfaceState(iface, false);
}
关注一下上面的 removeInterface 方法,这里是没移除节点的;
从串口看,ifconfig,不管关开有线网,都是会有eth0 节点的,只是调用关闭的情况是没有ip 的。
2、Android13 上的 EthernetTracker
E:\project_android11\code\android\frameworks\opt\net\ethernet\java\com\android\server\ethernet\EthernetTracker.java
private final INetworkManagementService mNMService;
//对比Android11 上开关有线网的最后实现,是通过mNMService 进行开关节点
+ public synchronized void setIntefaceState(boolean state) {
+ try {
+ String[] interfaces = getInterfaces(true);
+ for (String iface : interfaces) {
+ if (isTrackingInterface(iface)) {
+ if (state) {
+ mNMService.setInterfaceUp(iface);
+ } else {
+ mNMService.setInterfaceDown(iface);
+ }
+ }
+ }
+ if (state) mHandler.post(this::trackAvailableInterfaces);
+ } catch (Exception e) {
+ Log.e(TAG, "Error change eth state : " + state);
+ }
+ }
Android 原生没有上面的"+"的代码的,是自己加上去的;
这里的 mNMService.setInterfaceDown(iface) 关闭节点是会移除节点的。
3、对比开关过程
1、Android13 关闭有线网,未移除节点:
EthernetNetworkFactory mFactory;
mFactory.removeInterface(iface);
其实 Android9 的 EthernetTracker也是有 EthernetNetworkFactory 对象,只是没有调到 removeInterface;
Android11 原生代码上,有线网默认是开启的,没有关闭有线网的接口。
其实Android9 也可以参考Android13 只移除某个网络,不移除有线网节点。
2、Android9 关闭有线网,移除节点:
INetworkManagementService mNMService;
mNMService.setInterfaceDown(iface);
虽然Android13 EthernetNetworkFactory.java 没有 INetworkManagementService 对象,但是有类似意义的 INetd 对象。
Android13 上的 NetdUtils 包含了同样意义的 setInterfaceDown 方法。
3、NetdUtils
这个类是Android13 新增的工具类
framework\libs\net\client-libs\netd\com\android\net\module\util\NetdUtils.java
/**
* Set the given interface down.
*/
public static void setInterfaceDown(INetd netd, String iface) {
final InterfaceConfigurationParcel configParcel = getInterfaceConfigParcel(netd, iface);
configParcel.flags = removeAndAddFlags(configParcel.flags, IF_STATE_UP /* remove */,
IF_STATE_DOWN /* add */);
setInterfaceConfig(netd, configParcel);
}
/**
* Set interface configuration to netd by passing InterfaceConfigurationParcel.
*/
public static void setInterfaceConfig(INetd netd, InterfaceConfigurationParcel configParcel) {
try {
netd.interfaceSetCfg(configParcel);
} catch (RemoteException | ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}
三、总结
1、Android13 新增了有线网开关的api
mEthernetManager.setEthernetEnabled(boolean);
但是没有提供查询开关状态的api !需要自己在开关后记录有线网状态。
2、有线网开关区别
Android9 自动的开关是会关闭有线网节点的,
Android13 自带的有线网开关是不会关闭有线网节点的。
移除有线网节点的做法,会耗时两三秒;
不移除有线网的做法,基本不耗时。
(1)Android9 中要参考 Android13 不移除节点
关闭有线网的时候,执行下面相关代码即可:
//关闭有线网网络(Android13 复制过来的代码)
private void untrackFactoryInterfaces() {
for (String iface : mFactory.getAvailableInterfaces(true /* includeRestricted */)) {
stopTrackingInterface(iface);
}
}
(2)Android13 中要参考 Android9 移除节点
在 removeInterface 方法中调用 NetdUtils.setInterfaceDown 即可。
private void removeInterface(String iface) {
mFactory.removeInterface(iface);
//remove jiedian!by liwenzhi,Start
NetdUtils.setInterfaceDown(mNetd, iface);
//remove jiedian!by liwenzhi,End
maybeUpdateServerModeInterfaceState(iface, false);
}
在测试中发现,切换信源返回界面后, removeInterface 会移除到其他节点,这个多加个判断,只移除有线网相关节点就可以,比如是否eth0/eth1.
3、有线网出现没ip 问题
这里的移除有线网节点的解决方法,只能算是一种规避手段,要正在解决该文件估计要一整套系统流程分析。
因为是小概率问题,所以先规避解决。