Android14 以太网共享功能 相关代码简介
文章目录
- [Android14 以太网共享功能 相关代码简介](#Android14 以太网共享功能 相关代码简介)
-
- 一、前言
- 二、原生设置Settings中以太网相关代码
- 三、其他
-
- 1、以太网共享小结
- 2、以太网开关的具体代码流程
-
- (1)ConnectivityManager.startTethering
- [(2) ConnectivityManager](#(2) ConnectivityManager)
- (3)TetheringManager
- (4)ITetheringConnector
- (5)TetheringService
- (6)Tethering
- (7)EthernetManager
- (8)EthernetServiceImpl
- (8)EthernetTracker
- (9)NetdUtils
- (10)INetd
- 3、原生Settings中热点设置相关代码
- 4、热点设置
- [5、Android13 有线网开关研究](#5、Android13 有线网开关研究)
一、前言
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