ConnectivityService处理wifi连接

ConnectivityService用来管理系统中所有网络,谁能连接,谁需要断开。在连接一个网络是,收集网络信息,通过ConnetivityManager提供给应用使用。

在WIFI连接过程中,到链路层L2ConnectedState状态时,有:

class L2ConnectedState extends State {
    @Override
        public void enter() {
            mNetworkAgent = new WifiNetworkAgent(getHandler().getLooper(), mContext,
                    "WifiNetworkAgent", mNetworkInfo, mNetworkCapabilitiesFilter,
                    mLinkProperties, 60, mNetworkMisc);
        }
}

WifiNetworkAgent集成自NetworkAgent,NetworkAgent作为一种网络的代理,和ConnectivityService建立联系。

private class WifiNetworkAgent extends NetworkAgent {

public WifiNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
            super(l, c, TAG, ni, nc, lp, score, misc);
        }
}

NetworkAgent构造方法为:

 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);
    }

最后通过registerNetworkAgent向ConnectivityManager注册NetworkAgent。此处传入了networkinfo,wifi连接状态是CONNECTING, 传入了score = 60,looper参数是消息处理位置,这里是WifiStateMachine. registerNetworkAgent通过ConnectivityManager到达ConnectivityService.

    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,
                networkInfo.getExtraInfo());
        if (DBG) log("registerNetworkAgent " + nai);
        mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
        return nai.network.netId

NetworkAgentInfo在ConnectivityService中使用,它是NetwrokInfo等信息集合。通过本类Handler发送EVENT_REGISTER_NETWORK_AGENT消息。

消息处理方法是handleRegisterNetworkAgent().

private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
    na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
    NetworkInfo networkInfo = na.networkInfo;
    na.networkInfo = null;
    updateNetworkInfo(na, networkInfo);
}

updateNetworkInfor更新网络:

private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
    if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
        networkAgent.everConnected = true;

        updateLinkProperties(networkAgent, null);
        notifyIfacesChangedForNetworkStats();

        networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
        scheduleUnvalidatedPrompt(networkAgent);

        if (networkAgent.isVPN()) {
            // Temporarily disable the default proxy (not global).
            synchronized (mProxyLock) {
                if (!mDefaultProxyDisabled) {
                    mDefaultProxyDisabled = true;
                    if (mGlobalProxy == null && mDefaultProxy != null) {
                        sendProxyBroadcast(null);
                    }
                }
            }
            // TODO: support proxy per network.
        }

        // Whether a particular NetworkRequest listen should cause signal strength thresholds to
        // be communicated to a particular NetworkAgent depends only on the network's immutable,
        // capabilities, so it only needs to be done once on initial connect, not every time the
        // network's capabilities change. Note that we do this before rematching the network,
        // so we could decide to tear it down immediately afterwards. That's fine though - on
        // disconnection NetworkAgents should stop any signal strength monitoring they have been
        // doing.
        updateSignalStrengthThresholds(networkAgent, "CONNECT", null);

        // Consider network even though it is not yet validated.
        final long now = SystemClock.elapsedRealtime();
        rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);

        // This has to happen after matching the requests, because callbacks are just requests.
        notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);
    }
}

由于WIFI网络当前是CONNECTING, 此次调用不会做任何处理。但是当WIFI进入连接状态,将会有如下调用:

class ConnectedState extends State {
    if (mWifiConnectivityManager != null) {
        mWifiConnectivityManager.handleConnectionStateChanged(
                WifiConnectivityManager.WIFI_STATE_CONNECTED);
    }
}

但是当IpManager获得到IP地址,WifiStateMachine通过设置的回调,发出CMD_IP_CONFIGURATION_SUCCESSFUL消息。并做如下处理:

case CMD_IP_CONFIGURATION_SUCCESSFUL:
    handleSuccessfulIpConfiguration();
    reportConnectionAttemptEnd(
            WifiMetrics.ConnectionEvent.FAILURE_NONE,
            WifiMetricsProto.ConnectionEvent.HLF_NONE);
    sendConnectedState();
    transitionTo(mConnectedState);
    break;

sendConnectedState()方法将和ConnectivityService通信。

private void sendConnectedState() {
    setNetworkDetailedState(DetailedState.CONNECTED); // 设置网络状态为CONNECTED
    mWifiConfigManager.updateStatus(mLastNetworkId, DetailedState.CONNECTED);
    sendNetworkStateChangeBroadcast(mLastBssid);
}

在setNetworkDetailedState有一个比较重要的方法,setNetworkDetailedState。WifiStateMachine中通过setNetworkDetailedState更新WIFI状态到ConnectivityService.

private boolean setNetworkDetailedState(NetworkInfo.DetailedState state) {

if (state != mNetworkInfo.getDetailedState()) {
            mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());
            if (mNetworkAgent != null) {
                mNetworkAgent.sendNetworkInfo(mNetworkInfo);
            }
            sendNetworkStateChangeBroadcast(null);
            return true;
        }
    }

这里发送EVENT_NETWORK_INFO_CHANGED到ConnectivityService处理。处理方法是:
updateNetworkInfo(nai, info);在之前已经分析过。现在详细分析:

private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) {
    NetworkInfo.State state = newInfo.getState();
    NetworkInfo oldInfo = null;
    final int oldScore = networkAgent.getCurrentScore();
    
    if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
            networkAgent.everConnected = true;

            updateLinkProperties(networkAgent, null);
            notifyIfacesChangedForNetworkStats();

            networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
            scheduleUnvalidatedPrompt(networkAgent);

            if (networkAgent.isVPN()) {
                // Temporarily disable the default proxy (not global).
                synchronized (mProxyLock) {
                    if (!mDefaultProxyDisabled) {
                        mDefaultProxyDisabled = true;
                        if (mGlobalProxy == null && mDefaultProxy != null) {
                            sendProxyBroadcast(null);
                        }
                    }
                }
                // TODO: support proxy per network.
            }
    final long now = SystemClock.elapsedRealtime();
    rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now);
    
}

这里关注两个地方:

1.networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);  //这个消息将发给networkMonitor做protal

2.rematchNetworkAndRequests(networkAgent, ReapUnvalidatedNetworks.REAP, now); // 处理网络连接

这里先做网络做protal上网验证,这个验证可能会影响网络评分。然后在对网络进行管理,是连接网络,断开其他网络还是不连接。继续看起实现:

private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now) {
    final int score = newNetwork.getCurrentScore(); // 当前接入的网络评分
    // 已经加入的网络
    for (NetworkRequestInfo nri : mNetworkRequests.values()) {
        // 根据评分启动网络
        if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
        if (VDBG) log("rematch for " + newNetwork.name());
        if (currentNetwork != null) {
            if (VDBG) log("   accepting network in place of " + currentNetwork.name());
            currentNetwork.removeRequest(nri.request.requestId);
            currentNetwork.lingerRequest(nri.request, now, mLingerDelayMs);
            affectedNetworks.add(currentNetwork);
        } else {
            if (VDBG) log("   accepting network in place of null");
        }
        newNetwork.unlingerRequest(nri.request);
        mNetworkForRequestId.put(nri.request.requestId, newNetwork);
        if (!newNetwork.addRequest(nri.request)) {
            Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request);
        }
        addedRequests.add(nri);
        keep = true;
        // Tell NetworkFactories about the new score, so they can stop
        // trying to connect if they know they cannot match it.
        // TODO - this could get expensive if we have alot of requests for this
        // network.  Think about if there is a way to reduce this.  Push
        // netid->request mapping to each factory?
        sendUpdatedScoreToFactories(nri.request, score);
        if (isDefaultRequest(nri)) {
            isNewDefault = true;
            oldDefaultNetwork = currentNetwork;
            if (currentNetwork != null) {
                mLingerMonitor.noteLingerDefaultNetwork(currentNetwork, newNetwork);
            }
        }
    }
    
    updateLingerState(newNetwork, now);
    // 断开不需要的网络
    if (reapUnvalidatedNetworks == ReapUnvalidatedNetworks.REAP) {
            for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
                if (unneeded(nai, UnneededFor.TEARDOWN)) {
                    if (nai.getLingerExpiry() > 0) {
                        // This network has active linger timers and no requests, but is not
                        // lingering. Linger it.
                        //
                        // One way (the only way?) this can happen if this network is unvalidated
                        // and became unneeded due to another network improving its score to the
                        // point where this network will no longer be able to satisfy any requests
                        // even if it validates.
                        updateLingerState(nai, now);
                    } else {
                        if (DBG) log("Reaping " + nai.name());
                        teardownUnneededNetwork(nai);
                    }
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值