Android系统开发中发现,Android8以后有线网络开关没有api了,需要自己进行通路建造,或者自己实现开关控制。
这部分修改在Framework 的Java层进行修改即可完成。
总体思路:
1、有线网络开关控制是在EthernetService.java,但是具体实现是在EthernetServiceImpl.java和EthernetTracker.java,EthernetServiceImpl持有EthernetTracker的对象;
2、系统启动会执行EthernetTracker.java里面的start方法,根据Setting值情况判断是否执行trackAvailableInterfaces方法设置默认打开有线网络开关;
3、后续在EthernetTracker.java里面 NMService.setInterfaceUp方法和trackAvailableInterfaces方法,控制有线网络开关的开关;
3、需要新建一条通路从framework暴露的SDK中的EthernetManager.java到内部实现EthernetServiceImpl.java串通;
4、从而实现应用app(一般是系统应用)调用新增的EthernetManager.setEnable(boolean)控制有线网络的开关。
下面从上往下进行通路建造的过程分析。实际开发中是从下往上分析和开发的。
这里从上往下分析是为了方便查看效果。
为啥要定义数据,这个是参考6.0的代码做的,因为系统很多设置的开关都是有相关的Settings数值的;
6.0的代码是有Settings.Global ethernet_on这个属性的,表示有线网络开关状态,数值3表示开启状态;
frameworks/base/core/java/android/provider/Settings.java
public final class Settings {
public static final String ALLOWUSERSETPOWERSOURCE = "allow_user_set_power_source";
public static final String ALLOWUSERSETLOCKSOURCE = "allow_user_set_lock_source";
//定义数据
+ public static final String ETHERNET_ON = "ethernet_on";
MOVED_TO_GLOBAL.add(Settings.Global.WOS);
MOVED_TO_GLOBAL.add(Settings.Global.AUTOSEARCHSOURCE);
MOVED_TO_GLOBAL.add(Settings.Global.ALLOWUSERSETPOWERSOURCE);
MOVED_TO_GLOBAL.add(Settings.Global.ALLOWUSERSETLOCKSOURCE);
//在Global定义数据
+ MOVED_TO_GLOBAL.add(Settings.Global.ETHERNET_ON);
frameworks/base/packages/SettingsProvider/res/values/defaults.xml
true
true
//添加默认值
+ 3
frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
class DatabaseHelper extends SQLiteOpenHelper {
loadBooleanSetting(stmt, Settings.Global.ASSISTED_GPS_ENABLED,
R.bool.assisted_gps_enabled);
//加载默认值
+ loadIntegerSetting(stmt, Settings.Global.ETHERNET_ON, R.integer.def_ethernet_on);
二、Framework SDK添加开关控制方法
frameworks/base/core/java/android/net/EthernetManager.java
public class EthernetManager {
//添加定义数值
+ /**
+ * Ethernet is in the initial state.
+ *
+ * @see #ETHERNET_STATE_CHANGED_ACTION
+ * @see #getState()
+ */
+ public static final int ETHERNET_STATE_INITIAL = 0;
+ /**
+ * Ethernet is in an unknown state.
+ * This state will occur when an error happens while enabling or disabling.
+ *
+ * @see #ETHERNET_STATE_CHANGED_ACTION
+ * @see #getState()
+ */
+ public static final int ETHERNET_STATE_UNKNOWN = 1;
+ /**
+ * Ethernet is disabled.
+ *
+ * @see #ETHERNET_STATE_CHANGED_ACTION
+ * @see #getState()
+ */
+ public static final int ETHERNET_STATE_DISABLED = 2;
+ /**
+ * Ethernet is enabled.
+ *
+ * @see #ETHERNET_STATE_CHANGED_ACTION
+ * @see #getState()
+ */
+ public static final int ETHERNET_STATE_ENABLED = 3;
//添加方法
+ public boolean isEnabled() {
+ try {
+ return mService.getState() == ETHERNET_STATE_ENABLED;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ public void setEnabled(boolean enabled) {
+ try {
+ mService.setState(enabled ? ETHERNET_STATE_ENABLED : ETHERNET_STATE_DISABLED);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
代码中“+”表示增加的行。
接着是在Service对应的aidl文件添加接口
三、添加连接通道
1、添加aidl接口方法
frameworks/base/core/java/android/net/IEthernetManager.aidl
interface IEthernetManager {
String getPppUserName();
String getPppPassword();
String getEthernetInterface();
+ int getState();
+ void setState(int state);
}
2、添加aidl接口方法对应的实现
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetServiceImpl.java
public class EthernetServiceImpl extends IEthernetManager.Stub {
private EthernetTracker mTracker;
+ private int mState = EthernetManager.ETHERNET_STATE_INITIAL;
public void start() {
Log.i(TAG, "Starting Ethernet service");
mHandler = new Handler(handlerThread.getLooper());
mTracker = new EthernetTracker(mContext, mHandler);
//去除之前一开始就执行的操作
- mTracker.start();
- mStarted.set(true);
//修改根据系统属性值来判断是否执行操作
+ mEnabled = getPersistedState();
+ Log.i(TAG, "Ethernet Persisted Enabled " + mEnabled);
+
+ boolean isEnabled = mEnabled == EthernetManager.ETHERNET_STATE_ENABLED;
+ mTracker.start(isEnabled);
+ mStarted.set(isEnabled);
}
//暴露的获取状态,实际是获取Settings.Global值
@Override
+ public synchronized int getState() {
+ return getPersistedState();
+ }
//暴露的设置状态,除了Settings.Global值,还要具体事务的操作
@Override
+ public synchronized void setState(int state) {
+ Log.i(TAG, "setState from mState=" + mState + " to state=" + state);
+ if (mState != state) {
+ mState = state;
+ if (state == EthernetManager.ETHERNET_STATE_DISABLED) {
+ setPersistedState(EthernetManager.ETHERNET_STATE_DISABLED);
+ mStarted.set(false);
//关键设置,关闭有线网络
+ mTracker.setIntefaceState(false);
+ } else {
+ setPersistedState(EthernetManager.ETHERNET_STATE_ENABLED);
//关键设置,开启有线网络
+ mTracker.setIntefaceState(true);
+ mStarted.set(true);
+ }
+ }
+ }
//添加状态获取,实际是获取Settings.Global值
+ private int getPersistedState() {
+ final ContentResolver cr = mContext.getContentResolver();
+ try {
+ return Settings.Global.getInt(cr, Settings.Global.ETHERNET_ON);
+ } catch (Settings.SettingNotFoundException e) {
+ return EthernetManager.ETHERNET_STATE_UNKNOWN;
+ }
+ }
+
//添加状态设置,实际是设置Settings.Global值
+ private void setPersistedState(int state) {
+ final ContentResolver cr = mContext.getContentResolver();
+ Settings.Global.putInt(cr, Settings.Global.ETHERNET_ON, state);
+ }
3、添加具体实现内容
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java
class EthernetTracker {
void start() {
+ start(true);
+ }
+
+ void start(boolean isEnabled) {
mConfigStore.read();
- mHandler.post(this::trackAvailableInterfaces);
+
+ if (isEnabled) mHandler.post(this::trackAvailableInterfaces);
}
+
//实际作用方法,1、NMService.setInterfaceUp设置所有有线网络接口是否可用;2、是否进行接口激活;
+ 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);
+ }
+ }
到这里一个完整的有线网络开关控制已经完成了;
上面只是提供了一个思路,
EthernetNetworkFactory.java可能也有方式可以实现有线网络的控制,里面有needNetworkFor和releaseNetworkFor;
不过这个涉及到ConnectivityManagerService和评分机制,整个流程会复杂很多;
上面有线开关控制还是有些地方可以优化的:
1、比如不写完整的调用通路,可以定义数值后,
在EthernetServiceImpl.java里面监听Settings.Global.ETHERNET_ON的数值变化,
如果数值变化随即对有线网络的开关状态进行设置;
下面是上面涉及到的类的修改,不过是根据Android11的源码修改的,涉及到的几个类和Android9.0没有太多变化。
因为Android9和11都进行过了修改,Android11是最近的修改。
搜索“by liwenzhi”即可找到里面相关的修改记录位置。
这里提供一下修改记录的所有文件:
https://download.csdn.net/download/wenzhi20102321/72383905
这是TV架构的Android11系统,可能跟手机有点不同,但是基本思路是一样的。