使用以太网做内网访问,wifi做外网访问,也就是说wifi的优先级应该比以太网高,当wifi内网无法访问时,才发切换到以太网使用
首先是准备
1、以下四个变量代表着安卓平台不同网络的评分,这些评分用于网络选择仲裁,评分越高就会优先选择。
NETWORK_SCORE, WIFI_BASE_SCORE, NETWORK_SCORE, TELEPHONY_NETWORK_SCORE
2、这四个变量分别出自如下安卓SDK文件:
NETWORK_SCORE 有两个网络都用这个定义,一个是以太网,另一个是蓝牙
a. 以太网如下:
./frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetNetworkFactory.java:97 private static final int NETWORK_SCORE = 70
b. 蓝牙的如下:
./packages/apps/Bluetooth/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactory.java:52 private static final int NETWORK_SCORE = 69;
c. Wifi的如下:
./frameworks/base/core/java/android/net/NetworkAgent.java:94 public static final int WIFI_BASE_SCORE = 60;
d. 移动网络的如下:
./frameworks/opt/telephony/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java:61 private final static int TELEPHONY_NETWORK_SCORE = 50;
3、从上面四种网络的评分,我们就知道了,安卓平台网络选择顺序:以太网,蓝牙PAN, WiFi, 最后移动网络。
下面是修改过程
evalRequest 方法 注释两行
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;
Log.d(TAG, "needNetworkFor");
} else if (n.requested == true &&
(n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities(
mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {
if (VDBG) log(" releaseNetworkFor");
Log.d(TAG, "releaseNetworkFor");
//releaseNetworkFor(n.request);//注释这一句
//n.requested = false;//注释这一句
} else {
if (VDBG) log(" done");
}
}
这样以太网和wifi都能连接成功
Android12及以上的网络策略不太一致
frameworks\opt\net\ethernet\java\com\android\server\ethernet\EthernetNetworkFactory.java
需要修改下面的得分
private static final SparseArray sTransports = new SparseArray();
static {
// LowpanInterfaceTracker.NETWORK_SCORE
sTransports.put(NetworkCapabilities.TRANSPORT_LOWPAN,
new TransportInfo(ConnectivityManager.TYPE_NONE, 30));
// WifiAwareDataPathStateManager.NETWORK_FACTORY_SCORE_AVAIL
sTransports.put(NetworkCapabilities.TRANSPORT_WIFI_AWARE,
new TransportInfo(ConnectivityManager.TYPE_NONE, 1));
// EthernetNetworkFactory.NETWORK_SCORE
sTransports.put(NetworkCapabilities.TRANSPORT_ETHERNET,
new TransportInfo(ConnectivityManager.TYPE_ETHERNET, 70));
// BluetoothTetheringNetworkFactory.NETWORK_SCORE
sTransports.put(NetworkCapabilities.TRANSPORT_BLUETOOTH,
new TransportInfo(ConnectivityManager.TYPE_BLUETOOTH, 69));
// WifiNetworkFactory.SCORE_FILTER / NetworkAgent.WIFI_BASE_SCORE
sTransports.put(NetworkCapabilities.TRANSPORT_WIFI,
new TransportInfo(ConnectivityManager.TYPE_WIFI, 60));
// TelephonyNetworkFactory.TELEPHONY_NETWORK_SCORE
sTransports.put(NetworkCapabilities.TRANSPORT_CELLULAR,
new TransportInfo(ConnectivityManager.TYPE_MOBILE, 50));
}
frameworks\libs\net\common\device\android\net\NetworkFactoryLegacyImpl.java
原因是updateAgent变了
Android 9
private void updateAgent() {
if (mNetworkAgent == null) return;
if (DBG) {
Log.i(TAG, "Updating mNetworkAgent with: " +
mCapabilities + ", " +
mNetworkInfo + ", " +
mLinkProperties);
}
mNetworkAgent.sendNetworkCapabilities(mCapabilities);
mNetworkAgent.sendNetworkInfo(mNetworkInfo);
mNetworkAgent.sendLinkProperties(mLinkProperties);
// never set the network score below 0.
mNetworkAgent.sendNetworkScore(mLinkUp? NETWORK_SCORE : 0);
}
Android12
private void updateAgent() {
if (mNetworkAgent == null) return;
if (DBG) {
Log.i(TAG, "Updating mNetworkAgent with: " +
mCapabilities + ", " +
mLinkProperties);
}
mNetworkAgent.sendNetworkCapabilities(mCapabilities);
mNetworkAgent.sendLinkProperties(mLinkProperties);
// As a note, getNetworkScore() is fairly expensive to calculate. This is fine for now
// since the agent isn't updated frequently. Consider caching the score in the future if
// agent updating is required more often
mNetworkAgent.sendNetworkScore(getNetworkScore());
}
/**
* Determines the network score based on the transport associated with the interface.
* Ethernet interfaces could propagate a transport types forward. Since we can't
* get more information about the statuses of the interfaces on the other end of the local
* interface, we'll best-effort assign the score as the base score of the assigned transport
* when the link is up. When the link is down, the score is set to zero.
*
* This function is called with the purpose of assigning and updating the network score of
* the member NetworkAgent.
*/
private int getNetworkScore() {
// never set the network score below 0.
if (!mLinkUp) {
return 0;
}
int[] transportTypes = mCapabilities.getTransportTypes();
if (transportTypes.length < 1) {
Log.w(TAG, "Network interface '" + mLinkProperties.getInterfaceName() + "' has no "
+ "transport type associated with it. Score set to zero");
return 0;
}
TransportInfo transportInfo = sTransports.get(transportTypes[0], /* if dne */ null);
if (transportInfo != null) {
return transportInfo.mScore;
}
return 0;
}
所谓共存就是让两个网络同时使用,如果想让哪个网络作为外网,则该网络优先级要高于内网的网络,即可达到外网用来上网的需求,那么要想共存,就必须到从低优先级网络切换到优先级高的网络时,不要做断开操作,即可达到,两个网络同时存在的需求,做到以上两点,我们便满足了2个网络同时存在,且使用优先级高的外网上网
到了android12已经废弃了这种直接的打分机制,使用了policy机制,具体可参考
packages/modules/Connectivity/service/src/com/android/server/connectivity/NetworkRanker.java
但由于这种评分机制涉及的条件比较多,对于我们做网络共存这个需求来说更加复杂,
对此android开发者也给我么预留了以前的评分方案,只要我们简单的将
USE_POLICY_RANKING = false; 即可
/**
* Find the best network satisfying this request among the list of passed networks.
*/
@Nullable
public NetworkAgentInfo getBestNetwork(@NonNull final NetworkRequest request,
@NonNull final Collection nais,
@Nullable final NetworkAgentInfo currentSatisfier) {
final ArrayList candidates = filter(nais, nai -> nai.satisfies(request));
if (candidates.size() == 1) return candidates.get(0); // Only one potential satisfier
if (candidates.size() <= 0) return null; // No network can satisfy this request
if (USE_POLICY_RANKING) {
return getBestNetworkByPolicy(candidates, currentSatisfier);
} else {
return getBestNetworkByLegacyInt(candidates);
}
}