Android9, 11 wired network switch setting


Android9, 11 wired network switch settings

During the development of the Android system, it was found that after Android 8, the wired network switch has no api, and it is necessary to build the path by itself, or realize the switch control by itself.

This part of the modification can be completed in the Java layer of the Framework.

general idea:


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)控制有线网络的开关。

The following is an analysis of the process of channel construction from top to bottom. The actual development is analyzed and developed from bottom to top.

The analysis from top to bottom here is for the convenience of viewing the effect.

1. Define data

Why define the data, this is done with reference to the 6.0 code, because many switches in the system have related Settings values;

The 6.0 code has the attribute Settings.Global ethernet_on, which indicates the status of the wired network switch, and the value 3 indicates the on status;

1. Define data in 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. Define the default value

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. Add default definition value

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


2. Framework SDK adds switch control method

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();
+        }
+    }


"+" in the code indicates an additional line.

Then add the interface in the aidl file corresponding to the Service

3. Add connection channel

1. Add aidl interface method

frameworks/base/core/java/android/net/IEthernetManager.aidl


interface IEthernetManager {
     String getPppUserName();
     String getPppPassword();
     String getEthernetInterface();
    
+    int getState();
+    void setState(int state);

}

2. Add the implementation corresponding to the aidl interface method

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. Add specific implementation content

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

At this point, a complete wired network switch control has been completed;

The above just provides an idea,
EthernetNetworkFactory.java may also have a way to realize the control of wired network, which includes needNetworkFor and releaseNetworkFor;
but this involves ConnectivityManagerService and scoring mechanism, the whole process will be much more complicated;

There are still some areas that can be optimized for the above wired switch control:

1. For example, if you don’t write a complete call path, you can
monitor the value change of Settings.Global.ETHERNET_ON in EthernetServiceImpl.java after defining the value.
If the value changes, then set the switch status of the wired network;

The following is the modification of the classes involved above, but it is modified according to the source code of Android 11. The classes involved have not changed much from Android 9.0.

Because both Android9 and 11 have been modified, and Android11 ​​is the most recent modification.

Search for "by liwenzhi" to find the relevant modification record location.

Here are all the files for the modification record:

https://download.csdn.net/download/wenzhi20102321/72383905

This is the Android 11 system of the TV architecture. It may be a little different from the mobile phone, but the basic idea is the same.

Guess you like

Origin blog.csdn.net/wenzhi20102321/article/details/122243396
Recommended