Framework学习】安卓连接管理(ConnectivityService)之wifi连接及注册"/>
【安卓Framework学习】安卓连接管理(ConnectivityService)之wifi连接及注册
系列文章目录
【安卓Framework学习】Wifi框架学习之核心类
【安卓Framework学习】Wifi框架学习之wifi状态机
【安卓Framework学习】Wifi框架学习之连接与断开流程
【安卓Framework学习】Wifi框架学习之扫描模式及扫描流程
【安卓Framework学习】Wifi框架学习之开启与关闭流程
【安卓Framework学习】Wifi框架学习之热点评分机制
文章目录
- 系列文章目录
- 前言
- 一、连接管理(ConnectivityService)简介
- 1.关键类
- 1.1 NetworkFactory
- 1.2 NetworkProvider
- 1.3 NetworkAgent
- 1.4 NetworkAgentInfo
- 1.5 NetworkProviderInfo
- 2.框架整体简图
- 二、连接管理注册
- 1.wifi连接管理注册
- 1.1 NetworkFactory注册
- 1.2 NetworkAgent注册
- 1.3 反向网络请求评价
- 2.wifi连接管理注册流程图
- 总结
前言
之前介绍了一些wifi框架相关的内容,由于wifi框架在安卓连接框架中只是一个小部分,所以今天会分析一下wifi连接上后连接管理框架是如何管理这些网络连接等其他连接的。本篇中涉及到的安卓源码均来源于安卓11.
一、连接管理(ConnectivityService)简介
1.关键类
1.1 NetworkFactory
由类名粗暴的理解为网络工厂,本人理解为所需要的网络由此类提供并控制。根据提供的不同的网络类型有不同的实现,wifi的实现类为WifiNetworkFactory
,以太网的实现为EthernetNetworkFactory
。网络工厂在每个网络框架初始化时便会实例化一个对象出来与网络是否被使用或连接上无关,同时会向连接管理(ConnectivityService
)中注册,并且会接收连接管理发过来的网络请求来决定是否需要断开或继续使用此网络。
1.2 NetworkProvider
由于各个网络框架都运行在自己独立的线程中,与连接管理框架并不直接关联。但是各网络框架需要和连接管理框架进行通信,所以就有了NetworkProvider
作为网络框架和连接管理框架之间的沟通桥梁,也作为网络框架在连接管理框架中的一个代表类。
1.3 NetworkAgent
网络代理,管理着一个网络连接的生命周期,从连接上到断开这中间的保活机制等。当某个网络框架中的网络连接成功后,会向连接管理框架中注册一个NetworkAgent
,用于表示当前连接的网络,当网络断开时就会从连接管理框架中注销。无线网络中有自己的实现WifiNetworkAgent
是ClientModeImpl
的内部类,以太网的实现则是在EthernetNetworkFactory
中当网络层开启时会实例化一个NetworkAgent
并实现其中的unwanted
方法,然后向连接管理框架中注册。
1.4 NetworkAgentInfo
由于NetworkAgent
并不是一个能够跨进程传输的数据类,所以用NetworkAgentInfo
存储在连接管理框架中与对应的NetworkAgent
通过异步通信AsyncChannel
进行连接并实时发送消息,所以算是对NetworkAgent
的一个包装类。
1.5 NetworkProviderInfo
与NetworkAgentInfo
一样,是NetworkProvider
在连接管理框架中的一个代表包装,不同的是NetworkProvider
只需要接收信息即可,所以一般不需要使用异步通信。不过后续系统更新如果需要发送消息,会在NetworkFactory
子类中实现一个AsyncChannel
用于对连接管理框架发送消息,在NetworkProviderInfo
也是预留了异步通信的位置在其中。
2.框架整体简图
二、连接管理注册
1.wifi连接管理注册
1.1 NetworkFactory注册
在ClientModeImpl
构造函数中,会对其中的mNetworkFactory
变量进行赋值,此变量为NetworkFactory
的子类WifiNetworkFactory
。而WifiNetworkFactory
对象是通过WifiInjector.makeWifiNetworkFactory()
方法获得,如下。
public WifiNetworkFactory makeWifiNetworkFactory(NetworkCapabilities nc, WifiConnectivityManager wifiConnectivityManager) {return new WifiNetworkFactory(mWifiHandlerThread.getLooper(), mContext, nc,(ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE),(AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE),(AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE),mClock, this, wifiConnectivityManager, mWifiConfigManager,mWifiConfigStore, mWifiPermissionsUtil, mWifiMetrics);}
这时候再看SystemServer
在启动WifiService
的过程,下面部分SystemServer
的代码太长,这里就不放上来了。在SystemServer.startOtherServices()
方法中,调用了启动WifiService
的代码。
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {/*省略其他代码*/if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {// Wifi Service must be started first for wifi-related services.t.traceBegin("StartWifi");mSystemServiceManager.startService(WIFI_SERVICE_CLASS);t.traceEnd();t.traceBegin("StartWifiScanning");mSystemServiceManager.startService("com.android.server.wifi.scanner.WifiScanningService");t.traceEnd();}/*省略其他代码*/}
在SystemServer
起来的过程中,会将WifiService
拉起来,在其他服务都进入onStart
状态后,会调用WifiService.onBootPhase()
方法。
public void onBootPhase(int phase) {if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {createNotificationChannels(mWifiContext);mImpl.checkAndStartWifi();} else if (phase == SystemService.PHASE_BOOT_COMPLETED) {mImpl.handleBootCompleted();}}
由于传入SystemService.PHASE_BOOT_COMPLETED
值太绕,这里不做详细追踪,感兴趣的同学可以深入。然后会调用到WifiServiceImpl.handleBootCompleted()
,如下。
public void handleBootCompleted() {mWifiThreadRunner.post(() -> {/*省略其他代码*/mClientModeImpl.handleBootCompleted();});}
进一步调用到ClientModeImpl.handleBootCompleted()
,如下。
public void handleBootCompleted() {sendMessage(CMD_BOOT_COMPLETED);}DefaultState.processMessage(Message message)public boolean processMessage(Message message) {/*省略其他代码*/switch (message.what) {/*省略其他代码*/case CMD_BOOT_COMPLETED:// get other services that we need to managegetAdditionalWifiServiceInterfaces();registerNetworkFactory();mSarManager.handleBootCompleted();break;/*省略其他代码*/}/*省略其他代码*/}
在状态DefaultState
处理消息中调用了ClientModeImpl.registerNetworkFactory()
方法。
void registerNetworkFactory() {if (!checkAndSetConnectivityInstance()) return;mNetworkFactory.register();mUntrustedNetworkFactory.register();}
可以看到这里调用了NetworkFactory.register()
方法,从这里开始向连接管理框架中注册NetworkFactory
了。NetworkFactory.register()
方法。
public void register() {/*省略其他代码*/mProvider = new NetworkProvider(mContext, NetworkFactory.this.getLooper(), LOG_TAG) {@Overridepublic void onNetworkRequested(@NonNull NetworkRequest request, int score,int servingProviderId) {handleAddRequest(request, score, servingProviderId);}@Overridepublic void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {handleRemoveRequest(request);}};((ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE)).registerNetworkProvider(mProvider);}
这里直接调用了ConnectivityManager.registerNetworkProvider()
方法注册,跳过ConnectivityManager
直接转入ConnectivityService.registerNetworkProvider()
方法,如下。
public int registerNetworkProvider(Messenger messenger, String name) {enforceNetworkFactoryOrSettingsPermission();NetworkProviderInfo npi = new NetworkProviderInfo(name, messenger,null /* asyncChannel */, nextNetworkProviderId(),() -> unregisterNetworkProvider(messenger));mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_PROVIDER, npi));return npi.providerId;}
可以看到在registerNetworkProvider()
方法中,实例化了一个NetworkProviderInfo
对象,并且用nextNetworkProviderId()
赋予了其独一无二的Id值。然后通过内部的Handler
对象发送了EVENT_REGISTER_NETWORK_PROVIDER
消息,这里跳过处理消息的过程,因为其直接调用了handleRegisterNetworkProvider()
,如下。
private void handleRegisterNetworkProvider(NetworkProviderInfo npi) {/*省略其他代码*/mNetworkProviderInfos.put(npi.messenger, npi);npi.connect(mContext, mTrackerHandler);/*省略其他代码*/}
方法中,首先将NetworkProviderInfo
对象存入在一个全局变量的Map中,并以NetworkProviderInfo
对象获得的Messenger
对象为键值。然后调用NetworkProviderInfo.connect()
方法。
void connect(Context context, Handler handler) {if (isLegacyNetworkFactory()) {mAsyncChannel.connect(context, handler, messenger);} else {try {messenger.getBinder().linkToDeath(mDeathRecipient, 0);} catch (RemoteException e) {mDeathRecipient.binderDied();}}}
方法中的条件判断,由于一开始在初始化NetworkProviderInfo
对象时,传入的第三个参数为null
,所以会直接进入else
分支(因为mAsyncChannel == null
),直接向获得的Messenger
中注册了Binder生命监听对象。到此NetworkFactory注册全部完成。
1.2 NetworkAgent注册
在前面【安卓Framework学习】Wifi框架学习之连接与断开流程中分析到在连接某个热点的时候,ClientModeImpl
会由DisconnectedState
接收处理一个WifiMonitor.NETWORK_CONNECTION_EVENT
消息,由于DisconnectedState
没有处理则会交由其父状态ConnectModeState
来处理。ConnectModeState
处理如下。
public boolean processMessage(Message message) {switch (message.what) {/*省略其他代码*/case WifiMonitor.NETWORK_CONNECTION_EVENT:/*省略其他代码*/if (config != null) {/*省略其他代码*/transitionTo(mObtainingIpState);} else {/*省略其他代码*/}break;/*省略其他代码*/}}
可以看到ConnectModeState
将状态机切换到了ObtainingIpState
,随后在切换进入到ObtainingIpState
状态树时,会调用其父状态L2ConnectedState.enter()
方法。
public void enter() {/*省略部分代码*/// This should never happen.if (mNetworkAgent != null) {Log.wtf(TAG, "mNetworkAgent is not null: " + mNetworkAgent);mNetworkAgent.unregister();}mNetworkAgent = new WifiNetworkAgent(mContext, getHandler().getLooper(),"WifiNetworkAgent", nc, mLinkProperties, 60, naConfig,mNetworkFactory.getProvider());mWifiScoreReport.setNetworkAgent(mNetworkAgent);/*省略部分代码*/}
在L2ConnectedState.enter()
方法中,实例化了一个NetworkAgent
的子类WifiNetworkAgent
对象,看WifiNetworkAgent
的构造方法。
WifiNetworkAgent(Context c, Looper l, String tag, NetworkCapabilities nc, LinkProperties lp,int score, NetworkAgentConfig config, NetworkProvider provider) {super(c, l, tag, nc, lp, score, config, provider);register();}
子类的构造方法中调用了父类NetworkAgent
的构造方法,并同时调用了父类的register()
方法,再看NetworkAgent.register()
,如下。
public Network register() {if (VDBG) log("Registering NetworkAgent");synchronized (mRegisterLock) {/*省略部分代码*/final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context.getSystemService(Context.CONNECTIVITY_SERVICE);mNetwork = cm.registerNetworkAgent(new Messenger(mHandler),new NetworkInfo(mInitialConfiguration.info),mInitialConfiguration.properties, mInitialConfiguration.capabilities,mInitialConfiguration.score, mInitialConfiguration.config, providerId);mInitialConfiguration = null; // All this memory can now be GC'd}return mNetwork;}
这里调用了ConnectivityManager.registerNetworkAgent()
方法,直接进入ConnectivityService.registerNetworkAgent()
中。
public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,LinkProperties linkProperties, NetworkCapabilities networkCapabilities,int currentScore, NetworkAgentConfig networkAgentConfig) {return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities,currentScore, networkAgentConfig, NetworkProvider.ID_NONE);}public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,LinkProperties linkProperties, NetworkCapabilities networkCapabilities,int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) {/*省略部分代码*/final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc,currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig),this, mNetd, mDnsResolver, mNMS, providerId, Binder.getCallingUid());// Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says.nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc));processLinkPropertiesFromAgent(nai, nai.linkProperties);final String extraInfo = networkInfo.getExtraInfo();final String name = TextUtils.isEmpty(extraInfo)? naiworkCapabilities.getSsid() : extraInfo;if (DBG) log("registerNetworkAgent " + nai);final long token = Binder.clearCallingIdentity();try {mDeps.getNetworkStack().makeNetworkMonitor(naiwork, name, new NetworkMonitorCallbacks(nai));} finally {Binder.restoreCallingIdentity(token);}// NetworkAgentInfo registration will finish when the NetworkMonitor is created.// If the network disconnects or sends any other event before that, messages are deferred by// NetworkAgent until nai.asyncChannel.connect(), which will be called when finalizing the// registration.return naiwork;}
由上述方法中的注释可以读到,NetworkAgentInfo
的注册将在NetworkMonitor
被创建之后完成,如果这中间出现了断开连接或者其他的消息发送都将会被积压直到异步通信(AsynChannel
)连接成功后才会发送出去。这里其实只是将NetworkAgent
传过来的Messenger
对象包装成了NetworkAgentInfo
对象,主要的还是注册回调NetworkMonitorCallbacks
到NetworkMonitor
中。NetworkMonitor
其实也是一个状态机,会去做一些联通性检验等操作,源码阅读不方便,这里不做详细分析。直接分析NetworkMonitorCallbacks
,如下。
private class NetworkMonitorCallbacks extends INetworkMonitorCallbacks.Stub {/*省略部分代码*/@Overridepublic void onNetworkMonitorCreated(INetworkMonitor networkMonitor) {mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT,new Pair<>(mNai.getAndDestroy(), networkMonitor)));}/*省略部分代码*/
}
在创建NetworkMonitor
成功后,会调用NetworkMonitorCallbacks .onNetworkMonitorCreated()
回调,此时会给ConnectivityService
中发送EVENT_REGISTER_NETWORK_AGENT
消息,在处理消息中会调用handleRegisterNetworkAgent()
方法。
private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) {nai.onNetworkMonitorCreated(networkMonitor);if (VDBG) log("Got NetworkAgent Messenger");mNetworkAgentInfos.put(nai.messenger, nai);synchronized (mNetworkForNetId) {mNetworkForNetId.put(naiworkId, nai);}try {networkMonitor.start();} catch (RemoteException e) {e.rethrowAsRuntimeException();}nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);NetworkInfo networkInfo = naiworkInfo;updateNetworkInfo(nai, networkInfo);updateUids(nai, null, naiworkCapabilities);}
在此方法中,首先将远端传过来的Binder对象传给了NetworkAgentInfo.onNetworkMonitorCreated()
方法,在NetworkAgentInfo
中生成了一个INetworkMonitor
的代理类NetworkMonitorManager
。然后将刚刚创建的NetworkAgentInfo
分别以Messenger
和netId
为键值存入两个不同的Map
中。然后通过Binder远程调用状态机开启,接下来就是将连接框架中的NetworkAgentInfo
对象与实际的NetworkAgent
通过异步通信进行连接。到这里其实算是NetworkAgent
已经注册完成了。由于这时候刚注册完,NetworkInfo
其实是一个UNKNOWN
的状态,所以其实updateNetworkInfo()
方法虽然调用进去了,但是不会有什么执行内容。
1.3 反向网络请求评价
在注册完NetworkAgent
之后,就等wifi完全连接成功并且分配到可用IP。这里是在ClientModeImpl
中进入状态ConnectModeState
时便向下注册了回调对象IpClientCallbacksImpl
,其中当完全连接成功并有可用IP时,会调用IpClientCallbacksImpl.onProvisioningSuccess()
方法。
class IpClientCallbacksImpl extends IpClientCallbacks {/*省略部分代码*/@Overridepublic void onProvisioningSuccess(LinkProperties newLp) {mWifiMetrics.logStaEvent(StaEvent.TYPE_CMD_IP_CONFIGURATION_SUCCESSFUL);sendMessage(CMD_UPDATE_LINKPROPERTIES, newLp);sendMessage(CMD_IP_CONFIGURATION_SUCCESSFUL);}/*省略部分代码*/
}
可以看到向WIFI状态机ClientModeImpl
发送了CMD_IP_CONFIGURATION_SUCCESSFUL
消息,由上一小节分析可知当前正处于ObtainingIpState
状态,由于ObtainingIpState
没有处理此消息,那么就交由其父状态L2ConnectedState
处理。
public boolean processMessage(Message message) {boolean handleStatus = HANDLED;int callbackIdentifier = -1;switch (message.what) {/*省略部分代码*/case CMD_IP_CONFIGURATION_SUCCESSFUL:if (getCurrentWifiConfiguration() == null) {/*省略部分代码*/} else {handleSuccessfulIpConfiguration();sendConnectedState();transitionTo(mConnectedState);}break; /*省略部分代码*/ }}
因为此时已经连接上了wifi,所以getCurrentWifiConfiguration()
返回肯定不为null
,所以会走下面的分支。这里直接看sendConnectedState()
方法,如下。
private void sendConnectedState() {mNetworkAgent.markConnected();sendNetworkChangeBroadcast(DetailedState.CONNECTED);}
可以看到这里对外发送了广播,并标明wifi已经完成连接。这里调用了NetworkAgent.markConnected()
方法,再继续看此方法。
/*** Inform ConnectivityService that this agent has now connected.* Call {@link #unregister} to disconnect.*/public void markConnected() {/*省略部分代码*/ mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null /* reason */,mNetworkInfo.getExtraInfo());queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo);}
这里由于之前在ConnectivityService
中已经完全注册成功NetworkAgent
,并且异步通信也连接成功,所以这里其实是向ConnectivityService
发送了一个EVENT_NETWORK_INFO_CHANGED
消息,并带有NetworkInfo
数据且状态为CONNECTED
。我们再看ConnectivityService
是如何处理此消息。在内部类NetworkStateTrackerHandler
中。
private void maybeHandleNetworkAgentMessage(Message msg) {NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);/*省略部分代码*/ switch (msg.what) {/*省略部分代码*/ case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: {NetworkInfo info = (NetworkInfo) msg.obj;updateNetworkInfo(nai, info);break;}/*省略部分代码*/ }}
由于之前用Messenger
作为键值存入,所以这里能够精确获得对应的NetworkAgentInfo
对象。此时调用了updateNetworkInfo()
方法。
private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo info) {/*省略部分代码*/ if (!networkAgent.created&& (state == NetworkInfo.State.CONNECTED|| (state == NetworkInfo.State.CONNECTING && networkAgent.isVPN()))) {networkAgentworkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);if (!createNativeNetwork(networkAgent)) return;//这里假设不是VPNnetworkAgent.created = true;}if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {networkAgent.everConnected = true;if (networkAgent.linkProperties == null) {Slog.wtf(TAG, networkAgent.toShortString() + " connected with null LinkProperties");}// 这里由于前面改变了networkCapabilities,所以这里要往下层通知一下网络能力变化networkAgent.getAndSetNetworkCapabilities(networkAgentworkCapabilities);handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties),null);/*省略部分代码*/ //这里向NetworkMonitor通知做此网络的连通性检验networkAgentworkMonitor().notifyNetworkConnected(new LinkProperties(networkAgent.linkProperties,true /* parcelSensitiveFields */),networkAgentworkCapabilities);/*省略部分代码*/ //这里开始对所有的网络请求NetworkRequest与NetworkAgent进行匹配rematchAllNetworksAndRequests();// This has to happen after matching the requests, because callbacks are just requests.notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_PRECHECK);} else if (state == NetworkInfo.State.DISCONNECTED) {/*省略部分代码*/ } else if (networkAgent.created && (oldInfo.getState() == NetworkInfo.State.SUSPENDED ||state == NetworkInfo.State.SUSPENDED)) {/*省略部分代码*/ }}
这里直接看rematchAllNetworksAndRequests()
方法的处理情况,如下。
/*** Attempt to rematch all Networks with NetworkRequests. This may result in Networks* being disconnected.*/private void rematchAllNetworksAndRequests() {/*省略部分代码*/ final NetworkReassignment changes = computeNetworkReassignment();/*省略部分代码*/ applyNetworkReassignment(changes, now);}private NetworkReassignment computeNetworkReassignment() {ensureRunningOnConnectivityServiceThread();final NetworkReassignment changes = new NetworkReassignment();// Gather the list of all relevant agents and sort them by score.final ArrayList<NetworkAgentInfo> nais = new ArrayList<>();for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) {//由于刚刚在updateNetworkInfo中将nai.everConnected改为true所以wifinetworkagent会被加入到nais中if (!nai.everConnected) continue;nais.add(nai);}//这里就需要有添加NetworkRequest了,但是我们在使用的时候并没有添加这类数据,所以查看源码,是在ConnectivityService中起来//的时候添加了一个默认的NetworkRequest,在ConnectivityService的构造方法中for (final NetworkRequestInfo nri : mNetworkRequests.values()) {//添加的默认NetworkRequest是NetworkRequest.Type.REQUESTif (nri.request.isListen()) continue;//这里nais中只有wifi一个agent,所以这里bestNetwork就是wifi注册进来的agentfinal NetworkAgentInfo bestNetwork = mNetworkRanker.getBestNetwork(nri.request, nais);if (bestNetwork != nri.mSatisfier) {// 将要变化的NetworkAgent存起来changes.addRequestReassignment(new NetworkReassignment.RequestReassignment(nri, nri.mSatisfier, bestNetwork));}}return changes;}
随后会获得一个NetworkReassignment
对象,这个对象存储了需要重新请求的NetworkRequestInfo
以及原来的nri.mSatisfier
以及新满足的bestNetwork
。接下来调用applyNetworkReassignment()
方法。
private void applyNetworkReassignment(@NonNull final NetworkReassignment changes,final long now) {final Collection<NetworkAgentInfo> nais = mNetworkAgentInfos.values();final ArraySet<NetworkAgentInfo> oldBgNetworks = new ArraySet<>();for (final NetworkAgentInfo nai : nais) {if (nai.isBackgroundNetwork()) oldBgNetworks.add(nai);}// 先将NetworkRequestInfo中的NetworkAgentInfo更新为最新的for (final NetworkReassignment.RequestReassignment event :changes.getRequestReassignments()) {updateSatisfiersForRematchRequest(event.mRequest, event.mOldNetwork,event.mNewNetwork, now);}/*省略部分代码*/ // 这里将需要变化的NetworkRequestInfo进行遍历,然后通过调用sendUpdatedScoreToFactories()方法通知远端NetworkFactory// 决定是否需要释放当前网络for (final NetworkReassignment.RequestReassignment event :changes.getRequestReassignments()) {// 只有一个NetworkRequestInfo和一个NetworkAgentInfosendUpdatedScoreToFactories(event.mRequest.request, event.mNewNetwork);/*省略部分代码*/}/*省略部分代码*/}
直接转入到sendUpdatedScoreToFactories()
方法。
private void sendUpdatedScoreToFactories(@NonNull NetworkRequest networkRequest,@Nullable NetworkAgentInfo nai) {final int score;final int serial;//这里nai传入的不为null,所以会把wifi的当前分数60传给WifiNetworkProvider,并且ProviderId也是和WifiNetworkProvider一样的if (nai != null) {score = nai.getCurrentScore();serial = nai.factorySerialNumber;} else {score = 0;serial = 0;}/*省略部分代码*/for (NetworkProviderInfo npi : mNetworkProviderInfos.values()) {npi.requestNetwork(networkRequest, score, serial);}}
在继续看NetworkProviderInfo.requestNetwork()
,如下。
void requestNetwork(NetworkRequest request, int score, int servingProviderId) {// 这里因为Factory没有注册,而是注册的NetworkProvider,所以会走下面的分支if (isLegacyNetworkFactory()) {mAsyncChannel.sendMessage(android.NetworkFactory.CMD_REQUEST_NETWORK, score,servingProviderId, request);} else {sendMessageToNetworkProvider(NetworkProvider.CMD_REQUEST_NETWORK, score,servingProviderId, request);}}
可以知道这里给对应的NetworkProvider
发送了CMD_REQUEST_NETWORK
消息,这里需要注意的是发送的NetworkRequest
对象是ConnectivityService
在构造方法中实例化的,再看NetworkProvider
是如何处理消息。
public NetworkProvider(@NonNull Context context, @NonNull Looper looper, @NonNull String name) {/*省略部分代码*/Handler handler = new Handler(looper) {@Overridepublic void handleMessage(Message m) {switch (m.what) {case CMD_REQUEST_NETWORK:onNetworkRequested((NetworkRequest) m.obj, m.arg1, m.arg2);break;/*省略部分代码*/}}};/*省略部分代码*/}
调用了NetworkProvider.onNetworkRequested()
方法,再看NetworlFactory.register()
方法。
public void register() {/*省略部分代码*/mProvider = new NetworkProvider(mContext, NetworkFactory.this.getLooper(), LOG_TAG) {@Overridepublic void onNetworkRequested(@NonNull NetworkRequest request, int score,int servingProviderId) {handleAddRequest(request, score, servingProviderId);}/*省略部分代码*/};/*省略部分代码*/}protected void handleAddRequest(NetworkRequest request, int score, int servingProviderId) {NetworkRequestInfo n = mNetworkRequests.get(request);if (n == null) {/*省略部分代码*/n = new NetworkRequestInfo(request, score, servingProviderId);mNetworkRequests.put(n.request, n);} else {/*省略部分代码*/n.score = score;n.providerId = servingProviderId;}/*省略部分代码*/evalRequest(n);}private void evalRequest(NetworkRequestInfo n) {/*省略部分代码*/if (shouldNeedNetworkFor(n)) {if (VDBG) log(" needNetworkFor");needNetworkFor(n.request, n.score);n.requested = true;} else if (shouldReleaseNetworkFor(n)) {if (VDBG) log(" releaseNetworkFor");releaseNetworkFor(n.request);n.requested = false;} else {/*省略部分代码*/}}
通过上述的方法调用链,可以看到,核心评价方法在于shouldNeedNetworkFor()
和shouldReleaseNetworkFor()
,一个方法用于判断保留当前的网络连接,一个是判断需要断开当前网络连接。详细看这两个方法。
private boolean shouldNeedNetworkFor(NetworkRequestInfo n) {// If this request is already tracked, it doesn't qualify for needreturn !n.requested// If the score of this request is higher or equal to that of this factory and some// other factory is responsible for it, then this factory should not track the request// because it has no hope of satisfying it.&& (n.score < mScore || n.providerId == mProvider.getProviderId())// If this factory can't satisfy the capability needs of this request, then it// should not be tracked.&& n.request.canBeSatisfiedBy(mCapabilityFilter)// Finally if the concrete implementation of the factory rejects the request, then// don't track it.&& acceptRequest(n.request, n.score);}private boolean shouldReleaseNetworkFor(NetworkRequestInfo n) {// Don't release a request that's not tracked.return n.requested// The request should be released if it can't be satisfied by this factory. That// means either of the following conditions are met :// - Its score is too high to be satisfied by this factory and it's not already// assigned to the factory// - This factory can't satisfy the capability needs of the request// - The concrete implementation of the factory rejects the request&& ((n.score > mScore && n.providerId != mProvider.getProviderId())|| !n.request.canBeSatisfiedBy(mCapabilityFilter)|| !acceptRequest(n.request, n.score));}
由于当前的NetworkRequest
是从未请求过,所以n.requested == false
,同时远端传过来的分数与当前WifiNetworkFactory
的分数一样,并且ProviderId
也一样所以shouldNeedNetworkFor()
方法中前两个条件满足。再看n.request.canBeSatisfiedBy(mCapabilityFilter)
,直接进入到NetworkCapabilities.satisfiedByNetworkCapabilities()
方法。
private boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc, boolean onlyImmutable) {//onlyImmutable在跳过的调用链中设置为了falsereturn (nc != null//判断远端的要求网络能力和当前wifi所提供的能力,这里是满足的,因为远端要求的能力比较少,只要求NET_CAPABILITY_INTERNET//而在ClientModeImpl中给的WifiNetworkAgent的NetworkCapabilities就包含了NET_CAPABILITY_INTERNET//这里的判断标准其实是,提供的能力要覆盖大于等于要求的能力&& satisfiedByNetCapabilities(nc, onlyImmutable)//远端设置的网络传输类型为-1,也就是未指定网络类型,这里也是满足的&& satisfiedByTransportTypes(nc)//上传下载带宽在ClientModeImpl中都设置为了1024*1024,所以是满足远端NetworkRequest的要求,因为没有指明,默认为0&& (onlyImmutable || satisfiedByLinkBandwidths(nc))//未指定Specifier所以为ClientModeImpl中默认指定的MatchAllNetworkSpecifier,这里会返回true&& satisfiedBySpecifier(nc)//这里由于在ClientModeImpl中没有给明明确的wifi信号值,所以这里两边相等,条件是满足的&& (onlyImmutable || satisfiedBySignalStrength(nc))//在这个时候还没有完全接受的时候Uids为null,这里是满足的&& (onlyImmutable || satisfiedByUids(nc))//在一开始创建NetworkRequest的时候没有设置SSID,所以远端ConnectivityService中的SSID为null,这里条件满足&& (onlyImmutable || satisfiedBySSID(nc)))//在ConnectivityService中构造函数创建mDefaultRequest时(createDefaultInternetRequestForTransport方法中),//设置了Requestor的Uid和PackageName,这里的uid应该是systemserver的uid,所以这里为true&& (onlyImmutable || satisfiedByRequestor(nc));}
第三个条件网络能力也能够满足。然后分析第四个条件WifiNetworkFactory.acceptRequest()
其实也能满足,因为进入WifiNetworkFactory.acceptRequest()
方法时就判断发过来的请求中networkRequest.getNetworkSpecifier()
是否为null,因为在远端ConnectivityService
初始化NetworkRequest
时并没有指定,所以这里networkRequest.getNetworkSpecifier()
是null的,详细见ConnectivityService.createDefaultInternetRequestForTransport()
。进而会调用到needNetworkFor()
方法。
protected void needNetworkFor(NetworkRequest networkRequest, int score) {NetworkSpecifier ns = networkRequest.getNetworkSpecifier();if (ns == null) {// Generic wifi request. Turn on auto-join if necessary.if (++mGenericConnectionReqCount == 1) {mWifiConnectivityManager.setTrustedConnectionAllowed(true);}} else {// Invalid request with network specifier.if (!isRequestWithNetworkSpecifierValid(networkRequest)) {releaseRequestAsUnfulfillableByAnyFactory(networkRequest);return;}if (!mWifiEnabled) {// Will re-evaluate when wifi is turned on.Log.e(TAG, "Wifi off. Rejecting");return;}retrieveWifiScanner();// Reset state from any previous request.setupForActiveRequest();// Store the active network request.mActiveSpecificNetworkRequest = networkRequest;WifiNetworkSpecifier wns = (WifiNetworkSpecifier) ns;mActiveSpecificNetworkRequestSpecifier = new WifiNetworkSpecifier(wns.ssidPatternMatcher, wns.bssidPatternMatcher, wns.wifiConfiguration);mWifiMetrics.incrementNetworkRequestApiNumRequest();if (!triggerConnectIfUserApprovedMatchFound()) {// Start UI to let the user grant/disallow this request from the app.startUi();// Didn't find an approved match, send the matching results to UI and trigger// periodic scans for finding a network in the request.// Fetch the latest cached scan results to speed up network matching.ScanResult[] cachedScanResults = getFilteredCachedScanResults();if (mVerboseLoggingEnabled) {Log.v(TAG, "Using cached " + cachedScanResults.length + " scan results");}handleScanResults(cachedScanResults);sendNetworkRequestMatchCallbacksForActiveRequest(mActiveMatchedScanResults);startPeriodicScans();}}}
这个方法其实就是设置一些自动连接和周期性扫描相关的。但是这里由于远端的NetworkRequest
没有NetworkSpecifier
,所以这里只是调用了WifiConnectivityManager.setTrustedConnectionAllowed()
这里的设置和wifi的自动连接有关感兴趣的可以详细查看WifiConnectivityManager
源码,所以不做详细分析。到这里连接管理框架反向请求网络评判就结束了。
2.wifi连接管理注册流程图
总结
安卓的ConnectivityService
非常的庞大,这里只是简单介绍了wifi框架向其注册以及wifi连接成功后wifi框架的评价过程,基本思路也适用于以太网的连接注册,上述有部分本人也没有分析透彻,如有感兴趣的大佬可以在评论中指出其中错误之处。本文可以参考用于分析其他的连接注册,例如以太网、数据流量连接等。
更多推荐
【安卓Framework学习】安卓连接管理(ConnectivityService)之wifi连接及注册
发布评论