国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Android 11 Ethernet以太網(wǎng)架構(gòu)分析(1)——初始化

這篇具有很好參考價值的文章主要介紹了Android 11 Ethernet以太網(wǎng)架構(gòu)分析(1)——初始化。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

概要

android中以太網(wǎng)常被用作共享網(wǎng)絡(luò),或者是定制化設(shè)備連接網(wǎng)線的需求。
本章將會詳細(xì)分析該模塊對以太網(wǎng)的邏輯實現(xiàn),是大家對此有更深入認(rèn)識。

整體架構(gòu)流程

初始化

Systemserver

在安卓系統(tǒng)中有一個關(guān)于以太網(wǎng)的服務(wù),在systemserver中啟動
frameworks/base/services/java/com/android/server/SystemServer.java

            if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
                    mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
                t.traceBegin("StartEthernet");
                mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
                t.traceEnd();
            }
EthernetService

這個EthernetService類的內(nèi)容很少,重點主要看他這里初始化了EthernetServiceImpl這個類然后調(diào)用其start方法
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetService.java

public final class EthernetService extends SystemService {

    private static final String TAG = "EthernetService";
    final EthernetServiceImpl mImpl;

    public EthernetService(Context context) {
        super(context);
        mImpl = new EthernetServiceImpl(context);
    }

    @Override
    public void onStart() {
        Log.i(TAG, "Registering service " + Context.ETHERNET_SERVICE);
        publishBinderService(Context.ETHERNET_SERVICE, mImpl);
    }

    @Override
    public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
            mImpl.start();
        }
    }
}
EthernetServiceImpl

frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetServiceImpl.java

public class EthernetServiceImpl extends IEthernetManager.Stub {

首先可以看出他繼承了IEthernetManager接口,應(yīng)該是系統(tǒng)api的服務(wù)實現(xiàn)類

繼續(xù)看他的start方法
創(chuàng)建了一個handler但也只是作為入?yún)魅氲紼thernetTracker構(gòu)造中,之后在啟動EthernetTracker這個類
猜測EthernetTracker還有更重要的地方,繼續(xù)追蹤其啟動

    public void start() {
        Log.i(TAG, "Starting Ethernet service");

        HandlerThread handlerThread = new HandlerThread("EthernetServiceThread");
        handlerThread.start();
        mHandler = new Handler(handlerThread.getLooper());

        mTracker = new EthernetTracker(mContext, mHandler);
        mTracker.start();

        mStarted.set(true);
    }
EthernetTracker

frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java
構(gòu)造方法

    EthernetTracker(Context context, Handler handler) {
        mContext = context;
        mHandler = handler;

        // The services we use.
        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); //獲取了網(wǎng)絡(luò)管理的服務(wù),這個服務(wù)是直接和netd進(jìn)行交互的
        mNMService = INetworkManagementService.Stub.asInterface(b);

        // Interface match regex.
        updateIfaceMatchRegexp(); //更新以太網(wǎng)卡篩選規(guī)則,通常是‘eth\\d’

        // Read default Ethernet interface configuration from resources
        final String[] interfaceConfigs = context.getResources().getStringArray(
                com.android.internal.R.array.config_ethernet_interfaces);
        for (String strConfig : interfaceConfigs) {
            parseEthernetConfig(strConfig);//從資源文件中獲取并解析默認(rèn)的以太網(wǎng)絡(luò)配置 (1)
        }

        mConfigStore = new EthernetConfigStore();//初始化網(wǎng)絡(luò)配置類

        NetworkCapabilities nc = createNetworkCapabilities(true /* clear default capabilities */);//(2)
        mFactory = new EthernetNetworkFactory(handler, context, nc);
        mFactory.register();//(3)重點是這個mFactory,我們后續(xù)講道,知道是在這里初始化的
    }

parseEthernetConfig的這個解析系統(tǒng)的xml文件,然后讀到該類的對象數(shù)組中,具體格式如下

    <string-array translatable="false" name="config_ethernet_interfaces">
        
        <item>eth1;12,13,14,15;ip=192.168.0.10/24 gateway=192.168.0.1 dns=4.4.4.4,8.8.8.8</item>
        <item>eth2;;ip=192.168.0.11/24</item>
        <item>eth3;12,13,14,15;ip=192.168.0.12/24;1</item>
       
    </string-array>

createNetworkCapabilities是分析網(wǎng)絡(luò)功能的靜態(tài)列表作用,傳入?yún)?shù)true代表清除緩存
該方法作用主要是指定當(dāng)前網(wǎng)絡(luò)的一個能力和一些相關(guān)參數(shù)的初始化

start方法

    void start() {
        mConfigStore.read();

        // Default interface is just the first one we want to track.
        mIpConfigForDefaultInterface = mConfigStore.getIpConfigurationForDefaultInterface();
        final ArrayMap<String, IpConfiguration> configs = mConfigStore.getIpConfigurations();
        for (int i = 0; i < configs.size(); i++) {
            mIpConfigurations.put(configs.keyAt(i), configs.valueAt(i));
        }

        try {
            mNMService.registerObserver(new InterfaceObserver());
        } catch (RemoteException e) {
            Log.e(TAG, "Could not register InterfaceObserver " + e);
        }

        mHandler.post(this::trackAvailableInterfaces);
    }

mConfigStore會去讀/misc/ethernet/ipconfig.txt這個下面的網(wǎng)絡(luò)配置,如果用戶沒有指定,那這塊就為空
registerObserver(new InterfaceObserver())主要是監(jiān)聽down up remove add這幾個狀態(tài)然后做對應(yīng)的處理

    private class InterfaceObserver extends BaseNetworkObserver {

        @Override
        public void interfaceLinkStateChanged(String iface, boolean up) {
            if (DBG) {
                Log.i(TAG, "interfaceLinkStateChanged, iface: " + iface + ", up: " + up);
            }
            mHandler.post(() -> updateInterfaceState(iface, up));
        }

        @Override
        public void interfaceAdded(String iface) {
            mHandler.post(() -> maybeTrackInterface(iface));
        }

        @Override
        public void interfaceRemoved(String iface) {
            mHandler.post(() -> stopTrackingInterface(iface));
        }
    }

最后執(zhí)行trackAvailableInterfaces這個方法

    private void trackAvailableInterfaces() {
        try {
            final String[] ifaces = mNMService.listInterfaces(); //遍歷當(dāng)前網(wǎng)卡接口,返回字符數(shù)組
            for (String iface : ifaces) {
                maybeTrackInterface(iface);//挨個做處理
            }
        } catch (RemoteException | IllegalStateException e) {
            Log.e(TAG, "Could not get list of interfaces " + e);
        }
    }

繼續(xù)看maybeTrackInterface這個方法

    private void maybeTrackInterface(String iface) {
        if (!iface.matches(mIfaceMatch)) { //如果與設(shè)定的網(wǎng)卡名格式不匹配直接返回,例如eth0\eth1可以
            return;
        }

        // If we don't already track this interface, and if this interface matches
        // our regex, start tracking it.
        if (mFactory.hasInterface(iface) || iface.equals(mDefaultInterface)) { //如果當(dāng)前初始化過了該網(wǎng)卡直接返回
            if (DBG) Log.w(TAG, "Ignoring already-tracked interface " + iface);
            return;
        }
        if (DBG) Log.i(TAG, "maybeTrackInterface: " + iface);

        Intent intent = new Intent("android.net.action.ETH_DEVICE_ENABLED");
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        Log.e(TAG, "Send broadcast: ETH_DEVICE_ENABLED");
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL);//發(fā)送廣播,以太網(wǎng)設(shè)備可用

        // TODO: avoid making an interface default if it has configured NetworkCapabilities.
        //如果已配置NetworkCapabilities,請避免將接口設(shè)為默認(rèn)接口。
        if (mDefaultInterface == null) {
            mDefaultInterface = iface;
        }

        if (mIpConfigForDefaultInterface != null) { //第一次時這塊還是空的 所以沒走這
            updateIpConfiguration(iface, mIpConfigForDefaultInterface);
            mIpConfigForDefaultInterface = null;
        }

        addInterface(iface);//執(zhí)行下一步的方法
    }

addInterface

    private void addInterface(String iface) {
        InterfaceConfiguration config = null;
        // Bring up the interface so we get link status indications.
        try {
            mNMService.setInterfaceUp(iface);//先告訴netd加載上這個網(wǎng)卡并且獲取配置
            config = mNMService.getInterfaceConfig(iface);
        } catch (RemoteException | 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 for " + iface + ". Bailing out.");
            return;
        }

        final String hwAddress = config.getHardwareAddress();

        NetworkCapabilities nc = mNetworkCapabilities.get(iface);//測試相關(guān),先不管
        if (nc == null) {
            // Try to resolve using mac address
            nc = mNetworkCapabilities.get(hwAddress);
            if (nc == null) {
                final boolean isTestIface = iface.matches(TEST_IFACE_REGEXP);
                nc = createDefaultNetworkCapabilities(isTestIface);
            }
        }

        final int mode = getInterfaceMode(iface);//設(shè)置該網(wǎng)卡的這個模式,是客戶端還是服務(wù)端
        if (mode == INTERFACE_MODE_CLIENT) {//一般都會走到這
            IpConfiguration ipConfiguration = mIpConfigurations.get(iface);
            if (ipConfiguration == null) {
                ipConfiguration = createDefaultIpConfiguration();//創(chuàng)建一個默認(rèn)的數(shù)據(jù)對象
            }

            Log.d(TAG, "Tracking interface in client mode: " + iface);
            mFactory.addInterface(iface, hwAddress, nc, ipConfiguration);//繼續(xù)調(diào)用該工廠類中的方法
        } else {
            maybeUpdateServerModeInterfaceState(iface, true);
        }

        // Note: if the interface already has link (e.g., if we crashed and got
        // restarted while it was running), we need to fake a link up notification so we
        // start configuring it.
        if (config.hasFlag("running")) {
            updateInterfaceState(iface, true);最后更新狀態(tài)
        }
    }
EthernetNetworkFactory

frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java
是時候看這個類了,之前在EthernetTracker的構(gòu)造方法中就有他,現(xiàn)在我們來看
因為EthernetNetworkFactory注冊了NetworkFactory 但是在子類并沒有register方法,所以調(diào)的都是他父類的

public class EthernetNetworkFactory extends NetworkFactory {

來看其父類的注冊方法都做了什么
frameworks/libs/net/common/src_servicescommon/android/net/NetworkFactory.java

    public void register() { //向系統(tǒng)注冊此NetworkFactory。每個工廠只能調(diào)用一次
        if (mProvider != null) {
            throw new IllegalStateException("A NetworkFactory must only be registered once");
        }
        if (DBG) log("Registering NetworkFactory");

        mProvider = new NetworkProvider(mContext, NetworkFactory.this.getLooper(), LOG_TAG) {
            @Override
            public void onNetworkRequested(@NonNull NetworkRequest request, int score,//不同的網(wǎng)絡(luò)請求回調(diào)
                    int servingProviderId) {
                handleAddRequest(request, score, servingProviderId);
            }

            @Override
            public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {//網(wǎng)絡(luò)請求撤回
                handleRemoveRequest(request);
            }
        };

        ((ConnectivityManager) mContext.getSystemService(
            Context.CONNECTIVITY_SERVICE)).registerNetworkProvider(mProvider);//向connectivityService注冊改回調(diào)函數(shù),也就是和CONNECTIVITY_SERVICE進(jìn)行交互
    }

所以上層fw的CONNECTIVITY_SERVICE服務(wù)到ethernet服務(wù)再到nmms(netd)服務(wù)之間的鏈路是這樣來的
繼續(xù)看EthernetNetworkFactory的構(gòu)造方法

    public EthernetNetworkFactory(Handler handler, Context context, NetworkCapabilities filter) {
        super(handler.getLooper(), context, NETWORK_TYPE, filter);

        mHandler = handler;
        mContext = context;

        setScoreFilter(NETWORK_SCORE); //主要是設(shè)置分?jǐn)?shù),以太網(wǎng)的分?jǐn)?shù)大于為wifi大于mobile
    }

回到初始化中的addInterface方法

        void addInterface(String ifaceName, String hwAddress, NetworkCapabilities capabilities,
             IpConfiguration ipConfiguration) {
        if (mTrackingInterfaces.containsKey(ifaceName)) {//如果當(dāng)前打開的列表里有了,直接返回
            Log.e(TAG, "Interface with name " + ifaceName + " already exists.");
            return;
        }

        if (DBG) {
            Log.d(TAG, "addInterface, iface: " + ifaceName + ", capabilities: " + capabilities);
        }

        NetworkInterfaceState iface = new NetworkInterfaceState(//這個NetworkInterfaceState是個內(nèi)部類
                ifaceName, hwAddress, mHandler, mContext, capabilities, this);
        iface.setIpConfig(ipConfiguration);//設(shè)置ip地址,等參數(shù)
        mTrackingInterfaces.put(ifaceName, iface);//放進(jìn)容器內(nèi)保存

        updateCapabilityFilter();//更新
    }

繼續(xù)看

    private void updateCapabilityFilter() {
        NetworkCapabilities capabilitiesFilter = new NetworkCapabilities();
        capabilitiesFilter.clearAll();//清空

        for (NetworkInterfaceState iface:  mTrackingInterfaces.values()) {
            capabilitiesFilter.combineCapabilities(iface.mCapabilities);//根據(jù)現(xiàn)有打開的網(wǎng)卡初始化NetworkCapabilities對象
        }

        if (DBG) Log.d(TAG, "updateCapabilityFilter: " + capabilitiesFilter);
        setCapabilityFilter(capabilitiesFilter);//調(diào)用父類方法,第一次初始化不會執(zhí)行具體的邏輯
    }

執(zhí)行完這些之后,就可以回到EthernetTracker繼續(xù)執(zhí)行updateInterfaceState方法
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java

    private void updateInterfaceState(String iface, boolean up) {
        final int mode = getInterfaceMode(iface);
        final boolean factoryLinkStateUpdated = (mode == INTERFACE_MODE_CLIENT) //true
                && mFactory.updateInterfaceLinkState(iface, up);
                //調(diào)用EthernetNetworkFactory里邊的updateInterfaceLinkState

        if (factoryLinkStateUpdated) { 
        //*如果給定接口被配置為受限(不具有NET_CAPABILITY_NOT_RESTRICED)功能,則返回true。否則,返回false。
            boolean restricted = isRestrictedInterface(iface);
            int n = mListeners.beginBroadcast();//開始廣播
            for (int i = 0; i < n; i++) {
                try {
                    if (restricted) {
                        ListenerInfo listenerInfo = (ListenerInfo) mListeners.getBroadcastCookie(i);
                        if (!listenerInfo.canUseRestrictedNetworks) {
                            continue;
                        }
                    }
                    mListeners.getBroadcastItem(i).onAvailabilityChanged(iface, up);//執(zhí)行網(wǎng)卡可用回調(diào)
                } catch (RemoteException e) {
                    // Do nothing here.
                }
            }
            mListeners.finishBroadcast();
        }
    }

前面會執(zhí)行這里的updateInterfaceLinkState
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java

    /** Returns true if state has been modified */
    boolean updateInterfaceLinkState(String ifaceName, boolean up) {
        if (!mTrackingInterfaces.containsKey(ifaceName)) {//前面執(zhí)行addInterface添加的,如果沒有返回false,沒有更新
            return false;
        }

        if (DBG) {
            Log.d(TAG, "updateInterfaceLinkState, iface: " + ifaceName + ", up: " + up);
        }

        NetworkInterfaceState iface = mTrackingInterfaces.get(ifaceName);
        return iface.updateLinkState(up);//執(zhí)行內(nèi)部類方法
    }
        /** Returns true if state has been modified */
        boolean updateLinkState(boolean up) {
            if (mLinkUp == up) return false; //不同狀態(tài)才會執(zhí)行
            mLinkUp = up;

            stop(); // (1)
            if (up) {
                start(); //(2)
            }

            return true;
        }

sotp() 就是把各種變量和狀態(tài)清空

        void stop() {
            // Invalidate all previous start requests
            if (mIpClient != null) {
                shutdownIpClient(mIpClient);
                mIpClientCallback.awaitIpClientShutdown();
                mIpClient = null;
            }
            mIpClientCallback = null;

            if (mNetworkAgent != null) {
                mNetworkAgent.unregister();
                mNetworkAgent = null;
            }
            mLinkProperties.clear();
        }

IpClient下面有解釋
start() 開始執(zhí)行初始化網(wǎng)卡邏輯

        private void start() {
            if (mIpClient != null) {
                if (DBG) Log.d(TAG, "IpClient already started"); //之前已經(jīng)初始化了就返回
                return;
            }
            if (DBG) {
                Log.d(TAG, String.format("Starting Ethernet IpClient(%s)", name));
            }

            mIpClientCallback = new IpClientCallbacksImpl();//與IpClient通信的回調(diào)
            IpClientUtil.makeIpClient(mContext, name, mIpClientCallback);
            mIpClientCallback.awaitIpClientStart(); //等待IpClient開啟
            if (sTcpBufferSizes == null) {//緩存設(shè)置
                sTcpBufferSizes = mContext.getResources().getString(
                        com.android.internal.R.string.config_ethernet_tcp_buffers);
            }
            provisionIpClient(mIpClient, mIpConfig, sTcpBufferSizes);//設(shè)置各種網(wǎng)絡(luò)參數(shù)
        }

provisionIpClient這個方法主要是進(jìn)行網(wǎng)絡(luò)具體參數(shù)的一些設(shè)置,但要依靠IpClient

        private static void provisionIpClient(IIpClient ipClient, IpConfiguration config,
                String tcpBufferSizes) {
            if (config.getProxySettings() == ProxySettings.STATIC ||
                    config.getProxySettings() == ProxySettings.PAC) {
                try {
                    ipClient.setHttpProxy(toStableParcelable(config.getHttpProxy()));//設(shè)置代理根據(jù)入?yún)onfig中的參數(shù)
                } catch (RemoteException e) {
                    e.rethrowFromSystemServer();
                }
            }

            if (!TextUtils.isEmpty(tcpBufferSizes)) {
                try {
                    ipClient.setTcpBufferSizes(tcpBufferSizes);//不為空就設(shè)置
                } catch (RemoteException e) {
                    e.rethrowFromSystemServer();
                }
            }

            final ProvisioningConfiguration provisioningConfiguration;
            if (config.getIpAssignment() == IpAssignment.STATIC) {  //靜態(tài)ip就設(shè)置咱們自己指定的
                provisioningConfiguration = new ProvisioningConfiguration.Builder()
                        .withStaticConfiguration(config.getStaticIpConfiguration())
                        .build();
            } else {
                provisioningConfiguration = new ProvisioningConfiguration.Builder()//動態(tài)ip就由系統(tǒng)自動生成
                        .withProvisioningTimeoutMs(0)
                        .build();
            }

            try {
                ipClient.startProvisioning(provisioningConfiguration.toStableParcelable());//最后調(diào)用IpClient開始設(shè)置
            } catch (RemoteException e) {
                e.rethrowFromSystemServer();
            }
        }
IpClientManager

frameworks/base/services/net/java/android/net/ip/IpClientManager.java

    /**
     * Start provisioning with the provided parameters.
     */
    public boolean startProvisioning(ProvisioningConfiguration prov) {
        final long token = Binder.clearCallingIdentity();
        try {
            mIpClient.startProvisioning(prov.toStableParcelable());
            return true;
        } catch (RemoteException e) {
            log("Error starting IpClient provisioning", e);
            return false;
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

這也不是具體實現(xiàn),繼續(xù)看

IpClient

packages/modules/NetworkStack/src/android/net/ip/IpClient.java

        @Override
        public void startProvisioning(ProvisioningConfigurationParcelable req) {
            enforceNetworkStackCallingPermission();
            IpClient.this.startProvisioning(ProvisioningConfiguration.fromStableParcelable(req));
        }

調(diào)用其內(nèi)部類的方法

    /**
     * Start provisioning with the provided parameters.
     */
    public void startProvisioning(ProvisioningConfiguration req) {
        if (!req.isValid()) {
            doImmediateProvisioningFailure(IpManagerEvent.ERROR_INVALID_PROVISIONING);
            return;
        }

        final ScanResultInfo scanResultInfo = req.mScanResultInfo;
        mCurrentBssid = null;
        if (scanResultInfo != null) {
            try {
                mCurrentBssid = MacAddress.fromString(scanResultInfo.getBssid());//獲取并保存該網(wǎng)絡(luò)的mac地址
            } catch (IllegalArgumentException e) {
                Log.wtf(mTag, "Invalid BSSID: " + scanResultInfo.getBssid()
                        + " in provisioning configuration", e);
            }
        }

        if (req.mLayer2Info != null) {
            mL2Key = req.mLayer2Info.mL2Key;
            mCluster = req.mLayer2Info.mCluster;
        }
        sendMessage(CMD_START, new android.net.shared.ProvisioningConfiguration(req));//發(fā)送msg
    }
                case CMD_START:
                    mConfiguration = (android.net.shared.ProvisioningConfiguration) msg.obj;//保存到本地
                    transitionTo(mClearingIpAddressesState);//轉(zhuǎn)移狀態(tài),
                    break;

mClearingIpAddressesState是ClearingIpAddressesState這個內(nèi)部類new出來的
先進(jìn)入其enter方法

    class ClearingIpAddressesState extends State {
        @Override
        public void enter() {
            // Ensure that interface parameters are fetched on the handler thread so they are
            // properly ordered with other events, such as restoring the interface MTU on teardown.
            mInterfaceParams = mDependencies.getInterfaceParams(mInterfaceName);//在系統(tǒng)中獲取該網(wǎng)卡的硬件參數(shù)
            if (mInterfaceParams == null) { //如果是空,改變成停止?fàn)顟B(tài)直接返回
                logError("Failed to find InterfaceParams for " + mInterfaceName);
                doImmediateProvisioningFailure(IpManagerEvent.ERROR_INTERFACE_NOT_FOUND);
                deferMessage(obtainMessage(CMD_STOP,
                        DisconnectCode.DC_INTERFACE_NOT_FOUND.getNumber()));
                return;
            }

            mLinkObserver.setInterfaceParams(mInterfaceParams);//設(shè)置參數(shù)

            if (readyToProceed()) {//查看是否有ip地址,這是true
                deferMessage(obtainMessage(CMD_ADDRESSES_CLEARED));//發(fā)送:自發(fā)自收
            } else {
                // Clear all IPv4 and IPv6 before proceeding to RunningState.
                // Clean up any leftover state from an abnormal exit from
                // tethering or during an IpClient restart.
                stopAllIP();
            }

            mCallback.setNeighborDiscoveryOffload(true);
        }
    }

發(fā)送CMD_ADDRESSES_CLEARED,看接收端

        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                case CMD_ADDRESSES_CLEARED: //在這處理,改變狀態(tài)。這里分析isUsingPreconnection為false的情況
                    transitionTo(isUsingPreconnection() ? mPreconnectingState : mRunningState);//直接進(jìn)入mRunningState狀態(tài)
                    break;

                case EVENT_NETLINK_LINKPROPERTIES_CHANGED:
                    handleLinkPropertiesUpdate(NO_CALLBACKS);
                    if (readyToProceed()) {
                        transitionTo(isUsingPreconnection() ? mPreconnectingState : mRunningState);
                    }
                    break;

                case CMD_STOP:
                case EVENT_PROVISIONING_TIMEOUT:
                    // Fall through to StartedState.
                    return NOT_HANDLED;

                default:
                    // It's safe to process messages out of order because the
                    // only message that can both
                    //     a) be received at this time and
                    //     b) affect provisioning state
                    // is EVENT_NETLINK_LINKPROPERTIES_CHANGED (handled above).
                    deferMessage(msg);
            }
            return HANDLED;
        }

        private boolean readyToProceed() {
            return !mLinkProperties.hasIpv4Address() && !mLinkProperties.hasGlobalIpv6Address();
        }

看一下RunningState的enter方法

        @Override
        public void enter() {
            ApfFilter.ApfConfiguration apfConfig = new ApfFilter.ApfConfiguration();
            apfConfig.apfCapabilities = mConfiguration.mApfCapabilities;
            apfConfig.multicastFilter = mMulticastFiltering;
            // Get the Configuration for ApfFilter from Context
            apfConfig.ieee802_3Filter = ApfCapabilities.getApfDrop8023Frames();
            apfConfig.ethTypeBlackList = ApfCapabilities.getApfEtherTypeBlackList();
            apfConfig.minRdnssLifetimeSec = mMinRdnssLifetimeSec;
            mApfFilter = ApfFilter.maybeCreate(mContext, apfConfig, mInterfaceParams, mCallback);
            // TODO: investigate the effects of any multicast filtering racing/interfering with the
            // rest of this IP configuration startup.
            if (mApfFilter == null) {
                mCallback.setFallbackMulticastFilter(mMulticastFiltering);
            }

            mPacketTracker = createPacketTracker();
            if (mPacketTracker != null) mPacketTracker.start(mConfiguration.mDisplayName);

            if (mConfiguration.mEnableIPv6 && !startIPv6()) {
                doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV6);
                enqueueJumpToStoppingState(DisconnectCode.DC_ERROR_STARTING_IPV6);
                return;
            }

            if (mConfiguration.mEnableIPv4 && !isUsingPreconnection() && !startIPv4()) {//關(guān)鍵是這個startIPv4方法
                doImmediateProvisioningFailure(IpManagerEvent.ERROR_STARTING_IPV4);
                enqueueJumpToStoppingState(DisconnectCode.DC_ERROR_STARTING_IPV4);
                return;
            }

            final InitialConfiguration config = mConfiguration.mInitialConfig;
            if ((config != null) && !applyInitialConfig(config)) {//應(yīng)用初始化值,沒有就跳過
                // TODO introduce a new IpManagerEvent constant to distinguish this error case.
                doImmediateProvisioningFailure(IpManagerEvent.ERROR_INVALID_PROVISIONING);
                enqueueJumpToStoppingState(DisconnectCode.DC_INVALID_PROVISIONING);
                return;
            }

            if (mConfiguration.mUsingIpReachabilityMonitor && !startIpReachabilityMonitor()) {//默認(rèn)不走這
                doImmediateProvisioningFailure(
                        IpManagerEvent.ERROR_STARTING_IPREACHABILITYMONITOR);
                enqueueJumpToStoppingState(DisconnectCode.DC_ERROR_STARTING_IPREACHABILITYMONITOR);
                return;
            }
        }

來看這個startIPv4()

    private boolean startIPv4() {
        // If we have a StaticIpConfiguration attempt to apply it and
        // handle the result accordingly.
        if (mConfiguration.mStaticIpConfig != null) {//預(yù)先分配的話走這
            if (mInterfaceCtrl.setIPv4Address(mConfiguration.mStaticIpConfig.getIpAddress())) {//繼續(xù)去調(diào)mInterfaceCtrl
            //設(shè)置成功回調(diào)
                handleIPv4Success(new DhcpResults(mConfiguration.mStaticIpConfig));
            } else {
                return false;
            }
        } else {
            if (mDhcpClient != null) {
                Log.wtf(mTag, "DhcpClient should never be non-null in startIPv4()");
            }
            startDhcpClient();
        }

        return true;
    }
InterfaceController

packages/modules/NetworkStack/common/moduleutils/src/android/net/ip/InterfaceController.java

    /**
     * Set the IPv4 address of the interface.
     */
    public boolean setIPv4Address(final LinkAddress address) {
        return setInterfaceConfiguration(address, null);
    }

    /**
     * Set the IPv4 address and also optionally bring the interface up or down.
     */
    public boolean setInterfaceConfiguration(final LinkAddress ipv4Addr,
            final Boolean setIfaceUp) {
        if (!(ipv4Addr.getAddress() instanceof Inet4Address)) {//參數(shù)校驗
            throw new IllegalArgumentException("Invalid or mismatched Inet4Address");
        }
        // Note: currently netd only support INetd#IF_STATE_UP and #IF_STATE_DOWN.
        // Other flags would be ignored.
        
		//參數(shù)包裝,為了跨進(jìn)程傳遞給netd
        final InterfaceConfigurationParcel ifConfig = new InterfaceConfigurationParcel();
        ifConfig.ifName = mIfName;
        ifConfig.ipv4Addr = ipv4Addr.getAddress().getHostAddress();
        ifConfig.prefixLength = ipv4Addr.getPrefixLength();
        // Netd ignores hwaddr in interfaceSetCfg.
        ifConfig.hwAddr = "";
        if (setIfaceUp == null) {//默認(rèn)走這
            // Empty array means no change.
            ifConfig.flags = new String[0];
        } else {
            // Netd ignores any flag that's not IF_STATE_UP or IF_STATE_DOWN in interfaceSetCfg.
            ifConfig.flags = setIfaceUp.booleanValue()
                    ? new String[] {IF_STATE_UP} : new String[] {IF_STATE_DOWN};
        }
        try {
            mNetd.interfaceSetCfg(ifConfig);//接著把參數(shù)給到netd繼續(xù)執(zhí)行就可以了
        } catch (RemoteException | ServiceSpecificException e) {
            logError("Setting IPv4 address to %s/%d failed: %s",
                    ifConfig.ipv4Addr, ifConfig.prefixLength, e);
            return false;
        }
        return true;
    }

別忘了之前還有一個startIPv4()方法內(nèi)還有個handleIPv4Success回調(diào)
packages/modules/NetworkStack/src/android/net/ip/IpClient.java

    private void handleIPv4Success(DhcpResults dhcpResults) {
        mDhcpResults = new DhcpResults(dhcpResults);//填充的分配好的ip地址
        final LinkProperties newLp = assembleLinkProperties();
        final int delta = setLinkProperties(newLp); //更新配置然后返回一個狀態(tài)值,這個狀態(tài)值會通知到其他監(jiān)聽該狀態(tài)改變的類

        if (mDhcpResults.vendorInfo == null && detectUpstreamHotspotFromVendorIe()) {
            mDhcpResults.vendorInfo = DhcpPacket.VENDOR_INFO_ANDROID_METERED;
        }

        if (DBG) {
            Log.d(mTag, "onNewDhcpResults(" + Objects.toString(mDhcpResults) + ")");
            Log.d(mTag, "handleIPv4Success newLp{" + newLp + "}");
        }
        mCallback.onNewDhcpResults(mDhcpResults);//回調(diào)ip參數(shù)
        maybeSaveNetworkToIpMemoryStore();//空的

        dispatchCallback(delta, newLp);//重要是這里
    }
protected final IpClientCallbacksWrapper mCallback;

這個mCallback是IpClientCallbacksWrapper靜態(tài)內(nèi)部類
dispatchCallback開始分發(fā)配置結(jié)果

    private void dispatchCallback(int delta, LinkProperties newLp) {
        switch (delta) {
            case PROV_CHANGE_GAINED_PROVISIONING:
                if (DBG) {
                    Log.d(mTag, "onProvisioningSuccess()");
                }
                recordMetric(IpManagerEvent.PROVISIONING_OK);
                mCallback.onProvisioningSuccess(newLp); //如果正確設(shè)置后會走這
                break;

            case PROV_CHANGE_LOST_PROVISIONING:
                if (DBG) {
                    Log.d(mTag, "onProvisioningFailure()");
                }
                recordMetric(IpManagerEvent.PROVISIONING_FAIL);
                mCallback.onProvisioningFailure(newLp);
                break;

            default:
                if (DBG) {
                    Log.d(mTag, "onLinkPropertiesChange()");
                }
                mCallback.onLinkPropertiesChange(newLp);
                break;
        }
    }
    public static class IpClientCallbacksWrapper {
        private static final String PREFIX = "INVOKE ";
        private final IIpClientCallbacks mCallback;
       //...省略
        /**
         * Indicates that provisioning was successful.
         */
        public void onProvisioningSuccess(LinkProperties newLp) {
            log("onProvisioningSuccess({" + newLp + "})");
            try {
                mCallback.onProvisioningSuccess(mShim.makeSensitiveFieldsParcelingCopy(newLp));
            } catch (RemoteException e) {
                log("Failed to call onProvisioningSuccess", e);
            }
        }

最后則會回調(diào)到EthernetNetworkFactory中
frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java

            @Override
            public void onProvisioningSuccess(LinkProperties newLp) {
                mHandler.post(() -> onIpLayerStarted(newLp));
            }

繼續(xù)調(diào)到這

        void onIpLayerStarted(LinkProperties linkProperties) {
            if (mNetworkAgent != null) {
                Log.e(TAG, "Already have a NetworkAgent - aborting new request");
                stop(); //重復(fù),直接返回
                return;
            }
            mLinkProperties = linkProperties;

            // Create our NetworkAgent.
            final NetworkAgentConfig config = new NetworkAgentConfig.Builder()
                    .setLegacyType(mLegacyType)
                    .setLegacyTypeName(NETWORK_TYPE) //ethernet
                    .build();
            mNetworkAgent = new NetworkAgent(mContext, mHandler.getLooper(), //初始化這個NetworkAgent對象
                    NETWORK_TYPE, mCapabilities, mLinkProperties,
                    getNetworkScore(), config, mNetworkFactory.getProvider()) {
                public void unwanted() {
                    if (this == mNetworkAgent) {
                        stop();
                    } else if (mNetworkAgent != null) {
                        Log.d(TAG, "Ignoring unwanted as we have a more modern " +
                                "instance");
                    }  // Otherwise, we've already called stop.
                }
            };
            mNetworkAgent.register();//注冊到ConnectivityService
            mNetworkAgent.setLegacyExtraInfo(mHwAddress);
            mNetworkAgent.markConnected();  //建立鏈接
        }

參數(shù)申請完了就開始建立網(wǎng)絡(luò)連接了,這一部分將放到下一章來講
上層framework就分析到這,后續(xù)netd的部分如感興趣可以自行了解

技術(shù)名詞解釋

IPClient
  • Android的IpClient是一個用于管理網(wǎng)絡(luò)連接的類。它是Android系統(tǒng)中的一個重要組件,用于處理與網(wǎng)絡(luò)連接相關(guān)的任務(wù)。IpClient負(fù)責(zé)獲取IP地址、配置網(wǎng)絡(luò)接口、處理DHCP請求和響應(yīng)等操作。

  • IpClient使用了DHCP協(xié)議來獲取IP地址。它會通過發(fā)送DHCP請求來與DHCP服務(wù)器進(jìn)行通信,并獲取分配給設(shè)備的IP地址、子網(wǎng)掩碼、網(wǎng)關(guān)和DNS服務(wù)器等信息。一旦獲取到這些信息,IpClient會將其配置到設(shè)備的網(wǎng)絡(luò)接口上,使設(shè)備能夠正常與網(wǎng)絡(luò)進(jìn)行通信。

  • 除了處理DHCP請求和響應(yīng)外,IpClient還負(fù)責(zé)監(jiān)測網(wǎng)絡(luò)連接狀態(tài)的變化。它會監(jiān)聽網(wǎng)絡(luò)狀態(tài)的改變,并在網(wǎng)絡(luò)連接斷開或重新連接時觸發(fā)相應(yīng)的操作。例如,當(dāng)設(shè)備從無線網(wǎng)絡(luò)切換到移動數(shù)據(jù)網(wǎng)絡(luò)時,IpClient會重新獲取IP地址并更新網(wǎng)絡(luò)配置。

  • 總的來說,Android的IpClient是一個用于管理網(wǎng)絡(luò)連接的重要組件,它通過DHCP協(xié)議獲取IP地址并配置網(wǎng)絡(luò)接口,同時監(jiān)測網(wǎng)絡(luò)連接狀態(tài)的變化。這樣可以確保設(shè)備能夠順暢地進(jìn)行網(wǎng)絡(luò)通信。

IpAssignment
  • 在Android中,可以使用IpAssignment枚舉來設(shè)置IP地址分配模式。IpAssignment有以下幾個選項:
  1. STATIC:靜態(tài)IP地址分配模式。在這種模式下,你可以手動指定設(shè)備的IP地址、子網(wǎng)掩碼、網(wǎng)關(guān)和DNS服務(wù)器。
  2. DHCP:動態(tài)主機(jī)配置協(xié)議(DHCP)模式。在這種模式下,設(shè)備會自動通過DHCP服務(wù)器獲取IP地址、子網(wǎng)掩碼、網(wǎng)關(guān)和DNS服務(wù)器。
LinkProperties

這個網(wǎng)絡(luò)鏈接參數(shù)

/**
 * Describes the properties of a network link.
 *
 * A link represents a connection to a network.
 * It may have multiple addresses and multiple gateways,
 * multiple dns servers but only one http proxy and one
 * network interface.
 *
 * Note that this is just a holder of data.  Modifying it
 * does not affect live networks.
 *
 */
public final class LinkProperties implements Parcelable {
    // The interface described by the network link.
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private String mIfaceName;
    private final ArrayList<LinkAddress> mLinkAddresses = new ArrayList<>();
    private final ArrayList<InetAddress> mDnses = new ArrayList<>();
    // PCSCF addresses are addresses of SIP proxies that only exist for the IMS core service.
    private final ArrayList<InetAddress> mPcscfs = new ArrayList<InetAddress>();
    private final ArrayList<InetAddress> mValidatedPrivateDnses = new ArrayList<>();
    private boolean mUsePrivateDns;
    private String mPrivateDnsServerName;
    private String mDomains;
    private ArrayList<RouteInfo> mRoutes = new ArrayList<>();
    private Inet4Address mDhcpServerAddress;
    private ProxyInfo mHttpProxy;
    private int mMtu;
    // in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
    private String mTcpBufferSizes;
    private IpPrefix mNat64Prefix;
    private boolean mWakeOnLanSupported;
    private Uri mCaptivePortalApiUrl;
    private CaptivePortalData mCaptivePortalData;
NetworkAgent

Android NetworkAgent 是一個用于管理網(wǎng)絡(luò)連接的類。它允許應(yīng)用程序在 Android 設(shè)備上監(jiān)控和控制網(wǎng)絡(luò)連接狀態(tài)。NetworkAgent 可以用于創(chuàng)建、配置和管理網(wǎng)絡(luò)連接,并提供與網(wǎng)絡(luò)相關(guān)的信息。

通過 NetworkAgent,應(yīng)用程序可以:

  • 監(jiān)聽網(wǎng)絡(luò)連接狀態(tài)的變化,例如連接建立、斷開和切換連接等。
  • 獲取當(dāng)前活動的網(wǎng)絡(luò)連接的詳細(xì)信息,如網(wǎng)絡(luò)類型、信號強(qiáng)度和 IP 地址等。
  • 請求建立新的網(wǎng)絡(luò)連接或關(guān)閉現(xiàn)有的網(wǎng)絡(luò)連接。
  • 設(shè)置網(wǎng)絡(luò)連接的參數(shù),如代理設(shè)置、數(shù)據(jù)使用限制和網(wǎng)絡(luò)優(yōu)先級等。
  • 使用 NetworkAgent API,開發(fā)人員可以實現(xiàn)更高級的網(wǎng)絡(luò)管理功能,例如在多個網(wǎng)絡(luò)之間自動切換、

小結(jié)

本章分析了安卓以太網(wǎng)這個模塊的初始化流程,后續(xù)會對網(wǎng)卡的開啟,路由的設(shè)置等網(wǎng)絡(luò)策略進(jìn)行分析

謝謝文章來源地址http://www.zghlxwxcb.cn/news/detail-756185.html

到了這里,關(guān)于Android 11 Ethernet以太網(wǎng)架構(gòu)分析(1)——初始化的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包