1.网络管理概览

​ Android中提供的数据业务方式有几种:移动数据网络,WIFI,热点,网线等。这些数据业务本身可以独立使用,但是同一时刻,只能使用其中的一种数据业务方式。管理这些数据业务方式的使用由ConnectivityService,NetworkFactory,NetworkAgent,NetworkMonitor等来完成,ConnectivityService处于核心调度位置。

​ 在公司项目中,引入了Tbox和车内以太网。这两类网络上网的方式主要替代原生的移动数据网络和以太网。

​ ConnectivityService主要和以下四个模块交互来完成网络管理:

  • 网络有效性检测(NetworkMonitor)
  • 网络评分机制(NetworkFactory)
  • 路由配置信息的获取(NetworkAgent)
  • 网络物理端口的设置(Netd)

Android网络管理架构如下图所示

Android网络管理.png

当Android数据业务服务可用时,会将自己(NetworkFactory和NetworkAgent)注册到ConnectivityService中统一管理,ConnectivityService通过ping网络来检查网络的有效性(AOSP中的网址是墙外的网址,极有可能ping不通,因此项目中应该修改此网址,否则可能会导致期望的网络得不到上网权限),进而影响到各个数据业务方式的评分值,ConnectivityService通过这些评分值来决定以哪个数据业务方式连接网络。决定好数据业务方式后,把这些路由配置信息设置到网络物理设备中。这样我们的手机就可以正常上网了。

2.各个服务的初始化

2.1.1 ConnectivityService的初始化

ConnectivityService属于系统服务,在SystemServer中被启动。

SystemServer启动系统核心服务分为三个阶段:

  • 启动引导服务,包含AMS PMS DMS PKMS等
  • 启动核心服务:DropBox,Battery,UsageStats,WebViewUpdate等
  • 启动其他服务:InputManagerService,WindowManagerService,ConnectivityService等

咱们的主角ConnectivityService就是在其他服务中被启动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
private void run() {
try {
......
// 设置时区
String timezoneProperty = SystemProperties.get("persist.sys.timezone");
if (timezoneProperty == null || timezoneProperty.isEmpty()) {
Slog.w(TAG, "Timezone not set; setting to GMT.");
SystemProperties.set("persist.sys.timezone", "GMT");
}

......
// 设置语言,国家等等
if (!SystemProperties.get("persist.sys.language").isEmpty()) {
final String languageTag = Locale.getDefault().toLanguageTag();

SystemProperties.set("persist.sys.locale", languageTag);
SystemProperties.set("persist.sys.language", "");
SystemProperties.set("persist.sys.country", "");
SystemProperties.set("persist.sys.localevar", "");
}

// Here we go!
Slog.i(TAG, "Entered the Android system server!");
......
//此处省略部分主要干了清理更多内存出来为初始化服务做准备,设置后台任务,增加binder最大线程等

// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper();

// Initialize native services.
System.loadLibrary("android_servers");

// Initialize the system context.
//创建android上下文
createSystemContext();

// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
} finally {
traceEnd(); // InitBeforeStartServices
}

// Start services.
try {
traceBeginAndSlog("StartServices");
//开始启动服务了 ,这个方法是启动引导服务 例如AMS PMS DMS PKMS
startBootstrapServices();
//启动核心服务:DropBox,Battery,UsageStats,WebViewUpdate
startCoreServices();
//启动其他服务
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
......

// Loop forever.
//systemServer一直循环
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
private void startOtherServices() {
final Context context = mSystemContext;
VibratorService vibrator = null;
IStorageManager storageManager = null;
NetworkManagementService networkManagement = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
NetworkScoreService networkScore = null;
......

// 初始化NetworkManagementService
if (!disableNetwork) {
traceBeginAndSlog("StartNetworkManagementService");
try {
networkManagement = NetworkManagementService.create(context);
ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
} catch (Throwable e) {
reportWtf("starting NetworkManagement Service", e);
}
traceEnd();
}
......

// 初始化NetworkStatsService
traceBeginAndSlog("StartNetworkStatsService");
try {
networkStats = NetworkStatsService.create(context, networkManagement);
ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats);
} catch (Throwable e) {
reportWtf("starting NetworkStats Service", e);
}
traceEnd();

// 初始化NetworkPolicyManagerService
traceBeginAndSlog("StartNetworkPolicyManagerService");
try {
networkPolicy = new NetworkPolicyManagerService(context,
mActivityManagerService, networkStats, networkManagement);
ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
} catch (Throwable e) {
reportWtf("starting NetworkPolicy Service", e);
}
traceEnd();

// 初始化ConnectivityService
traceBeginAndSlog("StartConnectivityService");
try {
connectivity = new ConnectivityService(
context, networkManagement, networkStats, networkPolicy);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
networkStats.bindConnectivityManager(connectivity);
networkPolicy.bindConnectivityManager(connectivity);
} catch (Throwable e) {
reportWtf("starting Connectivity Service", e);
}
traceEnd();
}

初始化ConnectivityService的时候传入networkManagement,networkStats,networkPolicy。

2.1.2 获取其他服务的接口

ConnectivityService构造方法中接收交互服务的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
mNetd = checkNotNull(netManager, "missing INetworkManagementService");
mStatsService = checkNotNull(statsService, "missing INetworkStatsService");
mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
mPolicyManagerInternal = checkNotNull(
LocalServices.getService(NetworkPolicyManagerInternal.class),
"missing NetworkPolicyManagerInternal");

// 构建mTethering
mTethering = new Tethering(mContext, mNetd, statsService, mPolicyManager,
IoThread.get().getLooper(), new MockableSystemProperties());

//注册其他必要的监听和广播,以便接收变化信息和通知变化信息。
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_STARTED);
intentFilter.addAction(Intent.ACTION_USER_STOPPED);
intentFilter.addAction(Intent.ACTION_USER_ADDED);
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
intentFilter.addAction(Intent.ACTION_USER_UNLOCKED);
mContext.registerReceiverAsUser(
mUserIntentReceiver, UserHandle.ALL, intentFilter, null, null);
mContext.registerReceiverAsUser(mUserPresentReceiver, UserHandle.SYSTEM,
new IntentFilter(Intent.ACTION_USER_PRESENT), null, null);

// 向netd注册mTethering
mNetd.registerObserver(mTethering);
mNetd.registerObserver(mDataActivityObserver);

2.2 NetworkFactory的初始化

NetworkFactory负责构建新增网络默认评分,网络类型,网络能力。为了车机启动起来就能按照网络评分机制来选择网络,ConnectivityService服务起来之后,就不断收集外部注册进来的网络(本文用Tbox注册网络和wifi注册网络来叙述)。

NetworkFactory初始化.png

当管理Tbox的service起来之后,通过获取usb0(tbox通过usb0与车机通信)配置信息(usb0;12,13,14,15;ip=2.2.2.1/24 gateway=2.2.2.2 dns=116.116.116.116,8.8.8.8;0;70)。然后解析配置信息,解析获取网卡信息之后,创建一个NetworkFactory最后调用register()方法,将该网卡注册到ConnectivityService中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// NetworkFactory.java
public void register() {
this.log("Registering NetworkFactory");
if (this.mMessenger == null) {
this.mMessenger = new Messenger(this);
ConnectivityManager.from(this.mContext).registerNetworkFactory(this.mMessenger,
this.LOG_TAG);
}
}

// ConnectivityService.java
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));
}
//处理EVENT_REGISTER_NETWORK_FACTORY
private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
mNetworkFactoryInfos.put(nfi.messenger, nfi);
//通过asyncChannel通知Networkfactory操作成功
//注意,在异步回复Networkfactory的时候,asyncChannel会处理CMD_CHANNEL_HALF_CONNECTED来通知创建NetworkAgent
nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
}

2.3 NetworkAgent的初始化

NetworkAgent是一个网络代理,它里面保存了一些路由的配置信息,比如NetworkInfo,LinkProperties,NetworkCapabilities等。NetworkAgent的初始化都是在路由配置信息获取成功之后。比如打开数据开关,打开wifi开关等操作之后。

注:
NetworkInfo 描述一个给定类型的网络接口的状态方面的信息,包括网络连接状态、网络类型、网络可连接性、是否漫游等信息
LinkProperties 描述一个网络连接属性信息(包含网络地址、网关、DNS、HTTP代理等属性信息
NetworkCapabilities 描述一个网络连接能力方面的信息,包括带宽、延迟等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 处理CMD_CHANNEL_HALF_CONNECTED 
private boolean maybeHandleAsyncChannelMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
// 向NetworkFactory发送路由配置成功了,可以创建NetworkAgent代理了。
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.request.isListen()) continue;
NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
// 向NetworkFactory发送CMD_REQUEST_NETWORK请求处理
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);
}
}
......
}

// NetworkFactory.java
public void handleMessage(Message msg) {
switch (msg.what) {
case CMD_REQUEST_NETWORK: {
handleAddRequest((NetworkRequest) msg.obj, msg.arg1, msg.arg2);
break;
}
......
}
}

当路由信息配置成功之后,ConnectivityService会通知NetworkFactory创建NetworkAgent。在handleAddRequest方法中会调用evalRequest根据评分,网络能力等来判断是否需要创建代理。

调用链路:handleAddRequest() –> evalRequest() –> needNetworkFor() –> NetworkFactory.startNetwork()–> ExtNetworkFactory.startNetwork() –> mayStartIpManager() –> startIpManager() –> new NetworkAgent()

2.4 NetworkMonitor的初始化

NetworkMonitor主要是检测网络有效性的,通过Http封装类去ping一个网站,根据ping网站的结果来影响评分值。因此,它的初始化是在NetworkAgent初始化之后,必须要获取到路由配置信息NetworkAgent后才会去初始化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 构建NetworkAgent
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
......
// 向ConnectivityService中注册NetworkAgent
this.netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
......
}

public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
int currentScore, NetworkMisc networkMisc) {
// 构建NetworkAgentInfo,在NetworkAgentInfo中构建NetworkMonitor
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);
....
}

3. 网络有效性检测(NetworkMonitor)

NetworkMonitor是一个状态机。负责检测网络有效性,也就是ping网络的过程。ping网络过程中产生的几种状态如下:

  • DefaultState 默认状态
  • EvaluatingState 验证状态
  • ValidatedState 验证通过状态
  • LingeringState 休闲状态,表示网络的验证位是真实的,并且曾经是满足特定NetworkRequest的最高得分网络,但是此时另一个网络满足了NetworkRequest的更高分数,在断开连接前的一段时间前,该网络被“固定”为休闲状态。
  • CaptivePortalState 强制门户状态
  • MaybeNotifyState 可能通知状态,表示用户可能已被通知需要登录。 在退出该状态时,应该小心清除通知。

NetworkMonitor状态机.png

以正常的ping网站过程为例,DefaultState为默认状态,NetworkMonitor接收到CMD_NETWORK_CONNECTED事件消息后,先由DefaultState状态处理,然后由EvaluatingState处理,最后交给ValidatedState处理。

从NetworkMonitor的初始化,到ping网站的过程,到ping网站的结果影响评分值。这个过程的时序图如下:

NetworkMonitor初始化流程.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Handles a network appearing or improving its score.
// - Evaluates all current NetworkRequests that can be
// satisfied by newNetwork, and reassigns to newNetwork
// any such requests for which newNetwork is the best.
//
// - Lingers any validated Networks that as a result are no longer
// needed. A network is needed if it is the best network for
// one or more NetworkRequests, or if it is a VPN.
//
// - Tears down newNetwork if it just became validated
// but turns out to be unneeded.
//
// - If reapUnvalidatedNetworks==REAP, tears down unvalidated
// networks that have no chance (i.e. even if validated)
// of becoming the highest scoring network.

// 1.新的NetworkAgentInfo出来,要重新评估所有的NetworkRequests,如果这个网络是最好的网络,会将这些NetworkRequests reassigns到这个新网络, 比如数据网络连接的情况下,wifi连接成功且网络判通成功,这时候一些网络请求的NetworkRequests 要reassigns 到wifi的NetworkAgentInfo
// 2.Lingers任何一个不再需要的validated Networks,理解 “不再需要”,wifi连接的情况下,data网络正常是会linger的,但是如果此时有一个或多个NetworkRequest的指定的transportType为NetworkCapabilities.TRANSPORT_CELLULAR 此时不会linger这个数据网络,另外这个网络是VPN.也不会被linger
// 3.如果一个不需要的网络,就是被linger的网络,会执行Tears down newNetwork ,导致networkagent调用unwanted()方法 网络interface 都会被关闭(可以通过ifconfig 中消失掉来验证)
// 4.reapUnvalidatedNetworks 最后一个网络会传REAP,导致网络被tear down
rematchNetworkAndRequests(NetworkAgentInfo newNetwork,
ReapUnvalidatedNetworks reapUnvalidatedNetworks, long now)

当网络状态变化,网络信息变化都会调用到rematchNetworkAndRequests方法中,最后会根据状态机状态,send不同类型的message,NetworkMonitor收到message之后进行相应的处理。

以收到CMD_NETWORK_CONNECTED为例,当monitor收到CMD_NETWORK_CONNECTED消息的时候,会将状态机切换到EvaluatingState状态,在EvaluatingState的enter()方法中发送CMD_REEVALUATE消息。在processMessage()中处理该消息。最后会调用到isCaptivePortal();中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// isCaptivePortal会根据http或者https请求发起HttpURLConnection()
CaptivePortalProbeResult probeResult = isCaptivePortal();
//根据不同的ping结果,做相应处理
if (probeResult.isSuccessful()) {
transitionTo(mValidatedState);
} else if (probeResult.isPortal()) {
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
NETWORK_TEST_RESULT_INVALID, mNetId, probeResult.redirectUrl));
mLastPortalProbeResult = probeResult;
transitionTo(mCaptivePortalState);
} else {
final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
sendMessageDelayed(msg, mReevaluateDelayMs);
logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);
mConnectivityServiceHandler.sendMessage(obtainMessage(
EVENT_NETWORK_TESTED, NETWORK_TEST_RESULT_INVALID, mNetId,
probeResult.redirectUrl));
if (mAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) {
// Don't continue to blame UID forever.
TrafficStats.clearThreadStatsUid();
}
mReevaluateDelayMs *= 2;
if (mReevaluateDelayMs > MAX_REEVALUATE_DELAY_MS) {
mReevaluateDelayMs = MAX_REEVALUATE_DELAY_MS;
}
}

根据ping网络的结果来执行不同的操作:

  • ping网络成功,如果收到的响应码是204,将状态机切换到ValidatedState。当状态机切换到ValidatedState之后,在enter()方法中会发送消息EVENT_NETWORK_TESTED。当ConnectivityService收到EVENT_NETWORK_TESTED之后,调用updateCapabilities()更新网卡能力和重新评估这个网络是否对于所有请求是最优的;如果当前能ping通的网络评分和以前的评分不一致,调用sendUpdatedScoreToFactories()更新评分。
  • ping网络失败,网络返回200~399,转到CaptivePortalState状态处理。
  • ping网络失败,不是204,也不是200~399,则发送CMD_REEVALUATE消息,重新触发ping网络的动作。第一次失败,8s后重新ping网络,第二次失败,16s后重新ping网络,时间依次倍增,最长的时间间隔为10分钟。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private boolean maybeHandleNetworkMonitorMessage(Message msg) {
......
case NetworkMonitor.EVENT_NETWORK_TESTED: {
final NetworkAgentInfo nai;
synchronized (mNetworkForNetId) {
nai = mNetworkForNetId.get(msg.arg2);
}
.....
if (valid != nai.lastValidated) {
// 更新评分
final int oldScore = nai.getCurrentScore();
......
// 更新网络接口能力
updateCapabilities(oldScore, nai, nai.networkCapabilities);
// 更新评分到网络工厂
if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai);
}
.....
break;
}
.....
}

ping网络的状态会保存到NetworkAgentInfo中,而后续所有的评分值都会调用NetworkAgentInfo的getCurrentScore()方法来获取,getCurrentScore()方法会根据当前ping网络的状态重新计算评分值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private int getCurrentScore(boolean pretendValidated) {
// 如果是用户指定的网络,直接给100分
if (networkMisc.explicitlySelected && (networkMisc.acceptUnvalidated || pretendValidated)) {
return MAXIMUM_NETWORK_SCORE; //100
}

int score = currentScore;
// 如果ping失败了就扣40分,如果ping网络成功,则评分值不变。
if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty()) {
score -= UNVALIDATED_SCORE_PENALTY; // -40
}
if (score < 0) score = 0;
return score;
}

3.网络评分机制

NetworkFactory的存在意义就是为了帮助ConnectivityService进行评分的管理。一般在NetworkFactory在初始化时,设置固定的评分值,作为评判的标准。
NetworkAgent作为一个代理信息的抽象,在其初始化时,也设置了固定的评分值,不过,这个评分值会根据当前的网络情况的不同而变化,其最后的评分值会和NetworkFactory中的固定评分值进行比较,从而筛选出最优网络。

项目中可能涉及的网络源如下:WifiNetworkFactory,TelephonyNetwork,EthernetNetwork,PhoneSwitcher,Tbox。

这些工厂在初始化的时候,会将默认评分注册到ConnectivityService中

NetworkFactory初始化 NetworkAgent初始化 NetworkMonitor中ping网络 disconnect
TelephonyNetwork 50 50 成功:+0 失败:-40 用户指定:+100 0
Tbox 50 50 成功:+0 失败:-40 用户指定:+100 0
Wifi 60 60 成功:+0 失败:-40 用户指定:+100 0
EthernetNetwork 69 69 成功:+0 失败:-40 用户指定:+100 0
PhoneSwitcher 101 101 成功:+0 失败:-40 用户指定:+100 0

各种数据业务类型的评分标准,除了其基础评分值不同之外,其他的评判标准都一样。其评分值的变化,主要有以下几种情况:
一.代理信息获取结束后,会参与ping网络的过程,如果ping网络成功,那么NetworkAgent中的评分值不变。如果ping网络失败,那么NetworkAgent中的评分值-40。如果用户指定了某种网络类型作为连接方式,那么NetworkAgent重的评分值+100。
二.如果NetworkAgent和ConnectivityService的AsyncChannel通道断开,需要设置其评分值为0,好让其他的评分高的网络类型连接。

NetworkFactory中的评分标准:

NetworkFactory中维持了基础的评分分值mScore,mScore只有在 NetworkFactory对象创建的时候才会赋值。因网络环境的变化导致需要重新进行网络评估时,使用基础评分分值与传进来的NetworkRequestInfo中的分值进行比较。

  • 如果当前的NetworkRequestInfo没有requested过,且当前的分值score比基础分值mScore小,说明当前的NetworkRequestInfo为最优网络,调用needNetworkFor()连接网络。
  • 如果当前的NetworkRequestInfo已经requested过,且当前的分值score比基础分值mScore大,说明当前的NetworkRequestInfo已经不是最优网络了,有个更优的网络可用连接,此时应该调用releaseNetworkFor()释放掉此类网络连接。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void evalRequest(NetworkRequestInfo n) {
if (VDBG) log("evalRequest request = " + n.request + " with requested = " + n.requested);
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");
}
}

触发评分的过程:

1.NetworkFactory与ConnectivityService通过AsyncChannel建立连接的时候,初始化评分,并参与了第一次的评分过程。如果此时还没有ping网络的话,其传进来的评分值为基础评分值,以上代码会执行else逻辑。

2.调用sendUpdatedScoreToFactories()方法触发了评分过程
在ping网络过程中,会触发多次评分过程。在NetworkMonitor的多个状态中,都有向ConnectivityService发起EVENT_NETWORK_TESTED事件消息更新评分