Android R 网络共享

Tethering

Posted by LXG on July 30, 2024

网络共享-AOSP

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.
    }

}