android14双网共存和网络优先级
system-netd-server-rooutecontroller.patch
diff --git a/server/RouteController.cpp b/server/RouteController.cpp
index 97ca84e9..91f19607 100644
--- a/server/RouteController.cpp
+++ b/server/RouteController.cpp
@@ -777,6 +777,18 @@ int RouteController::modifyVpnFallthroughRule(uint16_t action, unsigned vpnNetId
fwmark.intValue, mask.intValue);
}
+
+// added by cgt ethernet and wifi coexist start
+// Add a new rule to look up the 'main' table, with the same selectors as the "default network"
+// rule, but with a lower priority. We will never create routes in the main table; it should only be
+// used for directly-connected routes implicitly created by the kernel when adding IP addresses.
+// This is necessary, for example, when adding a route through a directly-connected gateway: in
+// order to add the route, there must already be a directly-connected route that covers the gateway.
+[[nodiscard]] static int addDirectlyConnectedRule() {
+ return modifyIpRule(RTM_NEWRULE, RULE_PRIORITY_DIRECTLY_CONNECTED, RT_TABLE_MAIN,
+ MARK_UNSET, MARK_UNSET, IIF_NONE, OIF_NONE, INVALID_UID, INVALID_UID);
+}
+
/* static */
int RouteController::configureDummyNetwork() {
const char *interface = DummyNetwork::INTERFACE_NAME;
@@ -1305,6 +1317,9 @@ int RouteController::Init(unsigned localNetId) {
if (int ret = addLocalNetworkRules(localNetId)) {
return ret;
}
+ if (int ret = addDirectlyConnectedRule()) {
+ return ret;
+ }
if (int ret = addUnreachableRule()) {
return ret;
}
diff --git a/server/RouteController.h b/server/RouteController.h
index a56d4e05..501a1b2b 100644
--- a/server/RouteController.h
+++ b/server/RouteController.h
@@ -43,6 +43,7 @@ constexpr int32_t RULE_PRIORITY_PROHIBIT_NON_VPN = 14000;
// not have the necessary permission bits in the fwmark. We cannot just give any socket on any of
// these networks the permission bits, because if the UID that created the socket loses access to
// the network, then the socket must not match any rule that selects that network.
+constexpr int32_t RULE_PRIORITY_DIRECTLY_CONNECTED = 9999;
constexpr int32_t RULE_PRIORITY_UID_EXPLICIT_NETWORK = 15000;
constexpr int32_t RULE_PRIORITY_EXPLICIT_NETWORK = 16000;
constexpr int32_t RULE_PRIORITY_OUTPUT_INTERFACE = 17000;
connectivity.path
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 193bd920d2..7e4494a1c0 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -73,12 +73,14 @@ package android.net {
public class ConnectivitySettingsManager {
method public static void clearGlobalProxy(@NonNull android.content.Context);
+ method public static boolean getBluetoothAlwaysRequested(@NonNull android.content.Context, boolean);
method @Nullable public static String getCaptivePortalHttpUrl(@NonNull android.content.Context);
method public static int getCaptivePortalMode(@NonNull android.content.Context, int);
method @NonNull public static java.time.Duration getConnectivityKeepPendingIntentDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
method @NonNull public static android.util.Range<java.lang.Integer> getDnsResolverSampleRanges(@NonNull android.content.Context);
method @NonNull public static java.time.Duration getDnsResolverSampleValidityDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
method public static int getDnsResolverSuccessThresholdPercent(@NonNull android.content.Context, int);
+ method public static boolean getEthernetAlwaysRequested(@NonNull android.content.Context, boolean);
method @Nullable public static android.net.ProxyInfo getGlobalProxy(@NonNull android.content.Context);
method public static long getIngressRateLimitInBytesPerSecond(@NonNull android.content.Context);
method @NonNull public static java.time.Duration getMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
@@ -94,12 +96,14 @@ package android.net {
method @NonNull public static java.util.Set<java.lang.Integer> getUidsAllowedOnRestrictedNetworks(@NonNull android.content.Context);
method public static boolean getWifiAlwaysRequested(@NonNull android.content.Context, boolean);
method @NonNull public static java.time.Duration getWifiDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
+ method public static void setBluetoothAlwaysRequested(@NonNull android.content.Context, boolean);
method public static void setCaptivePortalHttpUrl(@NonNull android.content.Context, @Nullable String);
method public static void setCaptivePortalMode(@NonNull android.content.Context, int);
method public static void setConnectivityKeepPendingIntentDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
method public static void setDnsResolverSampleRanges(@NonNull android.content.Context, @NonNull android.util.Range<java.lang.Integer>);
method public static void setDnsResolverSampleValidityDuration(@NonNull android.content.Context, @NonNull java.time.Duration);
method public static void setDnsResolverSuccessThresholdPercent(@NonNull android.content.Context, @IntRange(from=0, to=100) int);
+ method public static void setEthernetAlwaysRequested(@NonNull android.content.Context, boolean);
method public static void setGlobalProxy(@NonNull android.content.Context, @NonNull android.net.ProxyInfo);
method public static void setIngressRateLimitInBytesPerSecond(@NonNull android.content.Context, @IntRange(from=-1L, to=4294967295L) long);
method public static void setMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
@@ -115,9 +119,11 @@ package android.net {
method public static void setUidsAllowedOnRestrictedNetworks(@NonNull android.content.Context, @NonNull java.util.Set<java.lang.Integer>);
method public static void setWifiAlwaysRequested(@NonNull android.content.Context, boolean);
method public static void setWifiDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
+ field public static final String BLUETOOTH_ALWAYS_REQUESTED = "bluetooth_always_requested";
field public static final int CAPTIVE_PORTAL_MODE_AVOID = 2; // 0x2
field public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0; // 0x0
field public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1; // 0x1
+ field public static final String ETHERNET_ALWAYS_REQUESTED = "ethernet_always_requested";
field public static final int NETWORK_AVOID_BAD_WIFI_AVOID = 2; // 0x2
field public static final int NETWORK_AVOID_BAD_WIFI_IGNORE = 0; // 0x0
field public static final int NETWORK_AVOID_BAD_WIFI_PROMPT = 1; // 0x1
diff --git a/framework/src/android/net/ConnectivitySettingsManager.java b/framework/src/android/net/ConnectivitySettingsManager.java
index 822e67d339..8ef43a9a18 100644
--- a/framework/src/android/net/ConnectivitySettingsManager.java
+++ b/framework/src/android/net/ConnectivitySettingsManager.java
@@ -291,6 +291,10 @@ public class ConnectivitySettingsManager {
*/
public static final String WIFI_ALWAYS_REQUESTED = "wifi_always_requested";
+
+ public static final String ETHERNET_ALWAYS_REQUESTED = "ethernet_always_requested";
+
+ public static final String BLUETOOTH_ALWAYS_REQUESTED = "bluetooth_always_requested";
/**
* Whether to automatically switch away from wifi networks that lose Internet access.
* Only meaningful if config_networkAvoidBadWifi is set to 0, otherwise the system always
@@ -902,6 +906,64 @@ public class ConnectivitySettingsManager {
context.getContentResolver(), WIFI_ALWAYS_REQUESTED, (enable ? 1 : 0));
}
+ /**
+ * Read from {@link Settings} whether the ethernet data connection should remain active
+ * even when higher priority networks are active.
+ *
+ * @param context The {@link Context} to query the setting.
+ * @param def The default value if no setting value.
+ * @return Whether the ethernet data connection should remain active even when higher
+ * priority networks are active.
+ */
+ public static boolean getEthernetAlwaysRequested(@NonNull Context context, boolean def) {
+ final int enable = Settings.Global.getInt(
+ context.getContentResolver(), ETHERNET_ALWAYS_REQUESTED, (def ? 1 : 0));
+ return (enable != 0) ? true : false;
+ }
+
+ /**
+ * Write into {@link Settings} whether the ethernet data connection should remain active
+ * even when higher priority networks are active.
+ *
+ * @param context The {@link Context} to set the setting.
+ * @param enable Whether the ethernet data connection should remain active even when higher
+ * priority networks are active
+ */
+ public static void setEthernetAlwaysRequested(@NonNull Context context, boolean enable) {
+ Settings.Global.putInt(
+ context.getContentResolver(), ETHERNET_ALWAYS_REQUESTED, (enable ? 1 : 0));
+ }
+
+/**
+ * Read from {@link Settings} whether the bluetooth data connection should remain active
+ * even when higher priority networks are active.
+ *
+ * @param context The {@link Context} to query the setting.
+ * @param def The default value if no setting value.
+ * @return Whether the bluetooth data connection should remain active even when higher
+ * priority networks are active.
+ */
+public static boolean getBluetoothAlwaysRequested(@NonNull Context context, boolean def) {
+ final int enable = Settings.Global.getInt(
+ context.getContentResolver(), BLUETOOTH_ALWAYS_REQUESTED, (def ? 1 : 0));
+ return (enable != 0) ? true : false;
+}
+
+/**
+ * Write into {@link Settings} whether the bluetooth data connection should remain active
+ * even when higher priority networks are active.
+ *
+ * @param context The {@link Context} to set the setting.
+ * @param enable Whether the bluetooth data connection should remain active even when higher
+ * priority networks are active
+ */
+public static void setBluetoothAlwaysRequested(@NonNull Context context, boolean enable) {
+ Settings.Global.putInt(
+ context.getContentResolver(), BLUETOOTH_ALWAYS_REQUESTED, (enable ? 1 : 0));
+}
+
+
+
/**
* Get avoid bad wifi setting from {@link Settings}.
*
diff --git a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
index 59b50bb6f9..c9c458e0b8 100644
--- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
+++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
@@ -742,6 +742,16 @@ public class EthernetNetworkFactory {
if (mNetworkOfferCallback == null) {
mNetworkOfferCallback = new EthernetNetworkOfferCallback();
}
+
+ if(name!=null && name.equals("eth1")){
+
+ //mCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ mCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ //mCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
+ Log.d(TAG, "hcq mCapabilities: " + mCapabilities);
+ }
+
+
mNetworkProvider.registerNetworkOffer(getNetworkScore(),
new NetworkCapabilities(mCapabilities), cmd -> mHandler.post(cmd),
mNetworkOfferCallback);
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index 120486c1df..4a86b2c040 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -357,8 +357,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
private static final String TRAFFICCONTROLLER_ARG = "trafficcontroller";
private static final boolean DBG = true;
- private static final boolean DDBG = Log.isLoggable(TAG, Log.DEBUG);
- private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
+ private static final boolean DDBG = true; //Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean VDBG = true; //Log.isLoggable(TAG, Log.VERBOSE);
private static final boolean LOGD_BLOCKED_NETWORKINFO = true;
@@ -1608,6 +1608,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
mDefaultVehicleRequest = createAlwaysOnRequestForCapability(
NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL,
NetworkRequest.Type.BACKGROUND_REQUEST);
+
+ mDefaultEthernetRequest = createDefaultInternetRequestForTransport(
+ NetworkCapabilities.TRANSPORT_ETHERNET, NetworkRequest.Type.BACKGROUND_REQUEST);
+
+ mDefaultBluetoothRequest = createDefaultInternetRequestForTransport(
+ NetworkCapabilities.TRANSPORT_BLUETOOTH, NetworkRequest.Type.BACKGROUND_REQUEST);
mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
// TODO: Consider making the timer customizable.
@@ -1928,10 +1934,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
handleAlwaysOnNetworkRequest(mDefaultMobileDataRequest,
ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON, true /* defaultValue */);
handleAlwaysOnNetworkRequest(mDefaultWifiRequest,
- ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED, false /* defaultValue */);
+ ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED, true /* defaultValue */);
final boolean vehicleAlwaysRequested = mResources.get().getBoolean(
R.bool.config_vehicleInternalNetworkAlwaysRequested);
handleAlwaysOnNetworkRequest(mDefaultVehicleRequest, vehicleAlwaysRequested);
+
+ handleAlwaysOnNetworkRequest(mDefaultEthernetRequest,
+ ConnectivitySettingsManager.ETHERNET_ALWAYS_REQUESTED, true /* defaultValue */);
+
+ handleAlwaysOnNetworkRequest(mDefaultEthernetRequest,
+ ConnectivitySettingsManager.BLUETOOTH_ALWAYS_REQUESTED, true /* defaultValue */);
}
// Note that registering observer for setting do not get initial callback when registering,
@@ -1962,6 +1974,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
Settings.Global.getUriFor(
ConnectivitySettingsManager.INGRESS_RATE_LIMIT_BYTES_PER_SECOND),
EVENT_INGRESS_RATE_LIMIT_CHANGED);
+
+ // Watch for whether to keep ethernet always on.
+ mSettingsObserver.observe(
+ Settings.Global.getUriFor(ConnectivitySettingsManager.ETHERNET_ALWAYS_REQUESTED),
+ EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
}
private void registerPrivateDnsSettingsCallbacks() {
@@ -4925,6 +4942,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
private boolean unneeded(NetworkAgentInfo nai, UnneededFor reason) {
ensureRunningOnConnectivityServiceThread();
+ boolean needed = nai.isWIFI();
+ if(needed)
+ return false;
+
if (!nai.everConnected() || nai.isVPN() || nai.isInactive()
|| nai.getScore().getKeepConnectedReason() != NetworkScore.KEEP_CONNECTED_NONE) {
return false;
@@ -7751,6 +7772,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Request used to optionally keep vehicle internal network always active
private final NetworkRequest mDefaultVehicleRequest;
+ private final NetworkRequest mDefaultEthernetRequest;
+
+ private final NetworkRequest mDefaultBluetoothRequest;
// Sentinel NAI used to direct apps with default networks that should have no connectivity to a
// network with no service. This NAI should never be matched against, nor should any public API
// ever return the associated network. For this reason, this NAI is not in the list of available
@@ -9044,7 +9068,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
}
- nai.disconnect();
+ // nai.disconnect();
}
private void handleLingerComplete(NetworkAgentInfo oldNetwork) {
diff --git a/service/src/com/android/server/connectivity/NetworkAgentInfo.java b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
index 85282cbc9b..b6cc1b7b75 100644
--- a/service/src/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/service/src/com/android/server/connectivity/NetworkAgentInfo.java
@@ -1181,6 +1181,15 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
}
+ /** Whether this network is a WIFI. */
+ public boolean isWIFI() {
+ return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
+ }
+
+ /** Whether this network is a ETHERNET. */
+ public boolean isETHERNET() {
+ return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET);
+ }
/**
* Whether this network should propagate the capabilities from its underlying networks.
* Currently only true for VPNs.
diff --git a/service/src/com/android/server/connectivity/NetworkRanker.java b/service/src/com/android/server/connectivity/NetworkRanker.java
index d94c8dceeb..d1f1a9082f 100644
--- a/service/src/com/android/server/connectivity/NetworkRanker.java
+++ b/service/src/com/android/server/connectivity/NetworkRanker.java
@@ -50,11 +50,17 @@ import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
+import android.util.Log;
+import android.os.SystemProperties;
/**
* A class that knows how to find the best network matching a request out of a list of networks.
*/
public class NetworkRanker {
+ private static final String TAG = "NetworkRanker";
+ private static final String PERSIST_NET_PREFERRED_TRANSPORTS_ORDER = "persist.net.preferred.transports.order";
+
+ private static int[] preferredTransportsOrder;
/**
* Home for all configurations of NetworkRanker
*/
@@ -118,10 +124,63 @@ public class NetworkRanker {
return getBestNetworkByPolicy(candidates, currentSatisfier);
}
+ //public static final int TRANSPORT_BLUETOOTH = 2;
+ //public static final int TRANSPORT_CELLULAR = 0;
+ //public static final int TRANSPORT_ETHERNET = 3;
+ //public static final int TRANSPORT_WIFI = 1;
+
+
// Transport preference order, if it comes down to that.
- private static final int[] PREFERRED_TRANSPORTS_ORDER = { TRANSPORT_ETHERNET, TRANSPORT_WIFI,
+ private static int[] PREFERRED_TRANSPORTS_ORDER = { TRANSPORT_ETHERNET, TRANSPORT_WIFI,
TRANSPORT_BLUETOOTH, TRANSPORT_CELLULAR };
+ private static int[] parseTransportsOrder(String transportsOrderStr) {
+ String[] transportStrings = transportsOrderStr.split(",");
+ int[] transportsOrder = new int[transportStrings.length];
+
+ for (int i = 0; i < transportStrings.length; i++) {
+ try {
+ int transport = Integer.parseInt(transportStrings[i].trim());
+ switch (transport) {
+ case TRANSPORT_BLUETOOTH:
+ case TRANSPORT_CELLULAR:
+ case TRANSPORT_ETHERNET:
+ case TRANSPORT_WIFI:
+ transportsOrder[i] = transport;
+ break;
+ default:
+ Log.w(TAG, "Invalid transport value: " + transport);
+ return null;
+ }
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Invalid transport format: " + transportsOrderStr);
+ return null;
+ }
+ }
+
+ return transportsOrder;
+ }
+
+
+ static void getPreferredTransportsOrder() {
+ String transportsOrderStr = SystemProperties.get(PERSIST_NET_PREFERRED_TRANSPORTS_ORDER);
+ if (transportsOrderStr == null || transportsOrderStr.isEmpty()) {
+ Log.w(TAG, "No preferred transports order set, using default.");
+ return;
+ }
+
+ preferredTransportsOrder = parseTransportsOrder(transportsOrderStr);
+ if (preferredTransportsOrder == null) {
+ Log.e(TAG, "Failed to parse the transports order string.");
+ return;
+ }
+
+ Log.i(TAG, "Preferred transports order set to: " + Arrays.toString(preferredTransportsOrder));
+
+
+ }
+
+
// Function used to partition a list into two working areas depending on whether they
// satisfy a predicate. All items satisfying the predicate will be put in |positive|, all
// items that don't will be put in |negative|.
@@ -324,6 +383,12 @@ public class NetworkRanker {
// change from the previous result. If there were, it's guaranteed candidates.size() > 0
// because accepted.size() > 0 above.
+ getPreferredTransportsOrder();
+
+ if(preferredTransportsOrder != null)
+ PREFERRED_TRANSPORTS_ORDER = preferredTransportsOrder;
+
+ Log.i(TAG, "Confirm candidates transports order" + Arrays.toString(PREFERRED_TRANSPORTS_ORDER));
// If some of the networks have a better transport than others, keep only the ones with
// the best transports.
for (final int transport : PREFERRED_TRANSPORTS_ORDER) {
@@ -381,6 +446,12 @@ public class NetworkRanker {
// If there is no satisfying network, then this network can beat, because some network
// is always better than no network.
if (null == champion) return true;
+
+ boolean needed = contestant.getCapsNoCopy().hasTransport(TRANSPORT_WIFI);
+
+ if(needed)
+ return true;
+
// If there is no champion, the offer can always beat.
// Otherwise rank them.
final ArrayList<Scoreable> candidates = new ArrayList<>();
使用
public static final int TRANSPORT_BLUETOOTH = 2;
public static final int TRANSPORT_CELLULAR = 0;
public static final int TRANSPORT_ETHERNET = 3;
public static final int TRANSPORT_WIFI = 1;
1、//以太网优先 > WIFI> 4G>蓝牙
setprop persist.net.preferred.transports.order “3,1,0,2”
2、//4G优先>WIFI>以太网>BLUETOOTH
setprop persist.net.preferred.transports.order “0,1,3,2”
3、// wifi优先 >4G>以太网>蓝牙 -->存在BUG
setprop persist.net.preferred.transports.order “1,0,3,2”
logcat -s NetworkRanker
11-08 02:05:57.555 705 849 I NetworkRanker: Preferred transports order set to: [0, 1, 3, 2]
11-08 02:05:57.555 705 849 I NetworkRanker: Confirm candidates transports order[0, 1, 3, 2]
这个修改是eth1一直作内网用
cd packages/modules/Connectivity
--- a/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
+++ b/service-t/src/com/android/server/ethernet/EthernetNetworkFactory.java
@@ -742,6 +742,16 @@ public class EthernetNetworkFactory {
if (mNetworkOfferCallback == null) {
mNetworkOfferCallback = new EthernetNetworkOfferCallback();
}
+
+ if(name!=null && name.equals("eth1")){
+
+ //mCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ //mCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ mCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
+ Log.d(TAG, "hcq mCapabilities: " + mCapabilities);
+ }
如果编译报错,建议去掉framework/api/module-lib-current.txt,
make update-api 自己更新