ConnectivityManager的requestNetwork方法是一个用于请求满足特定条件的网络连接的方法。它通常在应用需要特定类型网络的情况下使用,例如需要大量数据传输时可能会请求一个高带宽的网络。当满足NetworkRequest的条件时,requestNetwork会尝试主动去连接到一个满足条件的网络。
通过ConnectivityManager和通过WifiManager连接网络的区别在于使用的API和功能。
通过ConnectivityManager连接网络是一种更通用的方法,它可以用于获取当前活动的网络连接信息,并可以根据需要切换网络连接。通过ConnectivityManager可以获取到网络的状态、类型、连接状态等信息,可以用于判断当前网络是否可用、判断网络类型(如WiFi、移动数据等)、监听网络连接状态的变化等。
而通过WifiManager连接网络则是针对WiFi网络的连接操作。WifiManager提供了一系列的方法,用于扫描可用的WiFi网络、连接指定的WiFi网络、断开当前连接的WiFi网络等。通过WifiManager可以实现WiFi网络的连接和管理,包括连接到指定的WiFi网络、获取当前连接的WiFi网络信息、获取已保存的WiFi网络列表等。
总结起来,通过ConnectivityManager连接网络更加通用,可以用于判断和管理各种类型的网络连接,而通过WifiManager连接网络则是针对WiFi网络的连接和管理
下面分析ConnectivityManager的requestNetwork方法:
//packages/modules/Connectivity/framework/src/android/net/ConnectivityManager.java
public class ConnectivityManager {
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback) {
requestNetwork(request, networkCallback, getDefaultHandler());
}
}
调用requestNetwork重载方法:
//packages/modules/Connectivity/framework/src/android/net/ConnectivityManager.java
public class ConnectivityManager {
public void requestNetwork(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
CallbackHandler cbHandler = new CallbackHandler(handler);
NetworkCapabilities nc = request.networkCapabilities;
sendRequestForNetwork(nc, networkCallback, 0, REQUEST, TYPE_NONE, cbHandler);
}
}
调用sendRequestForNetwork方法:
//packages/modules/Connectivity/framework/src/android/net/ConnectivityManager.java
public class ConnectivityManager {
private NetworkRequest sendRequestForNetwork(NetworkCapabilities need, NetworkCallback callback,
int timeoutMs, NetworkRequest.Type reqType, int legacyType, CallbackHandler handler) {
return sendRequestForNetwork(Process.INVALID_UID, need, callback, timeoutMs, reqType,
legacyType, handler);
}
}
调用sendRequestForNetwork重载方法:
//packages/modules/Connectivity/framework/src/android/net/ConnectivityManager.java
public class ConnectivityManager {
private final IConnectivityManager mService;
private NetworkRequest sendRequestForNetwork(int asUid, NetworkCapabilities need,
NetworkCallback callback, int timeoutMs, NetworkRequest.Type reqType, int legacyType,
CallbackHandler handler) {
printStackTrace();
checkCallbackNotNull(callback);
if (reqType != TRACK_DEFAULT && reqType != TRACK_SYSTEM_DEFAULT && need == null) {
throw new IllegalArgumentException("null NetworkCapabilities");
}
final NetworkRequest request;
final String callingPackageName = mContext.getOpPackageName();
try {
synchronized(sCallbacks) {
if (callback.networkRequest != null
&& callback.networkRequest != ALREADY_UNREGISTERED) {
// TODO: throw exception instead and enforce 1:1 mapping of callbacks
// and requests (http://b/20701525).
Log.e(TAG, "NetworkCallback was already registered");
}
Messenger messenger = new Messenger(handler);
Binder binder = new Binder();
final int callbackFlags = callback.mFlags;
if (reqType == LISTEN) {
request = mService.listenForNetwork(
need, messenger, binder, callbackFlags, callingPackageName,
getAttributionTag());
} else {
request = mService.requestNetwork(
asUid, need, reqType.ordinal(), messenger, timeoutMs, binder,
legacyType, callbackFlags, callingPackageName, getAttributionTag());
}
if (request != null) {
sCallbacks.put(request, callback);
}
callback.networkRequest = request;
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
throw convertServiceException(e);
}
return request;
}
}
调用IConnectivityManager的listenForNetwork和requestNetwork方法,IConnectivityManager是一个接口,由ConnectivityService实现,因此会调用ConnectivityService的listenForNetwork和requestNetwork方法。
ConnectivityService listenForNetwork
ConnectivityService的listenForNetwork方法:
//packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java
public class ConnectivityService extends IConnectivityManager.Stub implements PendingIntent.OnFinished {
public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
Messenger messenger, IBinder binder,
@NetworkCallback.Flag int callbackFlags,
@NonNull String callingPackageName, @NonNull String callingAttributionTag) {
final int callingUid = mDeps.getCallingUid();
if (!hasWifiNetworkListenPermission(networkCapabilities)) {
enforceAccessPermission();
}
NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
ensureSufficientPermissionsForRequest(networkCapabilities,
Binder.getCallingPid(), callingUid, callingPackageName);
restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName);
// Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
// make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
// onLost and onAvailable callbacks when networks move in and out of the background.
// There is no need to do this for requests because an app without CHANGE_NETWORK_STATE
// can't request networks.
restrictBackgroundRequestForCaller(nc);
ensureListenableCapabilities(nc);
NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
NetworkRequest.Type.LISTEN);
NetworkRequestInfo nri =
new NetworkRequestInfo(callingUid, networkRequest, messenger, binder, callbackFlags,
callingAttributionTag);
if (VDBG) log("listenForNetwork for " + nri);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
return networkRequest;
}
}
发送EVENT_REGISTER_NETWORK_LISTENER消息,消息在ConnectivityService的InternalHandler类的handleMessage方法中处理:
//packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java
public class ConnectivityService extends IConnectivityManager.Stub implements PendingIntent.OnFinished {
private class InternalHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_REGISTER_NETWORK_REQUEST:
case EVENT_REGISTER_NETWORK_LISTENER: {
handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
break;
}
}
}
}
handleRegisterNetworkRequest
调用handleRegisterNetworkRequest方法:
//packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java
public class ConnectivityService extends IConnectivityManager.Stub implements PendingIntent.OnFinished {
private void handleRegisterNetworkRequest(@NonNull final NetworkRequestInfo nri) {
handleRegisterNetworkRequests(Collections.singleton(nri));
}
}
调用handleRegisterNetworkRequests方法:
//packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java
public class ConnectivityService extends IConnectivityManager.Stub implements PendingIntent.OnFinished {
private void handleRegisterNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris) {
ensureRunningOnConnectivityServiceThread();
for (final NetworkRequestInfo nri : nris) {
mNetworkRequestInfoLogs.log("REGISTER " + nri);
checkNrisConsistency(nri);
for (final NetworkRequest req : nri.mRequests) {
mNetworkRequests.put(req, nri);
// TODO: Consider update signal strength for other types.
if (req.isListen()) {
for (final NetworkAgentInfo network : mNetworkAgentInfos) {
if (req.networkCapabilities.hasSignalStrength()
&& network.satisfiesImmutableCapabilitiesOf(req)) {
updateSignalStrengthThresholds(network, "REGISTER", req);
}
}
}
}
// If this NRI has a satisfier already, it is replacing an older request that
// has been removed. Track it.
final NetworkRequest activeRequest = nri.getActiveRequest();
if (null != activeRequest) {
// If there is an active request, then for sure there is a satisfier.
nri.getSatisfier().addRequest(activeRequest);
}
}
if (mFlags.noRematchAllRequestsOnRegister()) {
rematchNetworksAndRequests(nris);
} else {
rematchAllNetworksAndRequests();
}
// Requests that have not been matched to a network will not have been sent to the
// providers, because the old satisfier and the new satisfier are the same (null in this
// case). Send these requests to the providers.
for (final NetworkRequestInfo nri : nris) {
for (final NetworkOfferInfo noi : mNetworkOffers) {
informOffer(nri, noi.offer, mNetworkRanker);
}
}
}
}
ConnectivityService requestNetwork
ConnectivityService的requestNetwork方法用于请求网络,代码如下:
//packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java
public class ConnectivityService extends IConnectivityManager.Stub implements PendingIntent.OnFinished {
public NetworkRequest requestNetwork(int asUid, NetworkCapabilities networkCapabilities,
int reqTypeInt, Messenger messenger, int timeoutMs, final IBinder binder,
int legacyType, int callbackFlags, @NonNull String callingPackageName,
@Nullable String callingAttributionTag) {
if (legacyType != TYPE_NONE && !checkNetworkStackPermission()) {
if (isTargetSdkAtleast(Build.VERSION_CODES.M, mDeps.getCallingUid(),
callingPackageName)) {
throw new SecurityException("Insufficient permissions to specify legacy type");
}
}
final NetworkCapabilities defaultNc = mDefaultRequest.mRequests.get(0).networkCapabilities;
final int callingUid = mDeps.getCallingUid();
// Privileged callers can track the default network of another UID by passing in a UID.
if (asUid != Process.INVALID_UID) {
enforceSettingsPermission();
} else {
asUid = callingUid;
}
final NetworkRequest.Type reqType;
try {
reqType = NetworkRequest.Type.values()[reqTypeInt];
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException("Unsupported request type " + reqTypeInt);
}
switch (reqType) {
case TRACK_DEFAULT:
// If the request type is TRACK_DEFAULT, the passed {@code networkCapabilities}
// is unused and will be replaced by ones appropriate for the UID (usually, the
// calling app). This allows callers to keep track of the default network.
networkCapabilities = copyDefaultNetworkCapabilitiesForUid(
defaultNc, asUid, callingUid, callingPackageName);
enforceAccessPermission(); //强制执行访问权限
break;
case TRACK_SYSTEM_DEFAULT:
enforceSettingsPermission(); //强制执行设置权限
networkCapabilities = new NetworkCapabilities(defaultNc);
break;
case BACKGROUND_REQUEST:
enforceNetworkStackOrSettingsPermission(); //强制执行网络堆栈或设置权限
// Fall-through since other checks are the same with normal requests.
case REQUEST:
networkCapabilities = new NetworkCapabilities(networkCapabilities);
enforceNetworkRequestPermissions(networkCapabilities, callingPackageName,
callingAttributionTag, callingUid); //强制执行网络请求权限
// TODO: this is incorrect. We mark the request as metered or not depending on
// the state of the app when the request is filed, but we never change the
// request if the app changes network state. http://b/29964605
enforceMeteredApnPolicy(networkCapabilities); //实施按流量计费的APN策略
break;
case LISTEN_FOR_BEST:
enforceAccessPermission(); //强制执行访问权限
networkCapabilities = new NetworkCapabilities(networkCapabilities);
break;
default:
throw new IllegalArgumentException("Unsupported request type " + reqType);
}
ensureRequestableCapabilities(networkCapabilities); //确保可请求功能
ensureSufficientPermissionsForRequest(networkCapabilities,
Binder.getCallingPid(), callingUid, callingPackageName); //确保请求的足够权限
// Enforce FOREGROUND if the caller does not have permission to use background network.
if (reqType == LISTEN_FOR_BEST) {
restrictBackgroundRequestForCaller(networkCapabilities);
}
// Set the UID range for this request to the single UID of the requester, unless the
// requester has the permission to specify other UIDs.
// This will overwrite any allowed UIDs in the requested capabilities. Though there
// are no visible methods to set the UIDs, an app could use reflection to try and get
// networks for other apps so it's essential that the UIDs are overwritten.
// Also set the requester UID and package name in the request.
restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities,
callingUid, callingPackageName); //将此请求的 UID 范围设置为请求者的单个 UID,除非请求者有权指定其他 UID
if (timeoutMs < 0) {
throw new IllegalArgumentException("Bad timeout specified");
}
final NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
nextNetworkRequestId(), reqType); //创建NetworkRequest对象
final NetworkRequestInfo nri = getNriToRegister(
asUid, networkRequest, messenger, binder, callbackFlags,
callingAttributionTag); //取得NetworkRequestInfo对象
if (DBG) log("requestNetwork for " + nri);
// For TRACK_SYSTEM_DEFAULT callbacks, the capabilities have been modified since they were
// copied from the default request above. (This is necessary to ensure, for example, that
// the callback does not leak sensitive information to unprivileged apps.) Check that the
// changes don't alter request matching.
if (reqType == NetworkRequest.Type.TRACK_SYSTEM_DEFAULT &&
(!networkCapabilities.equalRequestableCapabilities(defaultNc))) {
throw new IllegalStateException(
"TRACK_SYSTEM_DEFAULT capabilities don't match default request: "
+ networkCapabilities + " vs. " + defaultNc);
}
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri)); //发送EVENT_REGISTER_NETWORK_REQUEST消息
if (timeoutMs > 0) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NETWORK_REQUEST,
nri), timeoutMs); //发送EVENT_TIMEOUT_NETWORK_REQUEST消息
}
return networkRequest;
}
}
发送EVENT_REGISTER_NETWORK_REQUEST和EVENT_TIMEOUT_NETWORK_REQUEST消息,消息在ConnectivityService的InternalHandler类的handleMessage方法中处理:
//packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java
public class ConnectivityService extends IConnectivityManager.Stub implements PendingIntent.OnFinished {
private class InternalHandler extends Handler {
public void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_REGISTER_NETWORK_REQUEST:
case EVENT_REGISTER_NETWORK_LISTENER: {
handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj);
break;
}
case EVENT_TIMEOUT_NETWORK_REQUEST: {
NetworkRequestInfo nri = (NetworkRequestInfo) msg.obj;
handleTimedOutNetworkRequest(nri);
break;
}
}
}
}
handleRegisterNetworkRequest
调用handleRegisterNetworkRequest方法:
//packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java
public class ConnectivityService extends IConnectivityManager.Stub implements PendingIntent.OnFinished {
private void handleRegisterNetworkRequest(@NonNull final NetworkRequestInfo nri) {
handleRegisterNetworkRequests(Collections.singleton(nri));
}
}
调用handleRegisterNetworkRequests方法:
//packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java
public class ConnectivityService extends IConnectivityManager.Stub implements PendingIntent.OnFinished {
private void handleRegisterNetworkRequests(@NonNull final Set<NetworkRequestInfo> nris) {
ensureRunningOnConnectivityServiceThread();
for (final NetworkRequestInfo nri : nris) {
mNetworkRequestInfoLogs.log("REGISTER " + nri);
checkNrisConsistency(nri);
for (final NetworkRequest req : nri.mRequests) {
mNetworkRequests.put(req, nri);
// TODO: Consider update signal strength for other types.
if (req.isListen()) {
for (final NetworkAgentInfo network : mNetworkAgentInfos) {
if (req.networkCapabilities.hasSignalStrength()
&& network.satisfiesImmutableCapabilitiesOf(req)) {
updateSignalStrengthThresholds(network, "REGISTER", req);
}
}
}
}
// If this NRI has a satisfier already, it is replacing an older request that
// has been removed. Track it.
final NetworkRequest activeRequest = nri.getActiveRequest();
if (null != activeRequest) {
// If there is an active request, then for sure there is a satisfier.
nri.getSatisfier().addRequest(activeRequest);
}
}
if (mFlags.noRematchAllRequestsOnRegister()) {
rematchNetworksAndRequests(nris);
} else {
rematchAllNetworksAndRequests();
}
// Requests that have not been matched to a network will not have been sent to the
// providers, because the old satisfier and the new satisfier are the same (null in this
// case). Send these requests to the providers.
for (final NetworkRequestInfo nri : nris) {
for (final NetworkOfferInfo noi : mNetworkOffers) {
informOffer(nri, noi.offer, mNetworkRanker);
}
}
}
}
handleTimedOutNetworkRequest
调用handleTimedOutNetworkRequest方法:
//packages/modules/Connectivity/service/src/com/android/server/ConnectivityService.java
public class ConnectivityService extends IConnectivityManager.Stub implements PendingIntent.OnFinished {
private void handleTimedOutNetworkRequest(@NonNull final NetworkRequestInfo nri) {
ensureRunningOnConnectivityServiceThread();
// handleTimedOutNetworkRequest() is part of the requestNetwork() flow which works off of a
// single NetworkRequest and thus does not apply to multilayer requests.
ensureNotMultilayerRequest(nri, "handleTimedOutNetworkRequest");
if (mNetworkRequests.get(nri.mRequests.get(0)) == null) {
return;
}
if (nri.isBeingSatisfied()) {
return;
}
if (VDBG || (DBG && nri.mRequests.get(0).isRequest())) {
log("releasing " + nri.mRequests.get(0) + " (timeout)");
}
handleRemoveNetworkRequest(nri);
callCallbackForRequest(
nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
}
}