目录
1.回顾
2. NetworkFactory简介
2.1 构造函数
2.2 setScoreFilter
2.3 register
2.4 看下NetworkRequests哪里来的
2.5 evalRequest
3.总结
case CMD_START_CONNECT:
/* connect command coming from auto-join */
netId = message.arg1;
int uid = message.arg2;
bssid = (String) message.obj;
synchronized (mWifiReqCountLock) {
if (!hasConnectionRequests()) {
if (mNetworkAgent == null) {
loge("CMD_START_CONNECT but no requests and not connected,"
+ " bailing");
break;
} else if (!mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) {
loge("CMD_START_CONNECT but no requests and connected, but app "
+ "does not have sufficient permissions, bailing");
break;
}
}
}
在WiFi进行连接的时候会判断一下当前是否有连接请求
/**
* Check if there is any connection request for WiFi network.
* Note, caller of this helper function must acquire mWifiReqCountLock.
*/
private boolean hasConnectionRequests() {
return mConnectionReqCount > 0 || mUntrustedReqCount > 0;
}
看下mConnectionReqCount在哪里进行赋值
@GuardedBy("mWifiReqCountLock")
private int mConnectionReqCount = 0;
初始化为0,使用时需要锁mWifiReqCountLock
private class WifiNetworkFactory extends NetworkFactory {
public WifiNetworkFactory(Looper l, Context c, String TAG, NetworkCapabilities f) {
super(l, c, TAG, f);
}
@Override
protected void needNetworkFor(NetworkRequest networkRequest, int score) {
synchronized (mWifiReqCountLock) {
if (++mConnectionReqCount == 1) {
if (mWifiConnectivityManager != null && mUntrustedReqCount == 0) {
mWifiConnectivityManager.enable(true);
}
}
}
}
@Override
protected void releaseNetworkFor(NetworkRequest networkRequest) {
synchronized (mWifiReqCountLock) {
if (--mConnectionReqCount == 0) {
if (mWifiConnectivityManager != null && mUntrustedReqCount == 0) {
mWifiConnectivityManager.enable(false);
}
}
}
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("mConnectionReqCount " + mConnectionReqCount);
}
}
WifiNetworkFactory中会对mConnectionReqCount进行自增和自减的操作,区别在于是needNetworkFor还是releaseNetworkFor.
需要看下NetworkFactory是什么?主要有什么用途?needNetworkFor和releaseNetworkFor是做什么用的?
void maybeRegisterNetworkFactory() {
if (mNetworkFactory == null) {
checkAndSetConnectivityInstance();
if (mCm != null) {
mNetworkFactory = new WifiNetworkFactory(getHandler().getLooper(), mContext,
NETWORKTYPE, mNetworkCapabilitiesFilter);
mNetworkFactory.setScoreFilter(60);
mNetworkFactory.register();
// We can't filter untrusted network in the capabilities filter because a trusted
// network would still satisfy a request that accepts untrusted ones.
mUntrustedNetworkFactory = new UntrustedWifiNetworkFactory(getHandler().getLooper(),
mContext, NETWORKTYPE_UNTRUSTED, mNetworkCapabilitiesFilter);
mUntrustedNetworkFactory.setScoreFilter(Integer.MAX_VALUE);
mUntrustedNetworkFactory.register();
}
}
}
初始化很简单,就是new出来一个对象,然后设置一下ScoreFilter并注册了一下。
/**
* A NetworkFactory is an entity that creates NetworkAgent objects.
* The bearers register with ConnectivityService using {@link #register} and
* their factory will start receiving scored NetworkRequests. NetworkRequests
* can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
* overridden function. All of these can be dynamic - changing NetworkCapabilities
* or score forces re-evaluation of all current requests.
*
* If any requests pass the filter some overrideable functions will be called.
* If the bearer only cares about very simple start/stopNetwork callbacks, those
* functions can be overridden. If the bearer needs more interaction, it can
* override addNetworkRequest and removeNetworkRequest which will give it each
* request that passes their current filters.
* @hide
**/
public class NetworkFactory extends Handler {
NetworkFactory是创建NetworkAgent对象的类
使用了ConnectivityService的register方法,然后工厂就可以收到scored networkRequests
NetworkRequest可以用3种途径过滤:NetworkCapabilites/score和重载方法
改变NetworkCapabilities和score会强制触发所有requests的重新评估
当重载addNetworkRequest和removeNetworkRequest,可以获取通过filters的每个request来获取更多操作可能
public NetworkFactory(Looper looper, Context context, String logTag,
NetworkCapabilities filter) {
super(looper);
LOG_TAG = logTag;
mContext = context;
mCapabilityFilter = filter;
}
构造函数除了NetworkCapabilities没什么特别的
/**
* Representation of the capabilities of an active network. Instances are
* typically obtained through
* {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)}
* or {@link ConnectivityManager#getNetworkCapabilities(Network)}.
*
* This replaces the old {@link ConnectivityManager#TYPE_MOBILE} method of
* network selection. Rather than indicate a need for Wi-Fi because an
* application needs high bandwidth and risk obsolescence when a new, fast
* network appears (like LTE), the application should specify it needs high
* bandwidth. Similarly if an application needs an unmetered network for a bulk
* transfer it can specify that rather than assuming all cellular based
* connections are metered and all Wi-Fi based connections are not.
*/
public final class NetworkCapabilities implements Parcelable {
看下WifiStateMachine传递来的NetworkCapabilities有什么特殊的
// Used to filter out requests we couldn't possibly satisfy.
private final NetworkCapabilities mNetworkCapabilitiesFilter = new NetworkCapabilities();
mNetworkCapabilitiesFilter.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED);
mNetworkCapabilitiesFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
mNetworkCapabilitiesFilter.setLinkUpstreamBandwidthKbps(1024 * 1024);
mNetworkCapabilitiesFilter.setLinkDownstreamBandwidthKbps(1024 * 1024);
暂时还不知道这个filter具体有什么用。
public void setScoreFilter(int score) {
sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
}
看下怎么处理的
/**
* Internally used to set our best-guess score.
* msg.arg1 = new score
*/
private static final int CMD_SET_SCORE = BASE + 2;
case CMD_SET_SCORE: {
handleSetScore(msg.arg1);
break;
}
private void handleSetScore(int score) {
mScore = score;
evalRequests();
}
private void evalRequests() {
for (int i = 0; i < mNetworkRequests.size(); i++) {
NetworkRequestInfo n = mNetworkRequests.valueAt(i);
evalRequest(n);
}
}
需要看下NetworkRequests是哪里初始化的,后面需要再看下evalRequest是怎么评估request的
public void register() {
if (DBG) log("Registering NetworkFactory");
if (mMessenger == null) {
mMessenger = new Messenger(this);
ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);
}
}
这个 register看起来就是和ConnectivityService建立了AsyncChannel通信通道
具体看下
ConnectivityManager
/** {@hide} */
public static ConnectivityManager from(Context context) {
return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
}
/** {@hide} */
public void registerNetworkFactory(Messenger messenger, String name) {
try {
mService.registerNetworkFactory(messenger, name);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
ConnectivityService
@Override
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));
}
/**
* used internally when registering NetworkFactories
* obj = NetworkFactoryInfo
*/
private static final int EVENT_REGISTER_NETWORK_FACTORY = 17;
case EVENT_REGISTER_NETWORK_FACTORY: {
handleRegisterNetworkFactory((NetworkFactoryInfo)msg.obj);
break;
}
看下具体处理逻辑
private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
mNetworkFactoryInfos.put(nfi.messenger, nfi);
nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
}
一堆注册其实就是将ConnectivityService和NetworkFactory之间通过AsyncChannel建立了跨进程通信
NetworkFactory
public void addNetworkRequest(NetworkRequest networkRequest, int score) {
sendMessage(obtainMessage(CMD_REQUEST_NETWORK,
new NetworkRequestInfo(networkRequest, score)));
}
/**
* Pass a network request to the bearer. If the bearer believes it can
* satisfy the request it should connect to the network and create a
* NetworkAgent. Once the NetworkAgent is fully functional it will
* register itself with ConnectivityService using registerNetworkAgent.
* If the bearer cannot immediately satisfy the request (no network,
* user disabled the radio, lower-scored network) it should remember
* any NetworkRequests it may be able to satisfy in the future. It may
* disregard any that it will never be able to service, for example
* those requiring a different bearer.
* msg.obj = NetworkRequest
* msg.arg1 = score - the score of the any network currently satisfying this
* request. If this bearer knows in advance it cannot
* exceed this score it should not try to connect, holding the request
* for the future.
* Note that subsequent events may give a different (lower
* or higher) score for this request, transmitted to each
* NetworkFactory through additional CMD_REQUEST_NETWORK msgs
* with the same NetworkRequest but an updated score.
* Also, network conditions may change for this bearer
* allowing for a better score in the future.
*/
public static final int CMD_REQUEST_NETWORK = BASE;
case CMD_REQUEST_NETWORK: {
handleAddRequest((NetworkRequest)msg.obj, msg.arg1);
break;
}
@VisibleForTesting
protected void handleAddRequest(NetworkRequest request, int score) {
NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
if (n == null) {
if (DBG) log("got request " + request + " with score " + score);
n = new NetworkRequestInfo(request, score);
mNetworkRequests.put(n.request.requestId, n);
} else {
if (VDBG) log("new score " + score + " for exisiting request " + request);
n.score = score;
}
if (VDBG) log(" my score=" + mScore + ", my filter=" + mCapabilityFilter);
evalRequest(n);
}
搜了framework下没有直接调用addNetworkRequest的,但是有通过AsyncChannel发送CMD_REQUEST_NETWORK消息的
ConnectivityService
private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
if (DBG) log("Got NetworkFactory Messenger for " + nfi.name);
mNetworkFactoryInfos.put(nfi.messenger, nfi);
nfi.asyncChannel.connect(mContext, mTrackerHandler, nfi.messenger);
}
// must be stateless - things change under us.
private class NetworkStateTrackerHandler extends Handler {
public NetworkStateTrackerHandler(Looper looper) {
super(looper);
}
private boolean maybeHandleAsyncChannelMessage(Message msg) {
switch (msg.what) {
default:
return false;
case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: {
handleAsyncChannelHalfConnect(msg);
break;
}
刚才有说道NetworkFactory和ConnectivityService通过AsyncChannel建立了通信通道,其实是ConnectivityService到NetworkFactory的单向通信通道,这时会调用handleAsyncChannelHalfConnect
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 = getNetworkForRequest(nri.request.requestId);
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);
}
}
handleAsyncChannelHalfConnect将ConnectivityService保存的所有mNetworkRequests都传递给了NetworkFactory
而ConnectivityService的NetworkRequest是通过两个api加载的
ConnectivityManager
/**
* Helper function to request a network with a particular legacy type.
*
* This is temporarily public @hide so it can be called by system code that uses the
* NetworkRequest API to request networks but relies on CONNECTIVITY_ACTION broadcasts for
* instead network notifications.
*
* TODO: update said system code to rely on NetworkCallbacks and make this method private.
*
* @hide
*/
public void requestNetwork(NetworkRequest request, NetworkCallback networkCallback,
int timeoutMs, int legacyType, Handler handler) {
CallbackHandler cbHandler = new CallbackHandler(handler);
NetworkCapabilities nc = request.networkCapabilities;
sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, legacyType, cbHandler);
}
/**
* Registers a PendingIntent to be sent when a network is available which satisfies the given
* {@link NetworkRequest}.
*
* This function behaves identically to the version that takes a NetworkCallback, but instead
* of {@link NetworkCallback} a {@link PendingIntent} is used. This means
* the request may outlive the calling application and get called back when a suitable
* network is found.
*
* The operation is an Intent broadcast that goes to a broadcast receiver that
* you registered with {@link Context#registerReceiver} or through the
* <receiver> tag in an AndroidManifest.xml file
*
* The operation Intent is delivered with two extras, a {@link Network} typed
* extra called {@link #EXTRA_NETWORK} and a {@link NetworkRequest}
* typed extra called {@link #EXTRA_NETWORK_REQUEST} containing
* the original requests parameters.
*
* If there is already a request for this Intent registered (with the equality of
* two Intents defined by {@link Intent#filterEquals}), then it will be removed and
* replaced by this one, effectively releasing the previous {@link NetworkRequest}.
*
* The request may be released normally by calling
* {@link #unregisterNetworkCallback(android.app.PendingIntent)}.
* @param request {@link NetworkRequest} describing this request.
* @param operation Action to perform when the network is available (corresponds
* to the {@link NetworkCallback#onAvailable} call. Typically
* comes from {@link PendingIntent#getBroadcast}. Cannot be null.
*/
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
public void registerNetworkCallback(NetworkRequest request, PendingIntent operation) {
checkPendingIntentNotNull(operation);
try {
mService.pendingListenForNetwork(request.networkCapabilities, operation);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
throw convertServiceException(e);
}
}
private void evalRequest(NetworkRequestInfo n) {
if (VDBG) log("evalRequest");
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");
}
}
看起来就是当前NetworkFactory满足请求方设置的条件话就设置网络,否则释放网络。
看下条件
看下satisfiedByNetworkCapabilities
/**
* Check if our requirements are satisfied by the given {@code NetworkCapabilities}.
*
* @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
* @param onlyImmutable if {@code true}, do not consider mutable requirements such as link
* bandwidth, signal strength, or validation / captive portal status.
*
* @hide
*/
private boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc, boolean onlyImmutable) {
return (nc != null
&& satisfiedByNetCapabilities(nc, onlyImmutable)
&& satisfiedByTransportTypes(nc)
&& (onlyImmutable || satisfiedByLinkBandwidths(nc))
&& satisfiedBySpecifier(nc)
&& (onlyImmutable || satisfiedBySignalStrength(nc))
&& (onlyImmutable || satisfiedByUids(nc))
&& (onlyImmutable || satisfiedBySSID(nc)));
}
再看下acceptRequest
/**
* Overridable function to provide complex filtering.
* Called for every request every time a new NetworkRequest is seen
* and whenever the filterScore or filterNetworkCapabilities change.
*
* acceptRequest can be overriden to provide complex filter behavior
* for the incoming requests
*
* For output, this class will call {@link #needNetworkFor} and
* {@link #releaseNetworkFor} for every request that passes the filters.
* If you don't need to see every request, you can leave the base
* implementations of those two functions and instead override
* {@link #startNetwork} and {@link #stopNetwork}.
*
* If you want to see every score fluctuation on every request, set
* your score filter to a very high number and watch {@link #needNetworkFor}.
*
* @return {@code true} to accept the request.
*/
public boolean acceptRequest(NetworkRequest request, int score) {
return true;
}
网络过滤的可重载的比较复杂的条件
NetworkFactory看起来就像是网络(WiFi/lte/...)用来存储“app层发送给ConnectivityService再发给NetworkFactory的NetworkRequest”,
并实时对NetworkRequest进行评估,对于WiFi而言,若可以满足app需要,则可以进行连接操作,否则无法进行连接。(因为既然都无法满足app的网络需求,那连接也是毫无意义的)