Settings
packages/apps/Settings/src/com/android/settings/TetherSettings.java
public class TetherSettings extends RestrictedSettingsFragment
implements DataSaverBackend.Listener {
private OnStartTetheringCallback mStartTetheringCallback;
@Override
public boolean onPreferenceTreeClick(Preference preference) {
if (preference == mUsbTether) {
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) {
if (mEthernetTether.isChecked()) {
startTethering(TETHERING_ETHERNET);
} else {
mCm.stopTethering(TETHERING_ETHERNET);
}
}
return super.onPreferenceTreeClick(preference);
}
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;
}
}
mCm.startTethering(choice, true, mStartTetheringCallback, mHandler);
}
private static final class OnStartTetheringCallback extends
ConnectivityManager.OnStartTetheringCallback {
final WeakReference<TetherSettings> mTetherSettings;
OnStartTetheringCallback(TetherSettings settings) {
mTetherSettings = new WeakReference<>(settings);
}
@Override
public void onTetheringStarted() {
update();
}
@Override
public void onTetheringFailed() {
update();
}
private void update() {
TetherSettings settings = mTetherSettings.get();
if (settings != null) {
settings.updateState();
}
}
}
private final class EthernetListener implements EthernetManager.Listener {
public void onAvailabilityChanged(String iface, boolean isAvailable) {
mHandler.post(TetherSettings.this::updateState);
}
}
private void updateState() {
final ConnectivityManager cm =
(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
final String[] available = cm.getTetherableIfaces();
final String[] tethered = cm.getTetheredIfaces();
final String[] errored = cm.getTetheringErroredIfaces();
updateState(available, tethered, errored);
}
private void updateState(String[] available, String[] tethered,
String[] errored) {
updateUsbState(available, tethered, errored);
updateBluetoothState();
updateEthernetState(available, tethered);
}
}
framework
frameworks/base/packages/Tethering
rk3399_android_11/android/frameworks/base/packages/Tethering/src$ tree
.
├── android
│ └── net
│ ├── dhcp
│ │ ├── DhcpServerCallbacks.java
│ │ └── DhcpServingParamsParcelExt.java
│ ├── ip
│ │ ├── IpServer.java
│ │ └── RouterAdvertisementDaemon.java
│ └── util
│ ├── BaseNetdUnsolicitedEventListener.java
│ ├── InterfaceSet.java
│ ├── PrefixUtils.java
│ ├── TetheringMessageBase.java
│ ├── TetheringUtils.java
│ └── VersionedBroadcastListener.java
└── com
└── android
└── networkstack
└── tethering
├── BpfCoordinator.java
├── ConnectedClientsTracker.java
├── EntitlementManager.java
├── IPv6TetheringCoordinator.java
├── OffloadController.java
├── OffloadHardwareInterface.java
├── PrivateAddressCoordinator.java
├── TetheringConfiguration.java
├── TetheringDependencies.java
├── TetheringInterfaceUtils.java
├── Tethering.java
├── TetheringNotificationUpdater.java
├── TetheringService.java
├── UpstreamNetworkMonitor.java
└── UpstreamNetworkState.java
framework/base/core/java/android/net/ConnectivityManager.java
@SystemService(Context.CONNECTIVITY_SERVICE)
public class ConnectivityManager {
@SystemApi
@Deprecated
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
public void startTethering(int type, boolean showProvisioningUi,
final OnStartTetheringCallback callback, Handler handler) {
Preconditions.checkNotNull(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();
mTetheringManager.startTethering(request, executor, tetheringCallback);
}
/**
* Stops tethering for the given type. Also cancels any provisioning rechecks for that type if
* applicable.
*
* @param type The type of tethering to stop. Must be one of
* {@link ConnectivityManager.TETHERING_WIFI},
* {@link ConnectivityManager.TETHERING_USB}, or
* {@link ConnectivityManager.TETHERING_BLUETOOTH}.
*
* @deprecated Use {@link TetheringManager#stopTethering} instead.
* @hide
*/
@SystemApi
@Deprecated
@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
public void stopTethering(int type) {
mTetheringManager.stopTethering(type);
}
}
framework/base/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
public class TetheringManager {
/**
* Ethernet tethering type.
* @see #startTethering(TetheringRequest, Executor, StartTetheringCallback)
*/
public static final int TETHERING_ETHERNET = 5;
@SystemApi(client = MODULE_LIBRARIES)
public TetheringManager(@NonNull final Context context,
@NonNull Supplier<IBinder> connectorSupplier) {
mContext = context;
mCallback = new TetheringCallbackInternal();
mConnectorSupplier = connectorSupplier;
final String pkgName = mContext.getOpPackageName();
final IBinder connector = mConnectorSupplier.get();
// If the connector is available on start, do not start a polling thread. This introduces
// differences in the thread that sends the oneway binder calls to the service between the
// first few seconds after boot and later, but it avoids always having differences between
// the first usage of TetheringManager from a process and subsequent usages (so the
// difference is only on boot). On boot binder calls may be queued until the service comes
// up and be sent from a worker thread; later, they are always sent from the caller thread.
// Considering that it's just oneway binder calls, and ordering is preserved, this seems
// better than inconsistent behavior persisting after boot.
if (connector != null) {
mConnector = ITetheringConnector.Stub.asInterface(connector);
} else {
startPollingForConnector();
}
Log.i(TAG, "registerTetheringEventCallback:" + pkgName);
getConnector(c -> c.registerTetheringEventCallback(mCallback, pkgName));
}
@RequiresPermission(anyOf = {
android.Manifest.permission.TETHER_PRIVILEGED,
android.Manifest.permission.WRITE_SETTINGS
})
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, 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);
}
}
}
framework/base/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java
public class TetheringService extends Service {
private TetheringConnector mConnector;
@Override
public void onCreate() {
final TetheringDependencies deps = makeTetheringDependencies();
// The Tethering object needs a fully functional context to start, so this can't be done
// in the constructor.
mConnector = new TetheringConnector(makeTethering(deps), TetheringService.this);
}
/**
* Make a reference to Tethering object.
*/
@VisibleForTesting
public Tethering makeTethering(TetheringDependencies deps) {
System.loadLibrary("tetherutilsjni");
return new Tethering(deps);
}
@NonNull
@Override
public IBinder onBind(Intent intent) {
return mConnector;
}
private static class TetheringConnector extends ITetheringConnector.Stub {
private final TetheringService mService;
private final Tethering mTethering;
TetheringConnector(Tethering tether, TetheringService service) {
mTethering = tether;
mService = service;
}
@Override
public void startTethering(TetheringRequestParcel request, String callerPkg,
IIntResultListener listener) {
if (checkAndNotifyCommonError(callerPkg,
request.exemptFromEntitlementCheck /* onlyAllowPrivileged */,
listener)) {
return;
}
mTethering.startTethering(request, listener);
}
}
}
./base/packages/Tethering/src/com/android/networkstack/tethering/Tethering.java
public class Tethering {
private static final String TAG = Tethering.class.getSimpleName();
private static final boolean DBG = false;
private static final boolean VDBG = false;
public Tethering(TetheringDependencies deps) {
mExecutor = new TetheringThreadExecutor(mHandler);
}
void startTethering(final TetheringRequestParcel request, 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);
});
}
/**
* Enables or disables tethering for the given type. If provisioning is required, it will
* schedule provisioning rechecks for the specified interface.
*/
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);
synchronized (mPublicSync) {
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 {
stopEthernetTetheringLocked();
}
}
return TETHER_ERROR_NO_ERROR;
}
private class TetheringThreadExecutor implements Executor {
private final Handler mTetherHandler;
TetheringThreadExecutor(Handler handler) {
mTetherHandler = handler;
}
@Override
public void execute(Runnable command) {
if (!mTetherHandler.post(command)) {
throw new RejectedExecutionException(mTetherHandler + " is shutting down");
}
}
}
private class EthernetCallback implements EthernetManager.TetheredInterfaceCallback {
@Override
public void onAvailable(String iface) {
synchronized (mPublicSync) {
if (this != mEthernetCallback) {
// Ethernet callback arrived after Ethernet tethering stopped. Ignore.
return;
}
maybeTrackNewInterfaceLocked(iface, TETHERING_ETHERNET);
changeInterfaceState(iface, IpServer.STATE_TETHERED);
mConfiguredEthernetIface = iface;
}
}
@Override
public void onUnavailable() {
synchronized (mPublicSync) {
if (this != mEthernetCallback) {
// onAvailable called after stopping Ethernet tethering.
return;
}
stopEthernetTetheringLocked();
}
}
}
}
./core/java/android/net/EthernetManager.java
public class EthernetManager {
/**
* Request a tethered interface in tethering mode.
*
* <p>When this method is called and there is at least one ethernet interface available, the
* system will designate one to act as a tethered interface. If there is already a tethered
* interface, the existing interface will be used.
* @param callback A callback to be called once the request has been fulfilled.
*/
@RequiresPermission(anyOf = {
android.Manifest.permission.NETWORK_STACK,
android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
})
@NonNull
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);
}
}
opt/net/ethernet/java/com/android/server/ethernet/EthernetServiceImpl.java
public class EthernetServiceImpl extends IEthernetManager.Stub {
private static final String TAG = "EthernetServiceImpl";
private EthernetTracker mTracker;
@Override
public void requestTetheredInterface(ITetheredInterfaceCallback callback) {
NetworkStack.checkNetworkStackPermissionOr(mContext,
android.Manifest.permission.NETWORK_SETTINGS);
mTracker.requestTetheredInterface(callback);
}
}
opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java
final class EthernetTracker {
private static final int INTERFACE_MODE_CLIENT = 1;
private static final int INTERFACE_MODE_SERVER = 2;
public void requestTetheredInterface(ITetheredInterfaceCallback callback) {
mHandler.post(() -> {
if (!mTetheredInterfaceRequests.register(callback)) {
// Remote process has already died
return;
}
if (mDefaultInterfaceMode == INTERFACE_MODE_SERVER) {
if (mTetheredInterfaceWasAvailable) {
notifyTetheredInterfaceAvailable(callback, mDefaultInterface);
}
return;
}
setDefaultInterfaceMode(INTERFACE_MODE_SERVER);
});
}
}
dumpsys tethering
adb shell dumpsys tethering
Tethering:
Configuration:
activeDataSubId: 1
tetherableUsbRegexs: [usb\d, rndis\d]
tetherableWifiRegexs: [wlan\d, softap\d]
tetherableWifiP2pRegexs: [p2p-p2p\d-.*, p2p-wlan\d-.*, p2p\d]
tetherableBluetoothRegexs: [bt-pan]
tetherableNcmRegexs: []
isDunRequired: false
chooseUpstreamAutomatically: true
legacyPreredUpstreamIfaceTypes: [9, 0, 5]
legacyDhcpRanges: [192.168.42.2, 192.168.42.254, 192.168.43.2, 192.168.43.254, 192.168.44.2, 192.168.44.254, 192.168.45.2, 192.168.45.254, 192.168.46.2, 192.168.46.254, 192.168.47.2, 192.168.47.254, 192.168.48.2, 192.168.48.254, 192.168.49.2, 192.168.49.254]
defaultIPv4DNS: [8.8.4.4, 8.8.8.8]
offloadPollInterval: 5000
provisioningApp: []
provisioningAppNoUi:
enableBpfOffload: true
enableLegacyDhcpServer: false
Entitlement:
isCellularUpstreamPermitted: true
Type: TETHERING UNKNOWN TYPE (5), Value: empty
Exempted: []
Tether state:
eth0 - TetheredState - lastError = 0
usb0 - AvailableState - lastError = 0
Upstream wanted: true
Current upstream interface(s): [usb0]
Hardware offload:
Offload HALs not started
Current upstream: null
Exempt prefixes: []
NAT timeout update callbacks received during the last offload session: 0
NAT timeout update netlink errors during the last offload session: 0
BPF offload:
mIsBpfEnabled: true
Polling started
Stats provider registered
Upstream quota: {usb0=9223372036854775807}
Polling interval: 5000 ms
Forwarding stats:
<empty>
Forwarding rules:
<empty>
Private address coordinator:
mUpstreamPrefixMap:
100 - [10.0.0.0/8]
mDownstreams:
5 - 192.168.7.85/24
Log:
2024-07-30T16:33:04.564 - MARK Tethering.constructed
2024-07-30T16:33:04.639 - [config] TetheringConfiguration{activeDataSubId:-1 tetherableUsbRegexs:[usb\d,rndis\d] tetherableWifiRegexs:[wlan\d,softap\d] tetherableWifiP2pRegexs:[p2p-p2p\d-.*,p2p-wlan\d-.*,p2p\d] tetherableBluetoothRegexs:[bt-pan] isDunRequired:false chooseUpstreamAutomatically:true offloadPollInterval:5000 preferredUpstreamIfaceTypes:[I@81fb789 provisioningApp:[] provisioningAppNoUi: enableBpfOffload:true enableLegacyDhcpServer:false}
2024-07-30T16:33:05.079 - OBSERVED user restrictions changed
2024-07-30T16:33:05.777 - OBSERVED active data subscription change, from -1 to -1
2024-07-30T16:33:06.509 - USB bcast connected:false configured:false rndis:false
2024-07-30T16:33:07.062 - OBSERVED configuration changed
2024-07-30T16:33:07.098 - [config] TetheringConfiguration{activeDataSubId:-1 tetherableUsbRegexs:[usb\d,rndis\d] tetherableWifiRegexs:[wlan\d,softap\d] tetherableWifiP2pRegexs:[p2p-p2p\d-.*,p2p-wlan\d-.*,p2p\d] tetherableBluetoothRegexs:[bt-pan] isDunRequired:false chooseUpstreamAutomatically:true offloadPollInterval:5000 preferredUpstreamIfaceTypes:[I@6c0347f provisioningApp:[] provisioningAppNoUi: enableBpfOffload:true enableLegacyDhcpServer:false}
2024-07-30T16:33:08.378 - OBSERVED active data subscription change, from -1 to 1
2024-07-30T16:33:08.403 - [config] TetheringConfiguration{activeDataSubId:1 tetherableUsbRegexs:[usb\d,rndis\d] tetherableWifiRegexs:[wlan\d,softap\d] tetherableWifiP2pRegexs:[p2p-p2p\d-.*,p2p-wlan\d-.*,p2p\d] tetherableBluetoothRegexs:[bt-pan] isDunRequired:false chooseUpstreamAutomatically:true offloadPollInterval:5000 preferredUpstreamIfaceTypes:[I@57989aa provisioningApp:[] provisioningAppNoUi: enableBpfOffload:true enableLegacyDhcpServer:false}
2024-07-30T16:33:08.434 - USB bcast connected:true configured:false rndis:false
2024-07-30T16:33:08.472 - USB bcast connected:true configured:true rndis:false
2024-07-30T16:33:09.526 - OBSERVED carrier config change
2024-07-30T16:33:09.543 - [config] TetheringConfiguration{activeDataSubId:1 tetherableUsbRegexs:[usb\d,rndis\d] tetherableWifiRegexs:[wlan\d,softap\d] tetherableWifiP2pRegexs:[p2p-p2p\d-.*,p2p-wlan\d-.*,p2p\d] tetherableBluetoothRegexs:[bt-pan] isDunRequired:false chooseUpstreamAutomatically:true offloadPollInterval:5000 preferredUpstreamIfaceTypes:[I@2d999b provisioningApp:[] provisioningAppNoUi: enableBpfOffload:true enableLegacyDhcpServer:false}
2024-07-30T16:33:10.077 - adding TetheringInterfaceStateMachine for: usb0
2024-07-30T16:33:10.085 - OBSERVED iface=usb0 state=1 error=0
2024-07-30T16:33:10.088 - OBSERVED LinkProperties update iface=usb0 state=AVAILABLE lp={InterfaceName: usb0 LinkAddresses: [ ] DnsAddresses: [ ] Domains: null MTU: 0 Routes: [ ]}
2024-07-30T16:33:10.089 - InitialState got EVENT_IFACE_SERVING_STATE_INACTIVE
2024-07-30T16:33:10.090 - InitialState got EVENT_IFACE_UPDATE_LINKPROPERTIES
2024-07-30T16:33:10.091 - [usb0] InitialState got CMD_IPV6_TETHER_UPDATE
2024-07-30T16:33:10.121 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:33:10.122 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:33:10.233 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:33:10.302 - InitialState got CMD_UPSTREAM_CHANGED
2024-07-30T16:33:15.550 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:33:17.030 - active iface (usb0) reported as added, ignoring
2024-07-30T16:33:17.580 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:33:22.164 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:33:30.699 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:33:30.700 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:33:40.724 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:33:40.729 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:33:47.551 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:33:47.552 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:33:57.577 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:34:06.949 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:34:06.951 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:34:06.952 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:34:06.972 - adding TetheringInterfaceStateMachine for: eth0
2024-07-30T16:34:06.978 - OBSERVED iface=eth0 state=1 error=0
2024-07-30T16:34:06.990 - OBSERVED LinkProperties update iface=eth0 state=AVAILABLE lp={InterfaceName: eth0 LinkAddresses: [ ] DnsAddresses: [ ] Domains: null MTU: 0 Routes: [ ]}
2024-07-30T16:34:06.990 - [eth0] InitialState got CMD_TETHER_REQUESTED
2024-07-30T16:34:07.043 - OBSERVED iface=eth0 state=2 error=0
2024-07-30T16:34:07.048 - OBSERVED LinkProperties update iface=eth0 state=TETHERED lp={InterfaceName: eth0 LinkAddresses: [ 192.168.7.85/24 ] DnsAddresses: [ ] Domains: null MTU: 0 Routes: [ 192.168.7.0/24 -> 0.0.0.0 eth0 mtu 0 ]}
2024-07-30T16:34:07.048 - InitialState got EVENT_IFACE_SERVING_STATE_INACTIVE
2024-07-30T16:34:07.048 - InitialState got EVENT_IFACE_UPDATE_LINKPROPERTIES
2024-07-30T16:34:07.054 - InitialState got EVENT_IFACE_SERVING_STATE_ACTIVE
2024-07-30T16:34:07.059 - SET master tether settings: ON
2024-07-30T16:34:07.063 - ERROR getIOffloadConfig error java.util.NoSuchElementException
2024-07-30T16:34:07.064 - [OffloadHardwareInterface] ERROR Could not find IOffloadConfig service
2024-07-30T16:34:07.064 - [OffloadController] tethering offload config not supported
2024-07-30T16:34:07.064 - [OffloadHardwareInterface] stopOffloadControl()
2024-07-30T16:34:07.071 - [UpstreamNetworkMonitor] requesting mobile upstream network: NetworkRequest [ NONE id=0, [ Transports: CELLULAR Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN Uid: 1073 AdministratorUids: [] RequestorUid: -1 RequestorPackageName: null] ]
2024-07-30T16:34:07.079 - [IPv6TetheringCoordinator] setUpstreamNetworkState: UpstreamNetworkState{null}
2024-07-30T16:34:07.079 - [BpfCoordinator] Polling started
2024-07-30T16:34:07.080 - TetherModeAliveState got EVENT_IFACE_UPDATE_LINKPROPERTIES
2024-07-30T16:34:07.081 - [eth0] TetheredState got CMD_IPV6_TETHER_UPDATE
2024-07-30T16:34:07.081 - OBSERVED LinkProperties update iface=eth0 state=TETHERED lp={InterfaceName: eth0 LinkAddresses: [ 192.168.7.85/24 ] DnsAddresses: [ ] Domains: null MTU: 0 Routes: [ 192.168.7.0/24 -> 0.0.0.0 eth0 mtu 0 ]}
2024-07-30T16:34:07.082 - [eth0] TetheredState got CMD_IPV6_TETHER_UPDATE
2024-07-30T16:34:07.083 - OBSERVED LinkProperties update iface=eth0 state=TETHERED lp={InterfaceName: eth0 LinkAddresses: [ 192.168.7.85/24 ] DnsAddresses: [ ] Domains: null MTU: 0 Routes: [ 192.168.7.0/24 -> 0.0.0.0 eth0 mtu 0 ]}
2024-07-30T16:34:07.088 - [eth0] TetheredState got CMD_TETHER_CONNECTION_CHANGED
2024-07-30T16:34:07.088 - [eth0] TetheredState got CMD_TETHER_CONNECTION_CHANGED
2024-07-30T16:34:07.089 - [eth0] TetheredState got CMD_IPV6_TETHER_UPDATE
2024-07-30T16:34:07.089 - OBSERVED LinkProperties update iface=eth0 state=TETHERED lp={InterfaceName: eth0 LinkAddresses: [ 192.168.7.85/24 ] DnsAddresses: [ ] Domains: null MTU: 0 Routes: [ 192.168.7.0/24 -> 0.0.0.0 eth0 mtu 0 ]}
2024-07-30T16:34:07.089 - TetherModeAliveState got EVENT_IFACE_UPDATE_LINKPROPERTIES
2024-07-30T16:34:07.089 - TetherModeAliveState got EVENT_IFACE_UPDATE_LINKPROPERTIES
2024-07-30T16:34:07.089 - TetherModeAliveState got EVENT_UPSTREAM_CALLBACK
2024-07-30T16:34:07.094 - Looking for default routes on: {InterfaceName: usb0 LinkAddresses: [ 10.202.135.102/8 ] DnsAddresses: [ /211.138.21.66,/211.138.23.66 ] PcscfAddresses: [ /0.0.0.0 ] Domains: null MTU: 1500 TcpBufferSizes: 524288,1048576,2097152,262144,524288,1048576 Routes: [ 0.0.0.0/0 -> 10.202.135.153 usb0 mtu 0,10.0.0.0/8 -> 0.0.0.0 usb0 mtu 0 ]}
2024-07-30T16:34:07.095 - Found upstream interface(s): [usb0]
2024-07-30T16:34:07.098 - SET DNS forwarders: network=100 dnsServers=[211.138.21.66, 211.138.23.66]
2024-07-30T16:34:07.098 - [IPv6TetheringCoordinator] setUpstreamNetworkState: UpstreamNetworkState{null}
2024-07-30T16:34:07.100 - TetherModeAliveState got EVENT_UPSTREAM_CALLBACK
2024-07-30T16:34:07.104 - Looking for default routes on: {InterfaceName: usb0 LinkAddresses: [ 10.202.135.102/8 ] DnsAddresses: [ /211.138.21.66,/211.138.23.66 ] PcscfAddresses: [ /0.0.0.0 ] Domains: null MTU: 1500 TcpBufferSizes: 524288,1048576,2097152,262144,524288,1048576 Routes: [ 0.0.0.0/0 -> 10.202.135.153 usb0 mtu 0,10.0.0.0/8 -> 0.0.0.0 usb0 mtu 0 ]}
2024-07-30T16:34:07.104 - Found upstream interface(s): [usb0]
2024-07-30T16:34:07.106 - SET DNS forwarders: network=100 dnsServers=[211.138.21.66, 211.138.23.66]
2024-07-30T16:34:07.106 - [IPv6TetheringCoordinator] setUpstreamNetworkState: UpstreamNetworkState{null}
2024-07-30T16:34:07.107 - TetherModeAliveState got EVENT_UPSTREAM_CALLBACK
2024-07-30T16:34:07.107 - TetherModeAliveState got CMD_UPSTREAM_CHANGED
2024-07-30T16:34:07.110 - Looking for default routes on: {InterfaceName: usb0 LinkAddresses: [ 10.202.135.102/8 ] DnsAddresses: [ /211.138.21.66,/211.138.23.66 ] PcscfAddresses: [ /0.0.0.0 ] Domains: null MTU: 1500 TcpBufferSizes: 524288,1048576,2097152,262144,524288,1048576 Routes: [ 0.0.0.0/0 -> 10.202.135.153 usb0 mtu 0,10.0.0.0/8 -> 0.0.0.0 usb0 mtu 0 ]}
2024-07-30T16:34:07.111 - Found upstream interface(s): [usb0]
2024-07-30T16:34:07.112 - SET DNS forwarders: network=100 dnsServers=[211.138.21.66, 211.138.23.66]
2024-07-30T16:34:07.113 - [IPv6TetheringCoordinator] setUpstreamNetworkState: UpstreamNetworkState{null}
2024-07-30T16:34:07.113 - TetherModeAliveState got EVENT_IFACE_UPDATE_LINKPROPERTIES
2024-07-30T16:34:07.113 - [eth0] TetheredState got CMD_TETHER_CONNECTION_CHANGED
2024-07-30T16:34:07.113 - [eth0] TetheredState got CMD_TETHER_CONNECTION_CHANGED
2024-07-30T16:34:07.121 - [eth0] TetheredState got CMD_IPV6_TETHER_UPDATE
2024-07-30T16:34:07.121 - OBSERVED LinkProperties update iface=eth0 state=TETHERED lp={InterfaceName: eth0 LinkAddresses: [ 192.168.7.85/24 ] DnsAddresses: [ ] Domains: null MTU: 0 Routes: [ 192.168.7.0/24 -> 0.0.0.0 eth0 mtu 0 ]}
2024-07-30T16:34:07.121 - [eth0] TetheredState got CMD_TETHER_CONNECTION_CHANGED
2024-07-30T16:34:07.121 - [eth0] TetheredState got CMD_TETHER_CONNECTION_CHANGED
2024-07-30T16:34:07.121 - [eth0] TetheredState got CMD_IPV6_TETHER_UPDATE
2024-07-30T16:34:07.121 - OBSERVED LinkProperties update iface=eth0 state=TETHERED lp={InterfaceName: eth0 LinkAddresses: [ 192.168.7.85/24 ] DnsAddresses: [ ] Domains: null MTU: 0 Routes: [ 192.168.7.0/24 -> 0.0.0.0 eth0 mtu 0 ]}
2024-07-30T16:34:07.121 - [eth0] TetheredState got CMD_TETHER_CONNECTION_CHANGED
2024-07-30T16:34:07.122 - [eth0] TetheredState got CMD_TETHER_CONNECTION_CHANGED
2024-07-30T16:34:07.122 - [eth0] TetheredState got CMD_IPV6_TETHER_UPDATE
2024-07-30T16:34:07.122 - OBSERVED LinkProperties update iface=eth0 state=TETHERED lp={InterfaceName: eth0 LinkAddresses: [ 192.168.7.85/24 ] DnsAddresses: [ ] Domains: null MTU: 0 Routes: [ 192.168.7.0/24 -> 0.0.0.0 eth0 mtu 0 ]}
2024-07-30T16:34:07.122 - TetherModeAliveState got EVENT_IFACE_UPDATE_LINKPROPERTIES
2024-07-30T16:34:07.122 - TetherModeAliveState got EVENT_IFACE_UPDATE_LINKPROPERTIES
2024-07-30T16:34:07.122 - TetherModeAliveState got EVENT_IFACE_UPDATE_LINKPROPERTIES
2024-07-30T16:34:16.564 - [eth0] TetheredState got CMD_NEIGHBOR_EVENT
2024-07-30T16:34:16.564 - [eth0] TetheredState got CMD_NEIGHBOR_EVENT
2024-07-30T16:34:16.564 - [eth0] TetheredState got CMD_NEIGHBOR_EVENT
2024-07-30T16:34:16.565 - [eth0] TetheredState got CMD_NEIGHBOR_EVENT
2024-07-30T16:34:16.565 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:34:16.565 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
2024-07-30T16:34:26.591 - [eth0] TetheredState got CMD_NEIGHBOR_EVENT
2024-07-30T16:34:26.592 - [eth0] TetheredState got CMD_NEIGHBOR_EVENT
2024-07-30T16:34:26.592 - [usb0] InitialState got CMD_NEIGHBOR_EVENT
路由表对比
网络共享之前
rk3399_Android11:/ $ ip route
default via 10.114.189.125 dev usb0
10.0.0.0/8 dev usb0 proto kernel scope link src 10.114.189.130
网络共享之后
rk3399_Android11:/ $ ip route
default via 10.114.189.125 dev usb0
10.0.0.0/8 dev usb0 proto kernel scope link src 10.114.189.130
192.168.143.0/24 dev eth0 proto kernel scope link src 192.168.143.79
dumpsys ethernet
rk3399_Android11:/ $ dumpsys ethernet
Current Ethernet state:
EthernetTracker
Ethernet interface name filter: eth\d
Default interface: eth0
Default interface mode: 2
Tethered interface requests: 1
Listeners: 1
IP Configurations:
Network Capabilities:
{Ethernet - providerId=1, ScoreFilter=70, Filter=[ AdministratorUids: [] RequestorUid: -1 RequestorPackageName: null], requests=10, refCount=0}
{NetworkRequest [ REQUEST id=1, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN AdministratorUids: [] RequestorUid: 1000 RequestorPackageName: android] ], score=50, requested=false}
{NetworkRequest [ BACKGROUND_REQUEST id=2, [ Transports: CELLULAR Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN AdministratorUids: [] RequestorUid: 1000 RequestorPackageName: android] ], score=50, requested=false}
{NetworkRequest [ TRACK_DEFAULT id=9, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED Uid: 1000 AdministratorUids: [] RequestorUid: 1000 RequestorPackageName: android] ], score=50, requested=false}
{NetworkRequest [ TRACK_DEFAULT id=10, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED Uid: 1073 AdministratorUids: [] RequestorUid: 1073 RequestorPackageName: com.android.networkstack] ], score=50, requested=false}
{NetworkRequest [ REQUEST id=12, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN AdministratorUids: [] RequestorUid: 1073 RequestorPackageName: com.android.networkstack] ], score=50, requested=false}
{NetworkRequest [ TRACK_DEFAULT id=15, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED Uid: 10045 AdministratorUids: [] RequestorUid: 10045 RequestorPackageName: com.android.systemui] ], score=50, requested=false}
{NetworkRequest [ TRACK_DEFAULT id=16, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED Uid: 10045 AdministratorUids: [] RequestorUid: 10045 RequestorPackageName: com.android.systemui] ], score=50, requested=false}
{NetworkRequest [ REQUEST id=19, [ Capabilities: NOT_RESTRICTED&TRUSTED&NOT_VPN Uid: 1000 AdministratorUids: [] RequestorUid: 1000 RequestorPackageName: com.wif.baseservice] ], score=50, requested=false}
{NetworkRequest [ TRACK_DEFAULT id=21, [ Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED Uid: 1000 AdministratorUids: [] RequestorUid: 1000 RequestorPackageName: com.wif.baseservice] ], score=50, requested=false}
{NetworkRequest [ REQUEST id=35, legacyType=5, [ Transports: CELLULAR Capabilities: INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VPN Uid: 1073 AdministratorUids: [] RequestorUid: 1073 RequestorPackageName: com.android.networkstack] ], score=50, requested=false}
EthernetNetworkFactory
Tracking interfaces:
Handler:
EthernetServiceImplHandler (android.os.Handler) {fa3ce65} @ 700468
EthernetServiceImpl Looper (EthernetServiceThread, tid 106) {8bfd73a}
EthernetServiceImpl (Total messages: 0, polling=true, quitting=false)
IP 地址分配
如何修改4G 共享到以太网的IP网段
frameworks/base/packages/Tethering/src/android/net/ip/IpServer.java
public class IpServer extends StateMachine {
// TODO: have PanService use some visible version of this constant
private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1/24";
// lixiaogang add start
private static final String ETHETNET_IFACE_ADDR = "192.168.43.1/24";
// lixiaogang add end
private LinkAddress requestIpv4Address() {
if (mStaticIpv4ServerAddr != null) return mStaticIpv4ServerAddr;
if (mInterfaceType == TetheringManager.TETHERING_BLUETOOTH) {
return new LinkAddress(BLUETOOTH_IFACE_ADDR);
}
// lixiaogang add start
if (mInterfaceType == TetheringManager.TETHERING_ETHERNET) {
String ethIfaceAddr = SystemProperties.get("persist.net.eth_iface_addr", ETHETNET_IFACE_ADDR);
if (!TextUtils.isEmpty(ethIfaceAddr)) {
return new LinkAddress(ethIfaceAddr);
}
}
// lixiaogang add end
return mPrivateAddressCoordinator.requestDownstreamAddress(this);
}
}
frameworks/base/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java
public class PrivateAddressCoordinator {
/**
* Pick a random available address and mark its prefix as in use for the provided IpServer,
* returns null if there is no available address.
*/
@Nullable
public LinkAddress requestDownstreamAddress(final IpServer ipServer) {
maybeRemoveDeprectedUpstreams();
// Address would be 192.168.[subAddress]/24.
final byte[] bytes = mTetheringPrefix.getRawAddress();
final int subAddress = getRandomSubAddr(); // 随机生成
final int subNet = (subAddress >> 8) & BYTE_MASK;
bytes[3] = getSanitizedAddressSuffix(subAddress, (byte) 0, (byte) 1, (byte) 0xff);
for (int i = 0; i < MAX_UBYTE; i++) {
final int newSubNet = (subNet + i) & BYTE_MASK;
if (newSubNet == BLUETOOTH_RESERVED) continue;
bytes[2] = (byte) newSubNet;
final InetAddress addr;
try {
addr = InetAddress.getByAddress(bytes);
} catch (UnknownHostException e) {
throw new IllegalStateException("Invalid address, shouldn't happen.", e);
}
final IpPrefix prefix = new IpPrefix(addr, PREFIX_LENGTH);
// Check whether this prefix is in use.
if (isDownstreamPrefixInUse(prefix)) continue;
// Check whether this prefix is conflict with any current upstream network.
if (isConflictWithUpstream(prefix)) continue;
mDownstreams.add(ipServer);
return new LinkAddress(addr, PREFIX_LENGTH);
}
// No available address.
return null;
}
/** Get random sub address value. Return value is in 0 ~ 0xffff. */
@VisibleForTesting
public int getRandomSubAddr() {
return ((new Random()).nextInt()) & 0xffff; // subNet is in 0 ~ 0xffff.
}
}