Android -- 网络模块中NetworkFactory与NetworkAgent的通信机制

Android 9.0 网络评分之--NetworkAgent 一、NetworkAgent 和NetworkFactory的区别 NetworkAgent是被NetworkFactory创建的,这里的创建并不是说在NetworkFactory内部创建 NetworkAgent,而是说,在NetworkFactory这个环境就绪之后,网络提供者才可以创建 NetworkAgent。并且在一个NetworkFactory中可以创建不同的NetworkAgent, 他们拥有不同的Capabilities等参数。 而他们之间还有一个区别就是,NetworkFactory是在系 阅读详情

Android -- NetworkFactory与NetworkAgent的通信机制


在上一篇博文中讲到,EthernetNetworkFactory包揽了Ethernet所有的网络管理操作,这其中就包含怎么样通知ConnectifyService(下文都简称CS)网络状态发生变化。接下来,我们借助有线网络来简要介绍Android 4.4之后,网络模块是怎样与CS通信并进行网络管理的。

在启动Ethernet网络服务时,我们会对Ethernet做一些初始化操作,以方便我们进行网络管理。

看EthernetNetworkFactory::start()方法:
/**
     * Begin monitoring connectivity
     */
    public synchronized void start(Context context, Handler target) {
        // The services we use.
        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
        mNMService = INetworkManagementService.Stub.asInterface(b);
        mEthernetManager = (EthernetManager) context.getSystemService(Context.ETHERNET_SERVICE);

        // Interface match regex.
        mIfaceMatch = context.getResources().getString(
                com.android.internal.R.string.config_ethernet_iface_regex);

        // Create and register our NetworkFactory.
        mFactory = new LocalNetworkFactory(NETWORK_TYPE, context, target.getLooper());
        mFactory.setCapabilityFilter(mNetworkCapabilities);
        mFactory.setScoreFilter(-1); // this set high when we have an iface
        mFactory.register();

        mContext = context;

        // Start tracking interface change events.
        mInterfaceObserver = new InterfaceObserver();
        try {
            mNMService.registerObserver(mInterfaceObserver);
        } catch (RemoteException e) {
            Log.e(TAG, "Could not register InterfaceObserver " + e);
        }

        // If an Ethernet interface is already connected, start tracking that.
        // Otherwise, the first Ethernet interface to appear will be tracked.
        try {
            final String[] ifaces = mNMService.listInterfaces();
            for (String iface : ifaces) {
                synchronized(this) {
                    if (maybeTrackInterface(iface)) {
                        // We have our interface. Track it.
                        // 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. Since we're already holding the lock,
                        // any real link up/down notification will only arrive
                        // after we've done this.
                        if (mNMService.getInterfaceConfig(iface).hasFlag("running")) {
                            updateInterfaceState(iface, true);
                        }
                        break;
                    }
                }
            }
        } catch (RemoteException e) {
            Log.e(TAG, "Could not get list of interfaces " + e);
        }
    }
start()方法接受一个Handler对象作为参数,该参数是在EthernetServiceImpl::start()中传入的,它新建了一个HandlerThread对象,并传入作为参数,从这可知网络管理的操作是运行在EthernetServiceImpl线程中的。

代码中创建了一个LocalNetworkFactory对象。LocalNetworkFactory继承自NetworkFactory:
/**
 * A NetworkFactory is an entity that creates NetworkAgent objects.
 * The bearers register with ConnectivityService using {@link #register} and
 * their factory will start receiving scored NetworkRequests.  NetworkRequests
 * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
 * overridden function.  All of these can be dynamic - changing NetworkCapabilities
 * or score forces re-evaluation of all current requests.
 *
 * If any requests pass the filter some overrideable functions will be called.
 * If the bearer only cares about very simple start/stopNetwork callbacks, those
 * functions can be overridden.  If the bearer needs more interaction, it can
 * override addNetworkRequest and removeNetworkRequest which will give it each
 * request that passes their current filters.
 * @hide
 **/
public class NetworkFactory extends Handler {
...
public NetworkFactory(Looper looper, Context context, String logTag,
            NetworkCapabilities filter) {
        super(looper);
        LOG_TAG = logTag;
        mContext = context;
        mCapabilityFilter = filter;
    }
...
    public void register() {
        if (DBG) log("Registering NetworkFactory");
        if (mMessenger == null) {
            mMessenger = new Messenger(this);
            ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);
        }
    }
...
// override to do simple mode (request independent)
    protected void startNetwork() { }
    protected void stopNetwork() { }
...
}
NetworkFactory继承自Handler,我们可以把它动作一个工厂,对网络的请求和终止操作都通过该对象进行处理。从注释可知NetworkFactory与NetworkAgent对象有密切关系,它通过register()方法向CS进行注册。start/stopNetwork()是提供的回调函数 ,我们可以通过这两个函数来请求或终止网络:
    public void register() {
        if (DBG) log("Registering NetworkFactory");
        if (mMessenger == null) {
            mMessenger = new Messenger(this);
            ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);
        }
    }
创建NetworkFactory对象时,我们给它指定了一个特定线程的Looper对象;接着调用register()方法向CS注册这个NetworkFactory对象,实际是调用CS中的registerNetworkFactory()方法:
    @Override
    public void registerNetworkFactory(Messenger messenger, String name) {
        enforceConnectivityInternalPermission();
        NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
    }
参数Messenger对象是一个可以跨进程传递的实例对象,它实际代表一个Handler对象,我们可以像使用Handler对象一样,使用Messenger对象来发送消息;此处该引用指向mNetworkFactory这个Handler对象,它绑定的Looper属于一个特定的线程,它在EthernetServiceImpl中创建。

看NetworkFactoryInfo,它是一个CS中的内部类,保存了特定的Messager对象和一个与之关联的AsyncChannel对象。看到此处我们知道这里会通过异步通道来进行消息传递的。

接着会发送一个EVENT_REGISTER_NETWORK_FACTORY消息,它被CS中的InternalHandler处理,这个Handler主要完成CS内部消息事件的处理。我们直接看处理过程:
case EVENT_REGISTER_NETWORK_FACTORY: {
                    handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
                    break;
                }
    private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
        if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
        mNetworkFactoryInfos.put(nfi.messenger, nfi);
        nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
    }
异步通道的内容在以前的博文中已经讲过。先将之前创建的nfi对象以Messenger对象为key添加到mNetworkFactoryInfos中,它是一个HashMap对象,方便后面获取。再调用connect()方法进行AsyncChannel连接的创建:
/**
     * Connect handler and messenger.
     *
     * Sends a CMD_CHANNEL_HALF_CONNECTED message to srcHandler when complete.
     *      msg.arg1 = status
     *      msg.obj = the AsyncChannel
     *
     * @param srcContext
     * @param srcHandler
     * @param dstMessenger
     */
    public void connect(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
        if (DBG) log("connect srcHandler to the dstMessenger  E");

        // We are connected
        connected(srcContext, srcHandler, dstMessenger);

        // Tell source we are half connected
        replyHalfConnected(STATUS_SUCCESSFUL);

        if (DBG) log("connect srcHandler to the dstMessenger X");
    }
    /**
     * Connect handler to messenger. This method is typically called
     * when a server receives a CMD_CHANNEL_FULL_CONNECTION request
     * and initializes the internal instance variables to allow communication
     * with the dstMessenger.
     *
     * @param srcContext
     * @param srcHandler
     * @param dstMessenger
     */
    public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
        if (DBG) log("connected srcHandler to the dstMessenger  E");

        // Initialize source fields
        mSrcContext = srcContext;
        mSrcHandler = srcHandler;
        mSrcMessenger = new Messenger(mSrcHandler);

        // Initialize destination fields
        mDstMessenger = dstMessenger;

        if (DBG) log("connected srcHandler to the dstMessenger X");
    }
要明确的是,srcHandler指向CS中的NetworkStateTrackerHandler对象,它主要负责接收网络模块发送的消息,并进行网络更新;mSrcMessenger是代表该Handler对象的一个引用;mDstMessenger则代表EthernetNetworkFactory中的LocalNetworkFactory对象,该对象也是一个Handler。

然后向mSrcHandler回复CMD_CHANNEL_HALF_CONNECTED消息:
 /**
     * Reply to the src handler that we're half connected.
     * see: CMD_CHANNEL_HALF_CONNECTED for message contents
     *
     * @param status to be stored in msg.arg1
     */
    private void replyHalfConnected(int status) {
        Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_HALF_CONNECTED);
        msg.arg1 = status;
        msg.obj = this;
        msg.replyTo = mDstMessenger;

        /*
         * Link to death only when bindService isn't used.
         */
        if (mConnection == null) {
            mDeathMonitor = new DeathMonitor();
            try {
                mDstMessenger.getBinder().linkToDeath(mDeathMonitor, 0);//为了防止AsyncChannel用于不同进程通信时,若Server端所在的进程已经死掉,来通知
                													    //Client端进程进行一些后期处理
            } catch (RemoteException e) {
                mDeathMonitor = null;
                // Override status to indicate failure
                msg.arg1 = STATUS_BINDING_UNSUCCESSFUL;
            }
        }

        mSrcHandler.sendMessage(msg);
    }
CS中是这样处理的:
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
                    handleAsyncChannelHalfConnect(msg);
                    break;
                }
private void handleAsyncChannelHalfConnect(Message msg) {
        AsyncChannel ac = (AsyncChannel) msg.obj;
        if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
            if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                if (VDBG) log("NetworkFactory connected");
                // A network factory has connected.  Send it all current NetworkRequests.
                for (NetworkRequestInfo nri : mNetworkRequests.values()) {
                    if (nri.isRequest == false) continue;
                    NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
                    ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
                            (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
                }
            } else {
                loge("Error connecting NetworkFactory");
                mNetworkFactoryInfos.remove(msg.obj);
            }
        } else if (mNetworkAgentInfos.containsKey(msg.replyTo)) {
            if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                if (VDBG) log("NetworkAgent connected");
                // A network agent has requested a connection.  Establish the connection.
                mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
                        sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
            } else {
                loge("Error connecting NetworkAgent");
                NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);
                if (nai != null) {
                    final boolean wasDefault = isDefaultNetwork(nai);
                    synchronized (mNetworkForNetId) {
                        mNetworkForNetId.remove(nai.network.netId);
                        mNetIdInUse.delete(nai.network.netId);
                    }
                    // Just in case.
                    mLegacyTypeTracker.remove(nai, wasDefault);
                }
            }
        }
    }
我们先前已经向mNetworkFactoryInfos集合添加过NetworkFactoryInfo对象,实际的处理是:
// A network factory has connected.  Send it all current NetworkRequests.
                for (NetworkRequestInfo nri : mNetworkRequests.values()) {
                    if (nri.isRequest == false) continue;
                    NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
                    ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
                            (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
                }
直接看消息发送处理;通过AsyncChannel对象向mDstMessenger对象发送消息。根据前面所述,即向Ethernet中的LocalNetworkFactory发送CMD_REQUEST_NETWORK消息,表示当前系统要请求一个网络。

有前面可知父类NetworkFactory本身就是一个Handler,它处理该消息:
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case CMD_REQUEST_NETWORK: {
                handleAddRequest((NetworkRequest)msg.obj, msg.arg1);
                break;
            }
            case CMD_CANCEL_REQUEST: {
                handleRemoveRequest((NetworkRequest) msg.obj);
                break;
            }
            case CMD_SET_SCORE: {
                handleSetScore(msg.arg1);
                break;
            }
            case CMD_SET_FILTER: {
                handleSetFilter((NetworkCapabilities) msg.obj);
                break;
            }
        }
    }
private void handleAddRequest(NetworkRequest request, int score) {
        NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
        if (n == null) {
            if (DBG) log("got request " + request + " with score " + score);
            n = new NetworkRequestInfo(request, score);
            mNetworkRequests.put(n.request.requestId, n);
        } else {
            if (VDBG) log("new score " + score + " for exisiting request " + request);
            n.score = score;
        }
        if (VDBG) log("  my score=" + mScore + ", my filter=" + mCapabilityFilter);

        evalRequest(n);
    }
private void evalRequest(NetworkRequestInfo n) {
        if (VDBG) log("evalRequest");
        if (n.requested == false && n.score < mScore &&
                n.request.networkCapabilities.satisfiedByNetworkCapabilities(
                mCapabilityFilter) && acceptRequest(n.request, n.score)) {
            if (VDBG) log("  needNetworkFor");
            needNetworkFor(n.request, n.score);
            n.requested = true;
        } else if (n.requested == true &&
                (n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities(
                mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {
            if (VDBG) log("  releaseNetworkFor");
            releaseNetworkFor(n.request);
            n.requested = false;
        } else {
            if (VDBG) log("  done");
        }
    }
如果消息附带的NetworkRequestInfo对象没有保存,则先保存到mNetworkRequests集合中,同时根据NetworkRequestInfo对象中的requested和score属性值,相应的调用needNetworkFor()或releaseNetworkFor():
    // override to do fancier stuff
    protected void needNetworkFor(NetworkRequest networkRequest, int score) {
        if (++mRefCount == 1) startNetwork();
    }

    protected void releaseNetworkFor(NetworkRequest networkRequest) {
        if (--mRefCount == 0) stopNetwork();
    }
即调用LocalNetworkFactory中的start/stopNetwork()来管理网络的开启和关闭:
    private class LocalNetworkFactory extends NetworkFactory {
        LocalNetworkFactory(String name, Context context, Looper looper) {
            super(looper, context, name, new NetworkCapabilities());
        }

        protected void startNetwork() {
            onRequestNetwork();
        }
        protected void stopNetwork() {
        }
    }
onRequestNetwork()处理Ethernet的连接操作,包括对静态IP和DHCP的处理。到这里,一个NetworkFactory对象的注册过程就结束了。

我们看onRequestNetwork()方法来触发一个网络的连接:
    /* Called by the NetworkFactory on the handler thread. */
    public void onRequestNetwork() {
        // TODO: Handle DHCP renew.
        Thread dhcpThread = new Thread(new Runnable() {
            public void run() {
                if (DBG) Log.i(TAG, "dhcpThread(" + mIface + "): mNetworkInfo=" + mNetworkInfo);
                LinkProperties linkProperties;

                IpConfiguration config = mEthernetManager.getConfiguration();

                if (config.getIpAssignment() == IpAssignment.STATIC) {
                    if (!setStaticIpAddress(config.getStaticIpConfiguration())) {
                        // We've already logged an error.
                        return;
                    }
                    linkProperties = config.getStaticIpConfiguration().toLinkProperties(mIface);
                } else {
                    mNetworkInfo.setDetailedState(DetailedState.OBTAINING_IPADDR, null, mHwAddr);

                    DhcpResults dhcpResults = new DhcpResults();
                    // TODO: Handle DHCP renewals better.
                    // In general runDhcp handles DHCP renewals for us, because
                    // the dhcp client stays running, but if the renewal fails,
                    // we will lose our IP address and connectivity without
                    // noticing.
                    if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {
                        Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
                        // set our score lower than any network could go
                        // so we get dropped.
                        mFactory.setScoreFilter(-1);
                        // If DHCP timed out (as opposed to failing), the DHCP client will still be
                        // running, because in M we changed its timeout to infinite. Stop it now.
                        NetworkUtils.stopDhcp(mIface);
                        return;
                    }
                    linkProperties = dhcpResults.toLinkProperties(mIface);
                }
               ...
            }
        });
        dhcpThread.start();
    }
CS中处理网络更新的Handler是NetworkStateTrackerHandler。当网络连接后,通知CS更新网络的操作则是通过NetworkAgent对象进行的。从它的定义可知,它也是一个Handler:
                synchronized(EthernetNetworkFactory.this) {
                    if (mNetworkAgent != null) {
                        Log.e(TAG, "Already have a NetworkAgent - aborting new request");
                        return;
                    }
                    mLinkProperties = linkProperties;
                    mNetworkInfo.setIsAvailable(true);
                    mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);

                    // Create our NetworkAgent.
                    mNetworkAgent = new NetworkAgent(mFactory.getLooper(), mContext,
                            NETWORK_TYPE, mNetworkInfo, mNetworkCapabilities, mLinkProperties,
                            NETWORK_SCORE) {
                        public void unwanted() {
                            synchronized(EthernetNetworkFactory.this) {
                                if (this == mNetworkAgent) {
                                    NetworkUtils.stopDhcp(mIface);

                                    mLinkProperties.clear();
                                    mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null,
                                            mHwAddr);
                                    updateAgent();
                                    mNetworkAgent = null;
                                    try {
                                        mNMService.clearInterfaceAddresses(mIface);
                                    } catch (Exception e) {
                                        Log.e(TAG, "Failed to clear addresses or disable ipv6" + e);
                                    }
                                } else {
                                    Log.d(TAG, "Ignoring unwanted as we have a more modern " +
                                            "instance");
                                }
                            }
                        };
                    };
                }
/**
     * Called when ConnectivityService has indicated they no longer want this network.
     * The parent factory should (previously) have received indication of the change
     * as well, either canceling NetworkRequests or altering their score such that this
     * network won't be immediately requested again.
     */
    abstract protected void unwanted();
重写的unwanted()方法则在CS指出不再需要当前网络连接时调用。除了清除掉网络配置信息,还会把mNetworkAgent置为null。从代码中可以看出,mNetworkAgent是否为null标志了当前是否该类型的网络连接正在使用,如果有则不会处理新的网络请求。

既然网络状态的变化是由NetworkAgent处理的,那我们就接着看NetworkAgent是怎么跟CS通信的:
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
            NetworkCapabilities nc, LinkProperties lp, int score) {
        this(looper, context, logTag, ni, nc, lp, score, null);
    }

    public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
            NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
        super(looper);
        LOG_TAG = logTag;
        mContext = context;
        if (ni == null || nc == null || lp == null) {
            throw new IllegalArgumentException();
        }

        if (VDBG) log("Registering NetworkAgent");
        ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
                Context.CONNECTIVITY_SERVICE);
        netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
                new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
    }
在创建NetworkAgent对象时,接受一个特定的Looper对象,并向CS注册该NetworkAgent对象,这与LocalNetworkFactory的处理类似。看CS中具体的注册处理:
 public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
            LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
            int currentScore, NetworkMisc networkMisc) {
        enforceConnectivityInternalPermission();

        // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network
        // satisfies mDefaultRequest.
        final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
                new Network(reserveNetId()), new NetworkInfo(networkInfo), new LinkProperties(
                linkProperties), new NetworkCapabilities(networkCapabilities), currentScore,
                mContext, mTrackerHandler, new NetworkMisc(networkMisc), mDefaultRequest, this);
        synchronized (this) {
            nai.networkMonitor.systemReady = mSystemReady;
        }
        addValidationLogs(nai.networkMonitor.getValidationLogs(), nai.network);
        if (DBG) log("registerNetworkAgent " + nai);
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
        return nai.network.netId;
    }
这里的Messager对象是NetworkAgent对象自身的一个引用,创建对应的NetworkAgentInfo对象,其内部创建了一个AsyncChannel对象;messenger参数前面介绍过,mTrackderHandler是NetworkStateTrackerHandler的一个实例。

向InternalHandler发送EVENT_REGISTER_NETWORK_AGENT消息,处理注册操作。看CS中的处理:
case EVENT_REGISTER_NETWORK_AGENT: {
                    handleRegisterNetworkAgent((NetworkAgentInfo)msg.obj);
                    break;
                }
private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
        if (VDBG) log("Got NetworkAgent Messenger");
        mNetworkAgentInfos.put(na.messenger, na);
        synchronized (mNetworkForNetId) {
            mNetworkForNetId.put(na.network.netId, na);
        }
        na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
        NetworkInfo networkInfo = na.networkInfo;
        na.networkInfo = null;
        updateNetworkInfo(na, networkInfo);//更新网络状态的函数
    }
也是将na和messenger对象保存到一个HashMap集合中,也是通过AsyncChannel进行通信,也是调用connect()进行连接,这跟前面所述的NetworkFactory的处理基本类似。从前面的分析可知这个AsyncChannel对象中,mSrcHandler和mSrcMessenger指向一个CS中的NetworkStateTrackerHandler,mDstMessenger指向要注册的NetworkAgent对象,因为它本身也是个Handler。

接着向mSrcHandler发送CMD_CHANNEL_HALF_CONNECTED消息,同样也是handleAsyncChannelHalfConnect()处理,只不过走的处理分支不同,有前面的介绍可知:
if (VDBG) log("NetworkAgent connected");
                // A network agent has requested a connection.  Establish the connection.
                mNetworkAgentInfos.get(msg.replyTo).asyncChannel.
                        sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
使用AsyncChannel向mDstMessenger发送CMD_CHANNEL_FULL_CONNECTION消息,即向NetworkAgent对象发送该消息:
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
                if (mAsyncChannel != null) {
                    log("Received new connection while already connected!");
                } else {
                    if (VDBG) log("NetworkAgent fully connected");
                    AsyncChannel ac = new AsyncChannel();
                    ac.connected(null, this, msg.replyTo);
                    ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
                            AsyncChannel.STATUS_SUCCESSFUL);
                    synchronized (mPreConnectedQueue) {
                        mAsyncChannel = ac;
                        for (Message m : mPreConnectedQueue) {
                            ac.sendMessage(m);
                        }
                        mPreConnectedQueue.clear();
                    }
                }
                break;
            }
如果当前NetworkAgent是第一次进行连接,mAsyncChannel为null;新建一个AsyncChannel对象,调用connected()进行FULL_CONNECTION:
public void connected(Context srcContext, Handler srcHandler, Messenger dstMessenger) {
        if (DBG) log("connected srcHandler to the dstMessenger  E");

        // Initialize source fields
        mSrcContext = srcContext;
        mSrcHandler = srcHandler;
        mSrcMessenger = new Messenger(mSrcHandler);

        // Initialize destination fields
        mDstMessenger = dstMessenger;

        if (DBG) log("connected srcHandler to the dstMessenger X");
    }
mSrcHandler和mSrcMessenger指向当前的NetworkAgent对象;mDstMessenger指向CS中的NetworkStateTrackerHandler对象。

随后再发送CMD_CHANNEL_FULLY_CONNECTED消息,表示整个AsyncChannel的连接成功,可以进行通信了。同时,还会遍历mPreConnectedQueue集合,这个集合中保存了当mAsyncChannel为null时的所有与更新网络信息相关的message,通过ac.sendMessage()向CS发送所有的message进行状态更新(要注意,ac对象的mSrcHanlder为当前NetworkAgent,mDstMessenger指向NetworkStateTrackerHandler)。

至此可知,我们通过NetworkAgent向CS报告网络的变化,通知它进行网络状态的更新。EthernetNetworkFactory中通过updateAgent()完成此项工作:
    public void updateAgent() {
        synchronized (EthernetNetworkFactory.this) {
            if (mNetworkAgent == null) return;
            if (DBG) {
                Log.i(TAG, "Updating mNetworkAgent with: " +
                      mNetworkCapabilities + ", " +
                      mNetworkInfo + ", " +
                      mLinkProperties);
            }
            mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
            mNetworkAgent.sendNetworkInfo(mNetworkInfo);
            mNetworkAgent.sendLinkProperties(mLinkProperties);
            // never set the network score below 0.
            mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0);
        }
    }
这里以NetworkInfo的更新为例:
    /**
     * Called by the bearer code when it has new NetworkInfo data.
     */
    public void sendNetworkInfo(NetworkInfo networkInfo) {
        queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
    }
    private void queueOrSendMessage(int what, Object obj) {
        synchronized (mPreConnectedQueue) {
            if (mAsyncChannel != null) {
                mAsyncChannel.sendMessage(what, obj);//mDstMessenger指向CS中的NetworkStateTrackerHandler,mSrcMessenger指向当前NetworkAgent.
            } else {
                Message msg = Message.obtain();
                msg.what = what;
                msg.obj = obj;
                mPreConnectedQueue.add(msg);
            }
        }
    }
 通过已经建立的AsyncChannel连接向ConnectifyService发送消息,并附带需要更新的NetworkInfo对象,这样CS中NetworkStateTrackerHandler就可以收到消息,并进行网络状态更新了。
[Network]Android N Ethernet新IP获取机制—IpManager android N之前 Ethernet旧的ip获取Android N之前,即android 5.0和android 6.0的IP获取机制都是通过/system/bin下面的dhcpcd的bin档去拿的ip,但是android N采用了新的IpManger,自己通过socket去发送dhcp协议 阅读详情

相关推荐

网络连接评分机制之NetworkFactory

*** @hide**/这里的注释介绍了该类的基本作用和注册方法,其开头的部分介绍到,该对象可以用来创建NetworkAgent,而结尾的hide标明该类是隐藏类,也就是说第三方应用无法使用,也就意味着第三方应用是无法承担网络连接的责任。从其继承关系看到,他的本质是一个Handler类。//将当前网络注册到ConnectivityService//处理网络请求,用于打开或者释放当前连接//更新当前网络的分值以上三个是最重要的方法,在接下来的分析中将会多次看到他们的调用。

xiaowang_lj的博客 1245

Android以太网框架情景分析之NetworkFactory与NetworkAgent深入分析

2.4 EthernetNetworkFactory以太网网络管理类   EthernetNetworkFactory类是Ethernet的核心管理类,几乎包含了Ethernet所有的网络管理操作,该类的源码路径为frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java。 2,.4.1 EthernetNetworkFactory.EthernetNetworkFactory   该构造.

IT先森 8167

Android以太网服务启动全解析:从SystemServer到EthernetService的完整链路

本文深入解析了Android系统中以太网服务从SystemServer启动到EthernetService初始化的完整链路。详细阐述了基于硬件特性的条件启动机制、EthernetService与EthernetServiceImpl的分工,以及通过EthernetTracker与ConnectivityService、NetworkManagementService建立通信的关键流程,揭示了Android网络子系统精密的服务协同与异步通信设计。

weixin_28419039的博客 61

Android11 有线网和wifi优先级设置

Android11 有线网和wifi优先级设置 文章目录Android11 有线网和wifi优先级设置一、优先级基本知识介绍系统默认分值:二、有线网络优先级设置1、在Android9.0设置有线网络优先级直接修改EthernetNetworkFactory.java的 NETWORK_SCORE 值就行2、在Android11 修改有线网络优先级三、网络优先级简单刨析1、网络切换的主要逻辑都是在 ConnectivityService.java里面2、优先级评分逻辑主要在evalRequest方法3、要理解

wenzhi的博客 1万+

Android 以太网服务启动流程

Android 以太网服务启动流程 一、引言 阅读本文需要对Android系统的启动流程有一定的了解。如果读者还没有这方面的知识,建议大家先了解一下这方面的知识,鄙人后面也会专门做相关系列文章。这里先大概简单阐述一下(这里我们重点关注init以上的进程服务),方便阅读本文章。Android 在kernel内核启动后会加载启动Init进程,在Init进程中启动各种服务,包括显示系统的SurfaceFlinger,音频系统AudioFlinger,网络守护进程Netd等等,其中最重要一个进程是system_se

franc521的博客 5776

Android 9.0 网络评分之---NetworkFactory

一、网络评分框架图 二、NetworkFactory 与ConnectivityService连接过程 拿以太网为例,以太网的网口检测类EthernetTracker 会在自己的构造函数中将以太网类型的networkfactory 注册到ConnectivityService中。 EthernetTracker(Context context, Handler handler) { mHandler = handler; // The services we use. IBind

秦逸轩的博客 2704

Android -- Ethernet网络模块中NetworkFactory与NetworkAgent的通信机制

在上一篇博文中讲到,EthernetNetworkFactory包揽了Ethernet所有的网络管理操作,这其中就包含怎么样通知ConnectifyService(下文都简称CS)网络状态发生变化。接下来,我们借助有线网络来简要介绍Android 4.4之后,网络模块是怎样与CS通信并进行网络管理的。 在启动Ethernet网络服务时,我们会对Ethernet做一些初始化操作,以

成功不必在我,而功力必不唐捐! 4562

three.js开发3D地图记录(二)

添加地图点击事件,点击区域,地图区域改变颜色并浮起来。

anwebDesigner的博客 1694

Android 7系统网络(一)全景图与调用链路概览

本篇建立了 Android 7 网络子系统的五层全景图(内核 → netd → Framework → NetworkAgent → 应用 API),并跟踪了一条 HTTP 请求在各层之间穿行的完整路径。关键理解:netd 是网络控制的中枢——Framework 层的所有网络策略(防火墙、带宽、路由、DNS)最终都通过 netd 的 Controller 落地为 iptables 规则和路由表条目。理解 netd,就理解了 Android 网络的"操作系统"。

AfinalStone的专栏 373

YOLO11实战:手把手教你优化钢材表面缺陷识别模型(基于NEU-DET数据集)

本文详细介绍了如何使用YOLO11优化钢材表面缺陷识别模型,基于NEU-DET数据集进行实战训练。从数据增强、模型架构优化到训练过程控制,全面解析提升钢材缺陷检测性能的关键技术,特别针对裂纹、划痕等典型缺陷提出针对性解决方案。

weixin_29081163的博客 379

SAP 财务BAPI_ACC_DOCUMENT_POST批导的税务tax

最近遇到了关于SAP财务凭证批导要bapi:BAPI_ACC_DOCUMENT_POST增加税的功能要求,查阅了一众文献发现都不尽如人意,所以想着自己写一个趟过的雷吧。 一般前台sap的凭证是有自动计算税码的勾选框的,但是bapi却并没有这个字段。 实际操作过程中1.可以定义一个税额的结构,参考bapiactx09 2.在会计分录上传如果需要增加税码的时候,譬如总账gl,需要对应tax_code 3.通过CALCULATE_TAX_FROM_GROSSAMOUNT 计算出税额和acct_k...

qq_35640448的博客 3186

Android 11 Ethernet以太网架构分析(1)——初始化

一旦获取到这些信息,IpClient会将其配置到设备的网络接口上,使设备能够正常与网络进行通信。Android的IpClient是一个用于管理网络连接的类。它是Android系统中的一个重要组件,用于处理与网络连接相关的任务。总的来说,Android的IpClient是一个用于管理网络连接的重要组件,它通过DHCP协议获取IP地址并配置网络接口,同时监测网络连接状态的变化。parseEthernetConfig的这个解析系统的xml文件,然后读到该类的对象数组中,具体格式如下。

NEY10MAR的博客 4810

ADS仿真过孔阻抗(via designer)

目录一、将PCB层叠导入ADS(个人习惯)二、过孔的参数化设置三、过孔的仿真四、仿真结果查看五、导出仿真结果和模型六、过孔的经验法则欢迎交流,欢迎转载,转载请注明出处~ 工具:Via Designer Via Designer 调用的是ADS EMPro 仿真引擎,采用的FEM(三维全波有限元法)。 优点: 1、利用ADS已经做好的参数化和流程化的设计,不需要工程师完成过孔的建模这一繁琐的过程。 2、可以输出EMmodule 完成原理图协仿真。 一、将PCB层叠导入ADS(个人习惯) 个人认为在ADS中设置

luohuo9844的博客 1万+

Android系统安全 — 6.2 Ethernet安卓架构

Ethernet 安卓架构

qincheng168的博客 2914

10. 重磅!Spring AI 1.0 正式发布,Java 开发者的 AI神器!

重磅!Spring AI 1.0 正式发布,Java 开发者的 AI神器! 全网最详细的Spring AI 文章,每章都会提供代码入口,让你更容易得入门和理解Spring AI 相关概念,直接节约你百分之六十的学习成本时间。

gorgor在码农 1065

uniapp - H5人脸识别认证与活体检测功能(纯前端免费方案+微信sdk人脸识别)完整源码,微信公众号网页/h5端人脸识别功能人脸核身(微信方案提供后端spring boot+thinkphp源码

uniapp实现人脸认证,uniAPP h5手机拍照+人脸识别,免费人脸识别插件,前端人脸识别解决方案,uniapp H5人脸识别带前后摄像头,人脸识别在H5页面进行采集,微信公众号H5人脸核身,H5端人脸识别功能实现,免费h5人脸识别插件方案,微信公众号H5网页实现人脸识别,uniapp人脸监测,uniapp人脸生物监测,使用uniapp开发H5人脸采集功能/人脸识别功能,uniapp项目—h5端人脸采集功能实现,uniapp vue3人脸核身,H5活体检测认证,人脸认证张嘴摇摇头指引动作,人脸核身 微信

🏆 前端领域优质创作者 3809

网络连接评分机制之NetworkFactory(原)

在开机时,各个提供网络连接的对象需要向ConnectivityService注册自己,并把自己所提供的网络的分值告诉ConnectivityService。         为了ConnectivityService便于统一管理,每一个具备提供网络服务的对象都需要创建一个NetworkFactory的子类对象,并利用该对象注册自己,以及提供自己的分值。 一、NetworkFactory

阿杜的专栏 1万+

【Java 实战】通过Redis实现购物车功能

以上就是今天要讲的内容,本文仅仅简单介绍了如何通过Redis实现购物车功能,以上方法亲测有效,希望能给大家一个参考。

~~~~~~~BUG FLY~~~~~~~~~ 9969

[RK3399][Android7.1] Ethernet -- 在设置-Ethernet中切换静态/动态模式,然后连接网线,测试网络获取不到IP的问题

测试平台 Platform: RK3399 OS: Android 7.1 现象 断开网线后,在设置-Ethernet中切换静态/动态模式,然后连接网线,测试网络获取不到IP的问题。 分析 简单分析下代码,设置以太网ip static/dhcp的流程是: packages/apps/Settings/src/com/android/settings/ethernet/EthernetSettin...

weixin_39966398的博客 4269

【CAN总线测试】——通讯相关诊断测试

本章主要介绍通讯相关诊断测试用例设计

LOVE135149的博客 1813

Lammps的脚本提交作业方式.mp4

本视频主要讲解Lammps如何使用脚本提交作业LAMMPS简介:大规模原子分子并行模拟器LAMMPS即Large-scale Atomic/Molecular Massively Parallel Simulator,可以翻译为大规模原子分子并行模拟器,主要用于分子动力学相关的一些计算和模拟工作,一般来讲,分子动力学所涉及到的领域,LAMMPS代码也都涉及到了。

[RK3399][Android8.1.0][ETHERNET]添加setEthernetEnable()接口

测试平台 Platform: RK3399 OS: 8.1 说明 RK3399-8.1中没有控制Ethernet开关的接口,为了满足部分应用场景需要特添加setEthernetEnabled(boolean enable)和isEthernetInterfaceActive()来对开关进行控制及获取实时状态 实现代码 diff --git a/java/com/android/server/eth...

weixin_39966398的博客 2333

CAD表格输出到EXCEL插件.zip

CAD表格输出到EXCEL插件

Android12 以太网功能实现

Android 12 有线网络适配

weixin_52521865的博客 4475

一加6t q6010基带qcn文件

基带qcn文件可以修复刷机 降级 等掉基带 无串码等故障需要开端口写入有需要的友友下载使用都是完美测试过的资源百分百好使

《第一行代码-Android(第3版)》随书源代码

《第一行代码——Android(第3版)》随书资源

android 8.1 framework层Ethernet多个以太网口切换连接实现流程

之前写过一篇《android 8.1 framework层修改以太网静态ip功能》的文章,这篇是在该基础上实现的。之前的功能,只在设备仅支持单个网口的情况下。当大佬拿来一个设备说:这个还可以外接底座,多网口,目前无法上网。我内心是崩溃的。于是我又开启了慢慢的framework源码阅读之旅。因为百度目前没有找到过相关资料,希望我这篇能补缺——我会很开心! 我这边直接从设置以太网开始讲解,之前该怎么...

qq_33796069的博客 5673

Android 11 Wifi之ConnectivityService流程

framework wifi 之ConnectivityService

TSK_Amine的博客 2420

Andorid:msm8909:在系统设置中添加以太网功能

为安卓系统增加以太网功能,能够在系统设置菜单中找到以太网选项,完成以太网功能设置,并且在系统状态栏能够提示以太网网络状态。

甘霖的博客 3908
上一篇: Android -- 网络相关的系统服务启动简要分析
下一篇: Android -- Wifi扫描流程分析
第一序列丶
博客等级 码龄11年 249粉丝 77原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值