[RK3288][Android6.0] WiFi之NetworkFactory形成的评分机制

Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92

NetworkFactory作为网络评分机制中一个重要角色而存在,每个模块实现需要继承NetworkFactory

当Wifi状态机初始化处于默认状态时,会注册WifiNetworkFactory
processMessage -> WifiStateMachine.java//DefaultState
 maybeRegisterNetworkFactory

void maybeRegisterNetworkFactory() {
    if (mNetworkFactory == null) {
        //连接ConnectivityService
        checkAndSetConnectivityInstance();
        if (mCm != null) {
            //继承自NetworkFactory
            mNetworkFactory = new WifiNetworkFactory(getHandler().getLooper(), mContext,
                    NETWORKTYPE, mNetworkCapabilitiesFilter);
            //设置评分为60,后面在分析evalRequest会看到
            mNetworkFactory.setScoreFilter(60);
            //所有的NetworkFactory注册到ConnectivityService才能参与评分机制
            mNetworkFactory.register();
        }
    }
}

上面过程设置评分和注册两个步骤
设置评分:
setScoreFilter -> sendMessage(CMD_SET_SCORE) -> handleMessage-> handleSetScore

private void handleSetScore(int score) {
    //当前的score为60,初始化时关键是设置一个mScore值作为Wifi模块的标准值
    mScore = score;
    //当任何一个网络的score有变化时,需要重新评分来判断是否需要切换网络
    evalRequests();
}

mScore在后面evalRequest()会用到,用于比较ConnectivityService传进来的score而去决定request还是release网络

private void evalRequests() {
    //暂时mNetworkRequests为空,不作用
    for (int i = 0; i < mNetworkRequests.size(); i++) {
        NetworkRequestInfo n = mNetworkRequests.valueAt(i);
        evalRequest(n);
    }
}

注册:
register -> registerNetworkFactory
NetworkFactory.java

public void register() {
    if (DBG) log("Registering NetworkFactory");
    if (mMessenger == null) {
        mMessenger = new Messenger(this);
        ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);
    }
}

调用service端,ConnectivityService.java

public void registerNetworkFactory(Messenger messenger, String name) {
    enforceConnectivityInternalPermission();
    //每个client会在server端创建一个NetworkFactoryInfo作为NetworkFactory的代表,并且包含了异步通道和messager信息
    NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
    //把service端的NetworkFactoryInfo当做参数发给内部的InternalHandler处理
    mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
}

收到EVENT_REGISTER_NETWORK_FACTORY消息后处理:
handleMessage -> //InternalHandler类,处理EVENT_REGISTER_NETWORK_FACTORY
 handleRegisterNetworkFactory ->
  mNetworkFactoryInfos.put(nfi.messenger, nfi) //NetworkFactoryInfo被存到mNetworkFactoryInfos数组中
  nfi.asyncChannel.connect -> //发起异步通道连接请求
  handleMessage -> //异步通道对应处理的NetworkStateTrackerHandler类
  handleAsyncChannelHalfConnect -> ConnectivityService.java //CMD_CHANNEL_HALF_CONNECTED
来看handleAsyncChannelHalfConnect():

private void handleAsyncChannelHalfConnect(Message msg)
{
    AsyncChannel ac = (AsyncChannel) msg.obj;
    //mNetworkFactoryInfos前面注册过了,因此条件成立
    if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
        if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
            if (VDBG) log("NetworkFactory connected:"+mNetworkRequests.size());
            // A network factory has connected.  Send it all current NetworkRequests.
            //这里的mNetworkRequests列表开始用的是构造函数ConnectivityService里的默认值
            // NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest,new Binder(), NetworkRequestInfo.REQUEST);
            // mNetworkRequests.put(mDefaultRequest, defaultNRI);
            // mDefaultRequest被加入到mNetworkRequests中,类型是NetworkRequestInfo.REQUEST,请求网络类型
            for (NetworkRequestInfo nri : mNetworkRequests.values()) {
                //NetworkRequest分申请网络和监听网络用的,只处理申请网络,这里可以通过nri.toString()打印出来
                if (nri.isRequest == false) continue;
                //根据requestId取出NetworkRequest对应的NetworkAgentInfo,当网络处于连接状态时,这个值才会有
                //比如wifi的NetworkAgent的子类是WifiNetworkAgent,只有在连接时即L2ConnectedState状态才会去
                //创建,new WifiNetworkAgent(.....),其中参数就包含了score
                NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
                //因此,第一次进来默认没连接上wifi(未连接状态)时第二个参数是为0的
                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)) {
        ......
    }
}

接着通过异步通道发送消息到client,也就是NetworkFactory
ac.sendMessage -> //发送CMD_REQUEST_NETWORK给client端即wifi network factory
 handleMessage -> NetworkFactory.java
  handleAddRequest

protected void handleAddRequest(NetworkRequest request, int score) {
    NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
    //第一次进来肯定是空,生成一个新的NetworkRequestInfo,保存到client的mNetworkRequests数组中
    //注意这是client端的数据结构,只是和server端名字一样
    if (n == null) {
        if (DBG) log("got request " + request + " with score " + score);
        n = new NetworkRequestInfo(request, score);
        mNetworkRequests.put(n.request.requestId, n);
    } else {
        //否则只更新NetworkRequest的分数
        if (VDBG) log("new score " + score + " for exisiting request " + request);
        n.score = score;
    }
    if (VDBG) log("  my score=" + mScore + ", my filter=" + mCapabilityFilter);
    //评估NetworkRequest
    evalRequest(n);
}
private void evalRequest(NetworkRequestInfo n) {
    if (VDBG) log("evalRequest");
    //第一次进来n.requested为false,n.score为0,mScore是60
    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;
    //如果之前已经申请过了,而且当前申请的分数比mScore要大,那么就要释放网络
    } 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");
    }
}

对于evalRequest()函数,摘录一段网友的结论:
该逻辑就是整个网络评价系统最关键的地方,如果NetworkRequestInfo没有被requested过,并且其分值(n.score)小于当前NetworkFactory自己的分值(mScore),那么就说明,当前NetworkFactory所处的网络优先级高于其他网络的优先级,就会触发当前NetworkFactory所在网络的needNetworkFor()流程,也就是连接建立流程,并将标记NetworkRequestInfo.requested=true。
当NetworkRequestInfo被requested过(也就是当前网络被needNetworkFor过),此时如果再次收到请求,并且携带的新score大于当前NetworkFactory所处网络的mScore,那么就说明当前NetworkFactory所在网络优先级已经不是最高,需要将其releaseNetworkFor掉,并标记NetworkRequestInfo.requested=false。

申请网络函数needNetworkFor()被子类覆盖,调用wifi state machine中的WifiNetworkFactory
WifiStateMachine.java

protected void needNetworkFor(NetworkRequest networkRequest, int score) {
    ++mConnectionRequests;
}

最终的作用只是增加mConnectionRequests计数,而这个值会影响WiFi状态机是否去执行连接。也就是说默认情况下mConnectionRequests是不为0的

函数evalRequest()不仅仅是在这次默认初始化会调用,当任一模块比如有线网络连接更新评分机制时,ConnectivityService会通知所有注册了NetworkFactory的模块(也是通过发消息CMD_REQUEST_NETWORK的方式,最终调用到evalRequest())来让模块决定是否要去申请还是释放网络,而决定这一动作的标准值正式上面的mScore值。

关于为什么要用这样的方式而不是直接在ConnectivityService做比较,前辈给出了解释:
[RK3288][Android6.0] WiFi之NetworkFactory形成的评分机制_第1张图片

参考:
网络连接评分机制之NetworkFactory(原)
Android7.0 数据拨号前的准备工作

你可能感兴趣的:(子类__WiFi)