Android9 有线网络开关设置

  • 一、定义数据
  • 1、Setting中定义数据
  • 2、定义默认值
  • 3、添加默认定义值



Android9 、11有线网络开关设置

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表示开启状态;

1、Setting中定义数据

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);

2、定义默认值

frameworks/base/packages/SettingsProvider/res/values/defaults.xml

<string name="allow_user_set_power_source" translatable="false">true</string>
     <string name="allow_user_set_lock_source" translatable="false">true</string>
//添加默认值
+    <integer name="def_ethernet_on">3</integer>

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”即可找到里面相关的修改记录位置。

这里提供一下修改记录的所有文件:

这是TV架构的Android11系统,可能跟手机有点不同,但是基本思路是一样的。