让我们从最开始的enableWifi开始分析
public boolean enableNetwork(int netId, boolean disableOthers) {
final boolean pin = disableOthers && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP;
if (pin) {
NetworkRequest request = new NetworkRequest.Builder()
.clearCapabilities()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build();
NetworkPinner.pin(mContext, request);
}
boolean success;
try {
success = mService.enableNetwork(netId, disableOthers);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
if (pin && !success) {
NetworkPinner.unpin();
}
return success;
}
Android 4.4的enableNetwork
public boolean enableNetwork(int netId, boolean disableOthers) {
try {
return mService.enableNetwork(netId, disableOthers);
} catch (RemoteException e) {
return false;
}
}
通过binder机制调用了WifiManagerService的enableNetwork方法,对比Android 4.4的源码我们发现Android最新源码多了NetworkPinner,我们先来分析一下NetworkPinner的作用。如果disableOthers为TRUE && Tartget版本低于Android5.0, pin 为TRUE,可能跟Android 5.0之前版本兼容有关,我们看一下NetworkPinner的介绍。
/**
* A class that pins a process to the first network that satisfies a particular NetworkRequest.
*
* We use this to maintain compatibility with pre-M apps that call WifiManager.enableNetwork()
* to connect to a Wi-Fi network that has no Internet access, and then assume that they will be
* able to use that network because it's the system default.
*
* In order to maintain compatibility with apps that call setProcessDefaultNetwork themselves,
* we try not to set the default network unless they have already done so, and we try not to
* clear the default network unless we set it ourselves.
*
* This should maintain behaviour that's compatible with L, which would pin the whole system to
* any wifi network that was created via enableNetwork(..., true) until that network
* disconnected.
*
* Note that while this hack allows network traffic to flow, it is quite limited. For example:
*
* 1. setProcessDefaultNetwork only affects this process, so:
* - Any subprocesses spawned by this process will not be pinned to Wi-Fi.
* - If this app relies on any other apps on the device also being on Wi-Fi, that won't work
* either, because other apps on the device will not be pinned.
* 2. The behaviour of other APIs is not modified. For example:
* - getActiveNetworkInfo will return the system default network, not Wi-Fi.
* - There will be no CONNECTIVITY_ACTION broadcasts about TYPE_WIFI.
* - getProcessDefaultNetwork will not return null, so if any apps are relying on that, they
* will be surprised as well.
*
* This class is a per-process singleton because the process default network is a per-process
* singleton.
*
*/
public boolean enableNetwork(int netId, boolean disableOthers) {
enforceChangePermission();
if (mWifiStateMachineChannel != null) {
return mWifiStateMachine.syncEnableNetwork(mWifiStateMachineChannel, netId,
disableOthers);
} else {
Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
return false;
}
}
public boolean syncEnableNetwork(AsyncChannel channel, int netId, boolean disableOthers) {
Message resultMsg = channel.sendMessageSynchronously(CMD_ENABLE_NETWORK, netId,
disableOthers ? 1 : 0);
boolean result = (resultMsg.arg1 != FAILURE);
resultMsg.recycle();
return result;
}
我们看到了AsyncChannel,在WifiManager中也出现了,但是并没有被启用,因为启用它的方法都变成了hide,Android 的WiFi机制将消息系统从Proxy移到了Stub。
private class WifiStateMachineHandler extends Handler