【安卓Framework学习】安卓连接管理(ConnectivityService)之wifi连接及注册

系列文章目录

【安卓Framework学习】Wifi框架学习之核心类
【安卓Framework学习】Wifi框架学习之wifi状态机
【安卓Framework学习】Wifi框架学习之连接与断开流程
【安卓Framework学习】Wifi框架学习之扫描模式及扫描流程
【安卓Framework学习】Wifi框架学习之开启与关闭流程
【安卓Framework学习】Wifi框架学习之热点评分机制



前言

之前介绍了一些wifi框架相关的内容,由于wifi框架在安卓连接框架中只是一个小部分,所以今天会分析一下wifi连接上后连接管理框架是如何管理这些网络连接等其他连接的。本篇中涉及到的安卓源码均来源于安卓11.


一、连接管理(ConnectivityService)简介

1.关键类

1.1 NetworkFactory

由类名粗暴的理解为网络工厂,本人理解为所需要的网络由此类提供并控制。根据提供的不同的网络类型有不同的实现,wifi的实现类为WifiNetworkFactory,以太网的实现为EthernetNetworkFactory。网络工厂在每个网络框架初始化时便会实例化一个对象出来与网络是否被使用或连接上无关,同时会向连接管理(ConnectivityService)中注册,并且会接收连接管理发过来的网络请求来决定是否需要断开或继续使用此网络。

1.2 NetworkProvider

由于各个网络框架都运行在自己独立的线程中,与连接管理框架并不直接关联。但是各网络框架需要和连接管理框架进行通信,所以就有了NetworkProvider作为网络框架和连接管理框架之间的沟通桥梁,也作为网络框架在连接管理框架中的一个代表类。

1.3 NetworkAgent

网络代理,管理着一个网络连接的生命周期,从连接上到断开这中间的保活机制等。当某个网络框架中的网络连接成功后,会向连接管理框架中注册一个NetworkAgent,用于表示当前连接的网络,当网络断开时就会从连接管理框架中注销。无线网络中有自己的实现WifiNetworkAgentClientModeImpl的内部类,以太网的实现则是在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 manage
				getAdditionalWifiServiceInterfaces();
				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) {
	        @Override
	        public void onNetworkRequested(@NonNull NetworkRequest request, int score,
	                int servingProviderId) {
	            handleAddRequest(request, score, servingProviderId);
	        }
	        @Override
	        public 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)
	            ? nai.networkCapabilities.getSsid() : extraInfo;
	    if (DBG) log("registerNetworkAgent " + nai);
	    final long token = Binder.clearCallingIdentity();
	    try {
	        mDeps.getNetworkStack().makeNetworkMonitor(
	                nai.network, 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 nai.network;
	}

由上述方法中的注释可以读到,NetworkAgentInfo的注册将在NetworkMonitor被创建之后完成,如果这中间出现了断开连接或者其他的消息发送都将会被积压直到异步通信(AsynChannel)连接成功后才会发送出去。这里其实只是将NetworkAgent传过来的Messenger对象包装成了NetworkAgentInfo对象,主要的还是注册回调NetworkMonitorCallbacksNetworkMonitor中。NetworkMonitor其实也是一个状态机,会去做一些联通性检验等操作,源码阅读不方便,这里不做详细分析。直接分析NetworkMonitorCallbacks,如下。

private class NetworkMonitorCallbacks extends INetworkMonitorCallbacks.Stub {
	/*省略部分代码*/
    @Override
    public 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(nai.network.netId, nai);
	    }
	    try {
	        networkMonitor.start();
	    } catch (RemoteException e) {
	        e.rethrowAsRuntimeException();
	    }
	    nai.asyncChannel.connect(mContext, mTrackerHandler, nai.messenger);
	    NetworkInfo networkInfo = nai.networkInfo;
	    updateNetworkInfo(nai, networkInfo);
	    updateUids(nai, null, nai.networkCapabilities);
	}

在此方法中,首先将远端传过来的Binder对象传给了NetworkAgentInfo.onNetworkMonitorCreated()方法,在NetworkAgentInfo中生成了一个INetworkMonitor的代理类NetworkMonitorManager。然后将刚刚创建的NetworkAgentInfo分别以MessengernetId为键值存入两个不同的Map中。然后通过Binder远程调用状态机开启,接下来就是将连接框架中的NetworkAgentInfo对象与实际的NetworkAgent通过异步通信进行连接。到这里其实算是NetworkAgent已经注册完成了。由于这时候刚注册完,NetworkInfo其实是一个UNKNOWN的状态,所以其实updateNetworkInfo()方法虽然调用进去了,但是不会有什么执行内容。

1.3 反向网络请求评价

在注册完NetworkAgent之后,就等wifi完全连接成功并且分配到可用IP。这里是在ClientModeImpl中进入状态ConnectModeState时便向下注册了回调对象IpClientCallbacksImpl,其中当完全连接成功并有可用IP时,会调用IpClientCallbacksImpl.onProvisioningSuccess()方法。

class IpClientCallbacksImpl extends IpClientCallbacks {
	/*省略部分代码*/
	@Override
	public 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()))) {
	        networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
	        if (!createNativeNetwork(networkAgent)) return;
	        //这里假设不是VPN
	        networkAgent.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(networkAgent.networkCapabilities);
	        handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
	        updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties),
	                null);
	        /*省略部分代码*/	
	        //这里向NetworkMonitor通知做此网络的连通性检验
	        networkAgent.networkMonitor().notifyNetworkConnected(
	                new LinkProperties(networkAgent.linkProperties,
	                        true /* parcelSensitiveFields */),
	                networkAgent.networkCapabilities);
	        /*省略部分代码*/	
	        //这里开始对所有的网络请求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.REQUEST
	        if (nri.request.isListen()) continue;
	        //这里nais中只有wifi一个agent,所以这里bestNetwork就是wifi注册进来的agent
	        final 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和一个NetworkAgentInfo
	        sendUpdatedScoreToFactories(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.net.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) {
	        @Override
	        public 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) {
	        @Override
	        public 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 need
	    return !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在跳过的调用链中设置为了false
	    return (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框架的评价过程,基本思路也适用于以太网的连接注册,上述有部分本人也没有分析透彻,如有感兴趣的大佬可以在评论中指出其中错误之处。本文可以参考用于分析其他的连接注册,例如以太网、数据流量连接等。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中,可以通过以下方法检测WiFi连接是否可用: 1. 使用ConnectivityManager类检查网络连接状态。使用该类的`getActiveNetworkInfo()`方法可以获取当前设备的网络连接状态。如果返回的对象为null,表示设备当前没有可用的网络连接。 2. 使用WifiManager类检查WiFi连接状态。使用该类的`getConnectionInfo()`方法可以获取当前设备连接WiFi信息,包括SSID、BSSID、信号强度等。如果返回的对象为null,表示设备当前没有连接WiFi网络。 3. 使用BroadcastReceiver监听WiFi连接状态变化。可以使用`android.net.wifi.STATE_CHANGE`和`android.net.conn.CONNECTIVITY_CHANGE`这两个Intent过滤器来监听WiFi连接状态的变化,当WiFi连接状态变化时,会发送相应的广播。可以在BroadcastReceiver中处理这些广播,以便在WiFi连接状态发生变化时执行相应的操作。 需要注意的是,要检测WiFi连接状态,必须在AndroidManifest.xml文件中声明相应的权限,如下所示: ```xml <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> ``` 另外,检测WiFi连接状态也需要在运行时获取权限,可以使用以下代码来请求权限: ```java if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_NETWORK_STATE, Manifest.permission.ACCESS_WIFI_STATE}, requestCode); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值