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

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Android以太网共享是指使用Android手机或平板电脑通过USB或Wi-Fi等方式将有线以太网连接共享给其他设备的功能Android支持以太网共享是因为很多人在使用Android设备时可能会遇到只能连接无线网络而无法使用有线网络的问题。以太网共享功能可以解决这个问题,让用户可以通过有线网络连接上网。 具体的操作步骤如下: 1. 首先,确保你的手机或平板电脑上的Android系统版本支持以太网共享功能。某些旧版系统可能不支持此功能。 2. 连接手机或平板电脑的USB接口和电脑的USB接口,然后在Android设备上拉下通知栏,点击USB连接选项,在弹出的对话框中选择“以太网共享”选项。 3. 当手机或平板电脑成功连接到有线网络后,可以看到网络连接状态发生变化。此时,你可以把手机或平板电脑通过USB连接给其他设备,如电脑,让其他设备也能够享受有线网络连接。 4. 如果你希望通过Wi-Fi方式共享有线网络,则在选择“以太网共享”选项时选择“Wi-Fi共享”选项。Android设备会创建一个Wi-Fi热点,其他设备可以通过连接这个热点来使用有线网络。 需要注意的是,以太网共享功能可能会消耗较多的电量和流量。因此,在使用此功能时需要注意设备的电量和流量消耗,以及网络安全问题。 总之,Android以太网共享是一个可以将有线以太网连接共享给其他设备的实用功能,让用户在无法使用有线网络的情况下仍能够通过手机或平板电脑连接上有线网络。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

峥嵘life

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值