Android14 以太网共享功能 相关代码简介

Android14 以太网共享功能 相关代码简介

文章目录

一、前言

Android 的以太网共享功能是啥?

其实就是 Android设备接入一个网线后,再接入电脑,电脑就可以分配到到一个ip;

这里的Android 设备就相当于一个路由器。

如果Android设备可以正常上网,那么电脑也是可以上网的;

Android 的以太网共享功能简单的说就是把Android设备的网络通过网线的形式共享给其他设备。

Android手机设备基本没有网口,可以通过usb Hab转接网口;

一些调试用的Android 设备是保存有网口的,可以直接接入网线。

Android以太网共享功能并不是所有设备都支持,

支持有线网的正常使用的设备才能使用有线网共享功能。

也就是说插入路由器的网线接收到Android设备,Android设备能够自动获取ip;

这是Android设备是否支持有线网的前提。也是Android设备是否支持以太网共享的前提。

开启以太网共享的开关是在设置中和热点分享同级的界面。

同级目录下网络共享功能有:

热点
蓝牙网络共享
usb网络共享
以太网共享

上面的功能其实就是字面意思。

通过连接蓝牙共享网络;通过usb共享网络;通过网线共享网络。

但是很多Android 设备是没有这些功能的,有些系统是显示选项但是置灰了,有些系统是直接隐藏了功能选项。

本文主要分享一下Android14 以太网相关代码的,对于那些定制化修改以太网设置或者开发以太网的功能会有些帮助。

以太网设置在很多手机上是不显示的,有的手机在使用转接口接入网线后会显示该选项。

二、原生设置Settings中以太网相关代码

1、以太网显示布局代码

布局文件:

packages\apps\Settings\res\xml\tether_prefs.xml

<?xml version="1.0" encoding="utf-8"?>

<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:settings="http://schemas.android.com/apk/res-auto"
    android:title="@string/tether_settings_title_all">

    <com.android.settingslib.widget.TopIntroPreference
        android:key="tether_prefs_top_intro"
        settings:searchable="false"/>

    <com.android.settingslib.PrimarySwitchPreference //(1)热点
        android:key="wifi_tether"
        android:title="@string/wifi_hotspot_checkbox_text"
        android:summary="@string/wifi_hotspot_off_subtext"
        android:fragment="com.android.settings.wifi.tether.WifiTetherSettings"
        settings:allowDividerAbove="true"
        settings:maxLines="2"/>

    //(2)usb网络共享
    <com.android.settingslib.RestrictedSwitchPreference 
        android:key="usb_tether_settings"
        android:title="@string/usb_tethering_button_text"
        android:summary="@string/usb_tethering_subtext"
        settings:keywords="@string/keywords_hotspot_tethering" />
    //(3)蓝牙网络共享
    <SwitchPreference
        android:key="enable_bluetooth_tethering"
        android:title="@string/bluetooth_tether_checkbox_text"
        android:summary="@string/bluetooth_tethering_subtext"
        settings:keywords="@string/keywords_hotspot_tethering" />
    //(3)以太网共享
    <SwitchPreference
        android:key="enable_ethernet_tethering"
        android:title="@string/ethernet_tether_checkbox_text"
        android:summary="@string/ethernet_tethering_subtext"
        settings:keywords="@string/keywords_hotspot_tethering" />

    <com.android.settingslib.widget.FooterPreference
        android:key="disabled_on_data_saver"
        android:title="@string/tether_settings_disabled_on_data_saver"
        android:selectable="false"
        settings:searchable="false"/>
</PreferenceScreen>

2、Java部分代码

packages\apps\Settings\src\com\android\settings\network\tether\TetherSettings.java

@SearchIndexable
public class TetherSettings extends RestrictedSettingsFragment
        implements DataSaverBackend.Listener {
        
private ConnectivityManager mCm;

    @Override
    public void onCreate(Bundle icicle) { // (1) 界面 onCreate
        super.onCreate(icicle);
       
        setupTetherPreference(); //绑定界面
        ...//网络共享选项是否显示判断
        onDataSaverChanged(mDataSaverBackend.isDataSaverEnabled());
    }

    @VisibleForTesting
    void setupTetherPreference() { //(2)绑定
        mUsbTether = (RestrictedSwitchPreference) findPreference(KEY_USB_TETHER_SETTINGS);
        mBluetoothTether = (SwitchPreference) findPreference(KEY_ENABLE_BLUETOOTH_TETHERING);
        mEthernetTether = (SwitchPreference) findPreference(KEY_ENABLE_ETHERNET_TETHERING);
    }
    
    @Override
    public void onStart() {
        super.onStart();

    ...
        registerReceiver();//(3)广播监听

        updateUsbState();
        updateBluetoothAndEthernetState();
    }

    @VisibleForTesting
    void registerReceiver() { //(4)以太网共享状态监听
        final Activity activity = getActivity();

       
        mTetherChangeReceiver = new TetherChangeReceiver();
        IntentFilter filter = new IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED);
        final Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter);
        
        //其他共享监听...
    }

    //(5)开关点击后回调,热点分享是其他地方处理
    @Override
    public boolean onPreferenceTreeClick(Preference preference) {
        if (preference == mUsbTether) { //usb网络共享
            if (mUsbTether.isChecked()) {
                startTethering(TETHERING_USB);
            } else {
                mCm.stopTethering(TETHERING_USB);
            }
        } else if (preference == mBluetoothTether) { //蓝牙网络共享
            if (mBluetoothTether.isChecked()) {
                startTethering(TETHERING_BLUETOOTH);
            } else {
                mCm.stopTethering(TETHERING_BLUETOOTH);
            }
        } else if (preference == mEthernetTether) {//(6)以太网共享开关状态设置
            if (mEthernetTether.isChecked()) {
                startTethering(TETHERING_ETHERNET);
            } else {
                mCm.stopTethering(TETHERING_ETHERNET);//关闭
            }
        }

        return super.onPreferenceTreeClick(preference);
    }

    //(7)以太网共享,开启
    private void startTethering(int choice) {
        if (choice == TETHERING_BLUETOOTH) {//如果是蓝牙网络共享,需要先打开蓝牙
            // Turn on Bluetooth first.
            BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
            if (adapter.getState() == BluetoothAdapter.STATE_OFF) {
                mBluetoothEnableForTether = true;
                adapter.enable();
                mBluetoothTether.setEnabled(false);
                return;
            }
        }

        //(8)开启共享
        mCm.startTethering(choice, true, mStartTetheringCallback, mHandler); 
    }

        //(9)各种网络共享的广播监听
    private class TetherChangeReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context content, Intent intent) {
            String action = intent.getAction();
            if (DEBUG) {
                Log.d(TAG, "onReceive() action : " + action);
            }
            // TODO(b/194961339): Stop using ACTION_TETHER_STATE_CHANGED and use
            //  mTetheringEventCallback instead.
            if (action.equals(TetheringManager.ACTION_TETHER_STATE_CHANGED)) { //以太网共享状态广播
                // TODO - this should understand the interface types
                ArrayList<String> available = intent.getStringArrayListExtra(
                        TetheringManager.EXTRA_AVAILABLE_TETHER);
                ArrayList<String> active = intent.getStringArrayListExtra(
                        TetheringManager.EXTRA_ACTIVE_TETHER);
                updateBluetoothState();
                Log.d(TAG, "onReceive() available =  " + available + ", active = " + active);
                //(7)更新以太网状态
                updateEthernetState(available.toArray(new String[available.size()]),
                        active.toArray(new String[active.size()]));
            }
        }
    }

    //(10)以太网共享开关状态更新
    @VisibleForTesting
    void updateEthernetState(String[] available, String[] tethered) {
        boolean isAvailable = false;
        boolean isTethered = false;

        for (String s : available) {
            if (mAvailableInterfaces.contains(s)) isAvailable = true;
        }

        for (String s : tethered) {
            if (mAvailableInterfaces.contains(s)) isTethered = true;
        }

        if (DEBUG) {
            Log.d(TAG, "updateEthernetState() isAvailable : " + isAvailable
                    + ", isTethered : " + isTethered);
        }
        
        //(11)只有tethered返回数据的情况,以太网开关才会是开启
        if (isTethered) {
            mEthernetTether.setEnabled(!mDataSaverEnabled);
            mEthernetTether.setChecked(true);
        } else if (mAvailableInterfaces.size() > 0) {
            mEthernetTether.setEnabled(!mDataSaverEnabled);
            mEthernetTether.setChecked(false);
        } else {
            mEthernetTether.setEnabled(false);
            mEthernetTether.setChecked(false);
        }
    }

上面就是以太网开关的主要相关代码。

主要就是界面初始化+点击事件监听处理+广播监听处理+状态更新,都在上面这个类。

USB网络共享、蓝牙网络共享的控制代码也是在上面这个类。

2、以太网共享开关状态

以太网开关状态,不像热点那样有api可以查询直接查询。

并且以太网共享开关,热点开关状态都是系统重启不记忆的;

如果要实现记忆,就要自己记忆状态,设备重启后,重新打开。

以太网状态查询就是通过监听广播,通过广播返回的数据判断

主要代码:

(1)注册广播
        mTetherChangeReceiver = new TetherChangeReceiver();
        IntentFilter filter = new IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED);
        final Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter);

(2)监听广播
    private class TetherChangeReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context content, Intent intent) {
            String action = intent.getAction();
            if (DEBUG) {
                Log.d(TAG, "onReceive() action : " + action);
            }
          
            if (action.equals(TetheringManager.ACTION_TETHER_STATE_CHANGED)) { //以太网共享状态广播
                // TODO - this should understand the interface types
                ArrayList<String> available = intent.getStringArrayListExtra(
                        TetheringManager.EXTRA_AVAILABLE_TETHER);
                //只有这个activity是有用的
                ArrayList<String> active = intent.getStringArrayListExtra(
                        TetheringManager.EXTRA_ACTIVE_TETHER);
                updateBluetoothState();
                Log.d(TAG, "onReceive() available =  " + available + ", active = " + active);
                //(7)更新以太网状态
                updateEthernetState(available.toArray(new String[available.size()]),
                        active.toArray(new String[active.size()]));
            }
        }
    }

(3)更新状态
    void updateEthernetState(String[] available, String[] tethered) {
        boolean isAvailable = false;
        boolean isTethered = false;

        for (String s : tethered) {
            if (mAvailableInterfaces.contains(s)) isTethered = true;
        }

        //只有tethered返回数据的情况,以太网开关才会是开启
        if (isTethered) {
            mEthernetTether.setEnabled(!mDataSaverEnabled);
            mEthernetTether.setChecked(true);
        } else if (mAvailableInterfaces.size() > 0) {
            mEthernetTether.setEnabled(!mDataSaverEnabled);
            mEthernetTether.setChecked(false);
        } else {
            mEthernetTether.setEnabled(false);
            mEthernetTether.setChecked(false);
        }
    }

上面的代码看起来有点复杂,但是整理一下只要判断一种情况就行

ArrayList<String> active = intent.getStringArrayListExtra(TetheringManager.EXTRA_ACTIVE_TETHER);
//以太网共享是否开启:
boolean isEthernetShare = activite.size() > 0;

只要广播接收到当前可用的以太网共享节点数据是大于0 ,其实就是以太网开启的情况。

也许有些人会有疑问,以太网状态的广播,监听了就会有回调吗?

答案:是有的。

比如网络变化的广播也是一样的,只要监听了马上就会有回调。

但是也不是所有广播监听了就马上又回调,大部分广播监听了不会马上又回调的,

比如wifi开关、热点开关等广播,监听后是不会马上有回调的,需要开关状态改变后才有回调。

3、以太网共享设置接口

设置以太网就是api的调用:

ConnectivityManager mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

//开启以太网共享:
 mCm.startTethering(TetheringManager.TETHERING_ETHERNET, true, mStartTetheringCallback, mHandler); 
 
//关闭以太网共享:
mCm.stopTethering(TetheringManager.TETHERING_ETHERNET);

三、其他

1、以太网共享小结

(1)以太网共享开关状态是通过监听广播更新的;
只要监听了广播,就会有回调,开关状态修改,也会有回调;
(2)以太网共享开关使用对应的api就可以;
(3)以太网共享重启是不记忆的,如果需要记忆要自己适配;
(4)以太网共享功能,需要设备有线网可以使能的前提;
(5)以太网共享的节点是和有线网共用一个节点的
打开以太网共享后,有线网的节点会重新生成一个ip,用来做以太网共享功能;
大部分设备应该使用eth0节点,ifconfig 可以看到ip变化。

USB网络共享、蓝牙网络共享相关处理是类似的。

2、以太网开关的具体代码流程

这里简单追一下Android14以太网开启从应用到系统相关的调用流程代码:

(1)ConnectivityManager.startTethering

应用端的调用

//开启以太网共享:
 mCm.startTethering(TetheringManager.TETHERING_ETHERNET, true, mStartTetheringCallback, mHandler); 
(2) ConnectivityManager

package\modules\Connectivity\framework\src\android\net\ConnectivityManager.java

public class ConnectivityManager {
    private static final String TAG = "ConnectivityManager";
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    public void startTethering(int type, boolean showProvisioningUi,
            final OnStartTetheringCallback callback, Handler handler) {
        Objects.requireNonNull(callback, "OnStartTetheringCallback cannot be null.");

        final Executor executor = new Executor() {
            @Override
            public void execute(Runnable command) {
                if (handler == null) {
                    command.run();
                } else {
                    handler.post(command);
                }
            }
        };

        final StartTetheringCallback tetheringCallback = new StartTetheringCallback() {
            @Override
            public void onTetheringStarted() {
                callback.onTetheringStarted();
            }

            @Override
            public void onTetheringFailed(final int error) {
                callback.onTetheringFailed();
            }
        };

        final TetheringRequest request = new TetheringRequest.Builder(type)
                .setShouldShowEntitlementUi(showProvisioningUi).build();

        getTetheringManager().startTethering(request, executor, tetheringCallback);
    }

    private TetheringManager getTetheringManager() {
        synchronized (mTetheringEventCallbacks) {
            if (mTetheringManager == null) {
                mTetheringManager = mContext.getSystemService(TetheringManager.class);
            }
            return mTetheringManager;
        }
    }


}

热点也是这个类的api进行开关控制的。

Wifi是用WifiManager相关api的。

(3)TetheringManager

这个类是热点和其他分享网络的重要管理类。

package\modules\Connectivity\Tethering\common\TetheringLib\src\android\net\TetheringManager.java

@SystemApi
public class TetheringManager {
    private static final String TAG = TetheringManager.class.getSimpleName();
    private static final int DEFAULT_TIMEOUT_MS = 60_000;

    //各种网络共享的类型
    public static final int TETHERING_INVALID   = -1;
    public static final int TETHERING_WIFI      = 0;
    public static final int TETHERING_USB       = 1;
    public static final int TETHERING_BLUETOOTH = 2;
    public static final int TETHERING_WIFI_P2P = 3;
    public static final int TETHERING_NCM = 4;
    public static final int TETHERING_ETHERNET = 5;
    public static final int TETHERING_WIGIG = 6;
    public static final int MAX_TETHERING_TYPE = TETHERING_WIGIG;

    public void startTethering(@NonNull final TetheringRequest request,
            @NonNull final Executor executor, @NonNull final StartTetheringCallback callback) {
        final String callerPkg = mContext.getOpPackageName();
        Log.i(TAG, "startTethering caller:" + callerPkg);

        final IIntResultListener listener = new IIntResultListener.Stub() {
            @Override
            public void onResult(final int resultCode) {
                executor.execute(() -> {
                    if (resultCode == TETHER_ERROR_NO_ERROR) {
                        callback.onTetheringStarted();
                    } else {
                        callback.onTetheringFailed(resultCode);
                    }
                });
            }
        };
        getConnector(c -> c.startTethering(request.getParcel(), callerPkg,
                getAttributionTag(), listener));
    }

    private void getConnector(ConnectorConsumer consumer) {
        final ITetheringConnector connector;
        synchronized (mConnectorWaitQueue) {
            connector = mConnector;
            if (connector == null) {
                mConnectorWaitQueue.add(consumer);
                return;
            }
        }

        try {
            consumer.onConnectorAvailable(connector);
        } catch (RemoteException e) {
            throw new IllegalStateException(e);
        }
    }

}

上面可以看到很多其他相关网络类别的定义。

(4)ITetheringConnector

这个是接口定义,定义相关暴露的方法,aidl绑定服务用的。

package\modules\Connectivity\Tethering\common\TetheringLib\src\android\net\ITetheringConnector.aidl

oneway interface ITetheringConnector {
    void tether(String iface, String callerPkg, String callingAttributionTag,
            IIntResultListener receiver);

    void untether(String iface, String callerPkg, String callingAttributionTag,
            IIntResultListener receiver);

    void setUsbTethering(boolean enable, String callerPkg,
            String callingAttributionTag, IIntResultListener receiver);

    void startTethering(in TetheringRequestParcel request, String callerPkg,
            String callingAttributionTag, IIntResultListener receiver);

    void stopTethering(int type, String callerPkg, String callingAttributionTag,
            IIntResultListener receiver);
...
}
(5)TetheringService

热点等网络的服务实现

package\modules\Connectivity\Tethering\src\com\android\networkstack\tethering\TetheringService.java

        @Override
        public void startTethering(TetheringRequestParcel request, String callerPkg,
                String callingAttributionTag, IIntResultListener listener) {
            if (checkAndNotifyCommonError(callerPkg,
                    callingAttributionTag,
                    request.exemptFromEntitlementCheck /* onlyAllowPrivileged */,
                    listener)) {
                return;
            }

            mTethering.startTethering(request, callerPkg, listener);
        }

wifi服务不在这里。

(6)Tethering

这个相当于一个工具类吧,调用相关服务或者管理类实现具体功能。

package\modules\Connectivity\Tethering\src\com\android\networkstack\tethering\Tethering.java

/**
 *
 * This class holds much of the business logic to allow Android devices
 * to act as IP gateways via USB, BT, and WiFi interfaces.
 */
public class Tethering {

    private static final String TAG = Tethering.class.getSimpleName();
    private static final boolean DBG = false;
    private static final boolean VDBG = false;

    void startTethering(final TetheringRequestParcel request, final String callerPkg,
            final IIntResultListener listener) {
        mHandler.post(() -> {
            final TetheringRequestParcel unfinishedRequest = mActiveTetheringRequests.get(
                    request.tetheringType);
            // If tethering is already enabled with a different request,
            // disable before re-enabling.
            if (unfinishedRequest != null
                    && !TetheringUtils.isTetheringRequestEquals(unfinishedRequest, request)) {
                enableTetheringInternal(request.tetheringType, false /* disabled */, null);
                mEntitlementMgr.stopProvisioningIfNeeded(request.tetheringType);
            }
            mActiveTetheringRequests.put(request.tetheringType, request);

            if (request.exemptFromEntitlementCheck) {
                mEntitlementMgr.setExemptedDownstreamType(request.tetheringType);
            } else {
                mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType,
                        request.showProvisioningUi);
            }
            enableTetheringInternal(request.tetheringType, true /* enabled */, listener);
            mTetheringMetrics.createBuilder(request.tetheringType, callerPkg);
        });
    }

    private void enableTetheringInternal(int type, boolean enable,
            final IIntResultListener listener) {
        int result = TETHER_ERROR_NO_ERROR;
        switch (type) {
            case TETHERING_WIFI:
                result = setWifiTethering(enable);
                break;
            case TETHERING_USB:
                result = setUsbTethering(enable);
                break;
            case TETHERING_BLUETOOTH:
                setBluetoothTethering(enable, listener);
                break;
            case TETHERING_NCM:
                result = setNcmTethering(enable);
                break;
            case TETHERING_ETHERNET:
                result = setEthernetTethering(enable);
                break;
            default:
                Log.w(TAG, "Invalid tether type.");
                result = TETHER_ERROR_UNKNOWN_TYPE;
        }

        // The result of Bluetooth tethering will be sent by #setBluetoothTethering.
        if (type != TETHERING_BLUETOOTH) {
            sendTetherResult(listener, result, type);
        }
    }

    private int setEthernetTethering(final boolean enable) {
        final EthernetManager em = (EthernetManager) mContext.getSystemService(
                Context.ETHERNET_SERVICE);
        if (enable) {
            if (mEthernetCallback != null) {
                Log.d(TAG, "Ethernet tethering already started");
                return TETHER_ERROR_NO_ERROR;
            }

            mEthernetCallback = new EthernetCallback();
            mEthernetIfaceRequest = em.requestTetheredInterface(mExecutor, mEthernetCallback);
        } else {
            stopEthernetTethering();
        }
        return TETHER_ERROR_NO_ERROR;
    }

}
(7)EthernetManager

这个是控制有线网的管理者。

package\modules\Connectivity\framework-t\src\android\net\EthernetManager.java

public class EthernetManager {
    private static final String TAG = "EthernetManager";

    private final IEthernetManager mService;

    public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor,
            @NonNull final TetheredInterfaceCallback callback) {
        Objects.requireNonNull(callback, "Callback must be non-null");
        Objects.requireNonNull(executor, "Executor must be non-null");
        final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() {
            @Override
            public void onAvailable(String iface) {
                executor.execute(() -> callback.onAvailable(iface));
            }

            @Override
            public void onUnavailable() {
                executor.execute(() -> callback.onUnavailable());
            }
        };

        try {
            mService.requestTetheredInterface(cbInternal);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        return new TetheredInterfaceRequest(mService, cbInternal);
    }


}

有线网开关是通过 EthernetManager 进行控制的。

所以说以太网共享开关控制,兜兜转转,实际又回到了有线网控制的地方。

(8)EthernetServiceImpl

有线网控制的实现

package\modules\Connectivity\service-t\src\com\android\server\ethernet\EthernetServiceImpl.java

public class EthernetServiceImpl extends IEthernetManager.Stub {
    private static final String TAG = "EthernetServiceImpl";

    @Override
    public void requestTetheredInterface(ITetheredInterfaceCallback callback) {
        Objects.requireNonNull(callback, "callback must not be null");
        PermissionUtils.enforceNetworkStackPermissionOr(mContext,
                android.Manifest.permission.NETWORK_SETTINGS);
        mTracker.requestTetheredInterface(callback);
    }

}
(8)EthernetTracker

package\modules\Connectivity\service-t\src\com\android\server\ethernet\EthernetTracker.java

    public void requestTetheredInterface(ITetheredInterfaceCallback callback) {
        mHandler.post(() -> {
            if (!mTetheredInterfaceRequests.register(callback)) {
                // Remote process has already died
                return;
            }
            if (mTetheringInterfaceMode == INTERFACE_MODE_SERVER) {
                if (mTetheredInterfaceWasAvailable) {
                    notifyTetheredInterfaceAvailable(callback, mTetheringInterface);
                }
                return;
            }

            setTetheringInterfaceMode(INTERFACE_MODE_SERVER);
        });
    }

    private void setTetheringInterfaceMode(int mode) {
        Log.d(TAG, "Setting tethering interface mode to " + mode);
        mTetheringInterfaceMode = mode;
        if (mTetheringInterface != null) {
            removeInterface(mTetheringInterface);
            addInterface(mTetheringInterface);
            // when this broadcast is sent, any calls to notifyTetheredInterfaceAvailable or
            // notifyTetheredInterfaceUnavailable have already happened
            broadcastInterfaceStateChange(mTetheringInterface);
        }
    }

    private void removeInterface(String iface) {
        mFactory.removeInterface(iface);
        maybeUpdateServerModeInterfaceState(iface, false);
    }

    private void addInterface(String iface) {
        InterfaceConfigurationParcel config = null;
        // Bring up the interface so we get link status indications.
        try {
            PermissionUtils.enforceNetworkStackPermission(mContext);
            // Read the flags before attempting to bring up the interface. If the interface is
            // already running an UP event is created after adding the interface.
            config = NetdUtils.getInterfaceConfigParcel(mNetd, iface);
            if (NetdUtils.hasFlag(config, INetd.IF_STATE_DOWN)) {
                // As a side-effect, NetdUtils#setInterfaceUp() also clears the interface's IPv4
                // address and readds it which *could* lead to unexpected behavior in the future.
                NetdUtils.setInterfaceUp(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);
        }

        if (config == null) {
            Log.e(TAG, "Null interface config parcelable for " + iface + ". Bailing out.");
            return;
        }

        if (getInterfaceMode(iface) == INTERFACE_MODE_SERVER) {
            maybeUpdateServerModeInterfaceState(iface, true);
            return;
        }

        ...
    }
(9)NetdUtils

这个其实就是一个工具类,用来控制节点开启、关闭等功能

framework\libs\net\client-libs\netd\com\android\net\module\util\NetdUtils.java

public class NetdUtils {
    private static final String TAG = NetdUtils.class.getSimpleName();

    public static void setInterfaceUp(INetd netd, String iface) {
        final InterfaceConfigurationParcel configParcel = getInterfaceConfigParcel(netd, iface);
        configParcel.flags = removeAndAddFlags(configParcel.flags, IF_STATE_DOWN /* remove */,
                IF_STATE_UP /* add */);
        setInterfaceConfig(netd, configParcel);
    }

    public static void setInterfaceConfig(INetd netd, InterfaceConfigurationParcel configParcel) {
        try {
            netd.interfaceSetCfg(configParcel);
        } catch (RemoteException | ServiceSpecificException e) {
            throw new IllegalStateException(e);
        }
    }

}
(10)INetd

具体实现是通过 INetd,调用到底层。

framework\libs\net\common\netd\aidl_api\netd_aidl_interface\1\android\net\INetd.aidl

这里的 INetd 是有很多版本的,具体是哪个版本,要看系统硬件选择。

这里再往下就是HIDL的代码,就是cpp代码了,不再继续往下追踪了。

Wifi最终调用也是到IWifi,再到底层。

以太网共享开启的那个节点就是有线网那个节点。只是会重新配置ip信息。

3、原生Settings中热点设置相关代码

(1)Settings应用热点设置界面代码:

packages\apps\Settings\src\com\android\settings\wifi\tether\WifiTetherPreferenceController.java

public class WifiTetherPreferenceController extends AbstractPreferenceController ...{

    private static final String WIFI_TETHER_SETTINGS = "wifi_tether";

    @Override
    public void displayPreference(PreferenceScreen screen) { //初始化
        super.displayPreference(screen);
        mPreference = screen.findPreference(WIFI_TETHER_SETTINGS);
        if (mPreference == null) {
            // unavailable
            return;
        }
        if (mSwitch == null) {
            mSwitch = new GenericSwitchController(mPreference);
            mSwitch.setListener(this);
            updateSwitch();
        }
        mPreference.setEnabled(canEnabled());
        if (!mIsWifiTetheringAllow) {
            mPreference.setSummary(R.string.not_allowed_by_ent);
        }
    }

    @Override
    public boolean onSwitchToggled(boolean isChecked) { //开关回调
        if (isChecked) {
            mTetheringManagerModel.startTethering(TETHERING_WIFI);
        } else {
            mTetheringManagerModel.stopTethering(TETHERING_WIFI);
        }
        return true;
    }
(2)具体的热点开关api接口代码:

packages\apps\Settings\src\com\android\settings\network\tether\TetheringManagerModel.java

public class TetheringManagerModel extends AndroidViewModel {
    protected TetheringManager mTetheringManager;

    public TetheringManagerModel(@NonNull Application application) {
        super(application);
        mTetheringManager = application.getSystemService(TetheringManager.class);
        mTetheringManager
                .registerTetheringEventCallback(application.getMainExecutor(), mEventCallback);
    }

    //开启热点
    public void startTethering(int type) {
        mTetheringManager.startTethering(type, getApplication().getMainExecutor(),
                mStartTetheringCallback);
    }

    //关闭热点
    public void stopTethering(int type) {
        mTetheringManager.stopTethering(type);
    }

}

4、热点设置

Android11 设置默认热点名称和热点密码、密码长度
https://blog.csdn.net/wenzhi20102321/article/details/127737534

5、Android13 有线网开关研究

https://blog.csdn.net/wenzhi20102321/article/details/131871354

相关推荐
ziix1 小时前
android-sdk 安装脚本
android·android-sdk安装脚本
柯南二号1 小时前
Android 实现悬浮球的功能
android·gitee·悬浮球
我想睡到自然醒₍˄·͈༝·͈˄*₎◞ ̑1 小时前
【Android】View的解析—滑动篇
android·java
chadm1 小时前
android bindService打开失败
android
诸神黄昏EX1 小时前
Android 常用命令和工具解析之内存相关
android·java·开发语言
zhangphil1 小时前
Android Glide load origin Bitmap, Kotlin
android·kotlin·glide
MuYe1 小时前
Android Hook - 隐藏API绕过实践
android
dreamsever1 小时前
Glide源码学习
android·java·学习·glide
weixin_449310841 小时前
聚水潭与MySQL数据集成案例分享
android·数据库·mysql
zky___5 小时前
Android \android-sdk\platform-tools\adb.exe start-server‘ failed
android·adb