diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java index b6240c4561..dd0d5679a1 100644 --- a/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java +++ b/Tethering/src/com/android/networkstack/tethering/TetheringConfiguration.java @@ -23,6 +23,8 @@ import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; +import static com.android.net.module.util.DeviceConfigUtils.TETHERING_MODULE_NAME; + import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; @@ -60,8 +62,6 @@ public class TetheringConfiguration { private static final String[] EMPTY_STRING_ARRAY = new String[0]; - private static final String TETHERING_MODULE_NAME = "com.android.tethering"; - // Default ranges used for the legacy DHCP server. // USB is 192.168.42.1 and 255.255.255.0 // Wifi is 192.168.43.1 and 255.255.255.0 diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index 9e88890234..222f5c8379 100644 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -87,9 +87,12 @@ import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired; import static android.os.Process.INVALID_UID; import static android.os.Process.VPN_UID; +import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; +import static com.android.net.module.util.DeviceConfigUtils.TETHERING_MODULE_NAME; + import static java.util.Map.Entry; import android.Manifest; @@ -232,6 +235,7 @@ import com.android.modules.utils.BasicShellCommandHandler; import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.BaseNetdUnsolicitedEventListener; import com.android.net.module.util.CollectionUtils; +import com.android.net.module.util.DeviceConfigUtils; import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult; import com.android.net.module.util.LinkPropertiesUtils.CompareResult; import com.android.net.module.util.LocationPermissionChecker; @@ -239,6 +243,7 @@ import com.android.net.module.util.NetworkCapabilitiesUtils; import com.android.net.module.util.PermissionUtils; import com.android.net.module.util.netlink.InetDiagMessage; import com.android.server.connectivity.AutodestructReference; +import com.android.server.connectivity.ConnectivityFlags; import com.android.server.connectivity.DnsManager; import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate; import com.android.server.connectivity.FullScore; @@ -371,6 +376,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // The Context is created for UserHandle.ALL. private final Context mUserAllContext; private final Dependencies mDeps; + private final ConnectivityFlags mFlags; // 0 is full bad, 100 is full good private int mDefaultInetConditionPublished = 0; @@ -1309,6 +1315,14 @@ public class ConnectivityService extends IConnectivityManager.Stub public LocationPermissionChecker makeLocationPermissionChecker(Context context) { return new LocationPermissionChecker(context); } + + /** + * @see DeviceConfigUtils#isFeatureEnabled + */ + public boolean isFeatureEnabled(Context context, String name, boolean defaultEnabled) { + return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name, + TETHERING_MODULE_NAME, defaultEnabled); + } } public ConnectivityService(Context context) { @@ -1323,6 +1337,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (DBG) log("ConnectivityService starting up"); mDeps = Objects.requireNonNull(deps, "missing Dependencies"); + mFlags = new ConnectivityFlags(); mSystemProperties = mDeps.getSystemProperties(); mNetIdManager = mDeps.makeNetIdManager(); mContext = Objects.requireNonNull(context, "missing Context"); @@ -2790,6 +2805,9 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @VisibleForTesting public void systemReadyInternal() { + // Load flags after PackageManager is ready to query module version + mFlags.loadFlags(mDeps, mContext); + // Since mApps in PermissionMonitor needs to be populated first to ensure that // listening network request which is sent by MultipathPolicyTracker won't be added // NET_CAPABILITY_FOREGROUND capability. Thus, MultipathPolicyTracker.start() must @@ -4101,7 +4119,11 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - rematchAllNetworksAndRequests(); + 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 diff --git a/service/src/com/android/server/connectivity/ConnectivityFlags.java b/service/src/com/android/server/connectivity/ConnectivityFlags.java new file mode 100644 index 0000000000..122ea1c2b9 --- /dev/null +++ b/service/src/com/android/server/connectivity/ConnectivityFlags.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.connectivity; + +import android.content.Context; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.ConnectivityService; + +/** + * Collection of constants for the connectivity module. + */ +public final class ConnectivityFlags { + /** + * Minimum module version at which to avoid rematching all requests when a network request is + * registered, and rematch only the registered requests instead. + */ + @VisibleForTesting + public static final String NO_REMATCH_ALL_REQUESTS_ON_REGISTER = + "no_rematch_all_requests_on_register"; + + private boolean mNoRematchAllRequestsOnRegister; + + /** + * Whether ConnectivityService should avoid avoid rematching all requests when a network + * request is registered, and rematch only the registered requests instead. + * + * This flag is disabled by default. + * + * IMPORTANT NOTE: This flag is false by default and will only be loaded in ConnectivityService + * systemReady. It is also not volatile for performance reasons, so for most threads it may + * only change to true after some time. This is fine for this particular flag because it only + * controls whether all requests or a subset of requests should be rematched, which is only + * a performance optimization, so its value does not need to be consistent over time; but most + * flags will not have these properties and should not use the same model. + * + * TODO: when adding other flags, consider the appropriate timing to load them, and necessary + * threading guarantees according to the semantics of the flags. + */ + public boolean noRematchAllRequestsOnRegister() { + return mNoRematchAllRequestsOnRegister; + } + + /** + * Load flag values. Should only be called once, and can only be called once PackageManager is + * ready. + */ + public void loadFlags(ConnectivityService.Dependencies deps, Context ctx) { + mNoRematchAllRequestsOnRegister = deps.isFeatureEnabled( + ctx, NO_REMATCH_ALL_REQUESTS_ON_REGISTER, false /* defaultEnabled */); + } +} diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java index bc50d0d78a..e0dd8867b2 100644 --- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java @@ -327,6 +327,7 @@ import com.android.net.module.util.LocationPermissionChecker; import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo; import com.android.server.ConnectivityService.NetworkRequestInfo; import com.android.server.ConnectivityServiceTest.ConnectivityServiceDependencies.ReportedInterfaces; +import com.android.server.connectivity.ConnectivityFlags; import com.android.server.connectivity.MockableSystemProperties; import com.android.server.connectivity.Nat464Xlat; import com.android.server.connectivity.NetworkAgentInfo; @@ -1916,6 +1917,16 @@ public class ConnectivityServiceTest { mReportedInterfaceHistory.add(new ReportedInterfaces(context, iface, transportTypes)); super.reportNetworkInterfaceForTransports(context, iface, transportTypes); } + + @Override + public boolean isFeatureEnabled(Context context, String name, boolean defaultEnabled) { + switch (name) { + case ConnectivityFlags.NO_REMATCH_ALL_REQUESTS_ON_REGISTER: + return true; + default: + return super.isFeatureEnabled(context, name, defaultEnabled); + } + } } private static void initAlarmManager(final AlarmManager am, final Handler alarmHandler) {