Merge "Expose systemReady for SystemServer"
diff --git a/framework/Android.bp b/framework/Android.bp
index 9da27d2..86433e1 100644
--- a/framework/Android.bp
+++ b/framework/Android.bp
@@ -23,7 +23,6 @@
default_applicable_licenses: ["frameworks_base_license"],
}
-// TODO: use a java_library in the bootclasspath instead
filegroup {
name: "framework-connectivity-internal-sources",
srcs: [
@@ -84,3 +83,38 @@
],
permitted_packages: ["android.net", "com.android.connectivity.aidl"],
}
+
+java_library {
+ name: "framework-connectivity.impl",
+ // Instead of building against private API (framework.jar),
+ // build against core_platform + framework-minus-apex + module
+ // stub libs. This allows framework.jar to depend on this library,
+ // so it can be part of the private API until all clients have been migrated.
+ // TODO: just build against module_api, and remove this jar from
+ // the private API.
+ sdk_version: "core_platform",
+ srcs: [
+ ":framework-connectivity-sources",
+ ],
+ aidl: {
+ include_dirs: [
+ "frameworks/base/core/java", // For framework parcelables
+ "frameworks/native/aidl/binder", // For PersistableBundle.aidl
+ ],
+ },
+ libs: [
+ "framework-minus-apex",
+ // TODO: just framework-tethering, framework-wifi when building against module_api
+ "framework-tethering.stubs.module_lib",
+ "framework-wifi.stubs.module_lib",
+ "unsupportedappusage",
+ "ServiceConnectivityResources",
+ ],
+ static_libs: [
+ "net-utils-device-common",
+ ],
+ jarjar_rules: "jarjar-rules.txt",
+ apex_available: ["com.android.tethering"],
+ installable: true,
+ permitted_packages: ["android.net", "com.android.connectivity.aidl"],
+}
diff --git a/framework/api/current.txt b/framework/api/current.txt
index 243e4ca..f22d4b7 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -87,6 +87,7 @@
method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public boolean isActiveNetworkMetered();
method public boolean isDefaultNetworkActive();
method @Deprecated public static boolean isNetworkTypeValid(int);
+ method public void registerBestMatchingNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback);
method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback);
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 05e0813..ab03916 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -6,16 +6,25 @@
}
public class ConnectivityManager {
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void factoryReset();
method @NonNull @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public java.util.List<android.net.NetworkStateSnapshot> getAllNetworkStateSnapshot();
+ method @Nullable public android.net.ProxyInfo getGlobalProxy();
method @NonNull public static android.util.Range<java.lang.Integer> getIpSecNetIdRange();
- method @NonNull public static String getPrivateDnsMode(@NonNull android.content.ContentResolver);
+ method @NonNull public static String getPrivateDnsMode(@NonNull android.content.Context);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_SETTINGS}) public void registerSystemDefaultNetworkCallback(@NonNull android.net.ConnectivityManager.NetworkCallback, @NonNull android.os.Handler);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptPartialConnectivity(@NonNull android.net.Network, boolean, boolean);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAcceptUnvalidated(@NonNull android.net.Network, boolean, boolean);
+ method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void setAvoidUnvalidated(@NonNull android.net.Network);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setGlobalProxy(@Nullable android.net.ProxyInfo);
+ method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setProfileNetworkPreference(@NonNull android.os.UserHandle, int, @Nullable java.util.concurrent.Executor, @Nullable Runnable);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
method public void systemReady();
field public static final String PRIVATE_DNS_MODE_OFF = "off";
field public static final String PRIVATE_DNS_MODE_OPPORTUNISTIC = "opportunistic";
field public static final String PRIVATE_DNS_MODE_PROVIDER_HOSTNAME = "hostname";
+ field public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0; // 0x0
+ field public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1; // 0x1
}
public final class NetworkAgentConfig implements android.os.Parcelable {
@@ -27,9 +36,18 @@
}
public final class NetworkCapabilities implements android.os.Parcelable {
+ method @Nullable public java.util.Set<android.util.Range<java.lang.Integer>> getUids();
field public static final int TRANSPORT_TEST = 7; // 0x7
}
+ public static final class NetworkCapabilities.Builder {
+ method @NonNull public android.net.NetworkCapabilities.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
+ }
+
+ public static class NetworkRequest.Builder {
+ method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
+ }
+
public class ParseException extends java.lang.RuntimeException {
ctor public ParseException(@NonNull String);
ctor public ParseException(@NonNull String, @NonNull Throwable);
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index a98f14e..031bb91 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -56,7 +56,7 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull android.net.NetworkRequest, int, int, @NonNull android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) public void setAirplaneMode(boolean);
- method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable android.net.ConnectivityManager.OnSetOemNetworkPreferenceListener);
+ method @RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE) public void setOemNetworkPreference(@NonNull android.net.OemNetworkPreferences, @Nullable java.util.concurrent.Executor, @Nullable Runnable);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public boolean shouldAvoidBadWifi();
method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
@@ -78,10 +78,6 @@
field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd
}
- public static interface ConnectivityManager.OnSetOemNetworkPreferenceListener {
- method public void onComplete();
- }
-
@Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback {
ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback();
method @Deprecated public void onTetheringFailed();
diff --git a/framework/jarjar-rules.txt b/framework/jarjar-rules.txt
new file mode 100644
index 0000000..381a4ac
--- /dev/null
+++ b/framework/jarjar-rules.txt
@@ -0,0 +1,7 @@
+rule com.android.net.module.util.** android.net.connectivity.framework.util.@1
+
+# TODO (b/149403767): remove the annotations from net-utils-device-common instead of here
+zap android.annotation.**
+zap com.android.net.module.annotation.**
+zap com.android.internal.annotations.**
+
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index dc06cd9..786ed24 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -16,15 +16,15 @@
package android.net;
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE;
import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST;
import static android.net.NetworkRequest.Type.LISTEN;
+import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST;
import static android.net.NetworkRequest.Type.REQUEST;
-import static android.net.NetworkRequest.Type.TRACK_BEST;
import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
import static android.net.NetworkRequest.Type.TRACK_SYSTEM_DEFAULT;
import static android.net.QosCallback.QosCallbackRegistrationException;
-import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE;
-import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
@@ -64,6 +64,7 @@
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
+import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -76,7 +77,6 @@
import com.android.connectivity.aidl.INetworkAgent;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
-import com.android.internal.util.Protocol;
import libcore.net.event.NetworkEventDispatcher;
@@ -971,6 +971,33 @@
}
/**
+ * Preference for {@link #setNetworkPreferenceForUser(UserHandle, int, Executor, Runnable)}.
+ * Specify that the traffic for this user should by follow the default rules.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int PROFILE_NETWORK_PREFERENCE_DEFAULT = 0;
+
+ /**
+ * Preference for {@link #setNetworkPreferenceForUser(UserHandle, int, Executor, Runnable)}.
+ * Specify that the traffic for this user should by default go on a network with
+ * {@link NetworkCapabilities#NET_CAPABILITY_ENTERPRISE}, and on the system default network
+ * if no such network is available.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int PROFILE_NETWORK_PREFERENCE_ENTERPRISE = 1;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ PROFILE_NETWORK_PREFERENCE_DEFAULT,
+ PROFILE_NETWORK_PREFERENCE_ENTERPRISE
+ })
+ public @interface ProfileNetworkPreference {
+ }
+
+ /**
* Specifies the preferred network type. When the device has more
* than one type available the preferred network type will be used.
*
@@ -3011,8 +3038,9 @@
* HTTP proxy. A {@code null} value will clear the global HTTP proxy.
* @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
- public void setGlobalProxy(ProxyInfo p) {
+ public void setGlobalProxy(@Nullable ProxyInfo p) {
try {
mService.setGlobalProxy(p);
} catch (RemoteException e) {
@@ -3027,6 +3055,8 @@
* if no global HTTP proxy is set.
* @hide
*/
+ @SystemApi(client = MODULE_LIBRARIES)
+ @Nullable
public ProxyInfo getGlobalProxy() {
try {
return mService.getGlobalProxy();
@@ -3523,29 +3553,28 @@
}
}
- private static final int BASE = Protocol.BASE_CONNECTIVITY_MANAGER;
/** @hide */
- public static final int CALLBACK_PRECHECK = BASE + 1;
+ public static final int CALLBACK_PRECHECK = 1;
/** @hide */
- public static final int CALLBACK_AVAILABLE = BASE + 2;
+ public static final int CALLBACK_AVAILABLE = 2;
/** @hide arg1 = TTL */
- public static final int CALLBACK_LOSING = BASE + 3;
+ public static final int CALLBACK_LOSING = 3;
/** @hide */
- public static final int CALLBACK_LOST = BASE + 4;
+ public static final int CALLBACK_LOST = 4;
/** @hide */
- public static final int CALLBACK_UNAVAIL = BASE + 5;
+ public static final int CALLBACK_UNAVAIL = 5;
/** @hide */
- public static final int CALLBACK_CAP_CHANGED = BASE + 6;
+ public static final int CALLBACK_CAP_CHANGED = 6;
/** @hide */
- public static final int CALLBACK_IP_CHANGED = BASE + 7;
+ public static final int CALLBACK_IP_CHANGED = 7;
/** @hide obj = NetworkCapabilities, arg1 = seq number */
- private static final int EXPIRE_LEGACY_REQUEST = BASE + 8;
+ private static final int EXPIRE_LEGACY_REQUEST = 8;
/** @hide */
- public static final int CALLBACK_SUSPENDED = BASE + 9;
+ public static final int CALLBACK_SUSPENDED = 9;
/** @hide */
- public static final int CALLBACK_RESUMED = BASE + 10;
+ public static final int CALLBACK_RESUMED = 10;
/** @hide */
- public static final int CALLBACK_BLK_CHANGED = BASE + 11;
+ public static final int CALLBACK_BLK_CHANGED = 11;
/** @hide */
public static String getCallbackName(int whichCallback) {
@@ -4241,15 +4270,33 @@
}
/**
- * @hide
+ * Registers to receive notifications about the best matching network which satisfy the given
+ * {@link NetworkRequest}. The callbacks will continue to be called until
+ * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is
+ * called.
+ *
+ * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the
+ * number of outstanding requests to 100 per app (identified by their UID), shared with
+ * {@link #registerNetworkCallback} and its variants and {@link #requestNetwork} as well as
+ * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}.
+ * Requesting a network with this method will count toward this limit. If this limit is
+ * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources,
+ * make sure to unregister the callbacks with
+ * {@link #unregisterNetworkCallback(NetworkCallback)}.
+ *
+ *
+ * @param request {@link NetworkRequest} describing this request.
+ * @param networkCallback The {@link NetworkCallback} that the system will call as suitable
+ * networks change state.
+ * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+ * @throws RuntimeException if the app already has too many callbacks registered.
*/
- // TODO: Make it public api.
@SuppressLint("ExecutorRegistration")
public void registerBestMatchingNetworkCallback(@NonNull NetworkRequest request,
@NonNull NetworkCallback networkCallback, @NonNull Handler handler) {
final NetworkCapabilities nc = request.networkCapabilities;
final CallbackHandler cbHandler = new CallbackHandler(handler);
- sendRequestForNetwork(nc, networkCallback, 0, TRACK_BEST, TYPE_NONE, cbHandler);
+ sendRequestForNetwork(nc, networkCallback, 0, LISTEN_FOR_BEST, TYPE_NONE, cbHandler);
}
/**
@@ -4344,8 +4391,13 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
- public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
+ public void setAcceptUnvalidated(@NonNull Network network, boolean accept, boolean always) {
try {
mService.setAcceptUnvalidated(network, accept, always);
} catch (RemoteException e) {
@@ -4367,8 +4419,14 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
- public void setAcceptPartialConnectivity(Network network, boolean accept, boolean always) {
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
+ public void setAcceptPartialConnectivity(@NonNull Network network, boolean accept,
+ boolean always) {
try {
mService.setAcceptPartialConnectivity(network, accept, always);
} catch (RemoteException e) {
@@ -4386,8 +4444,13 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
- public void setAvoidUnvalidated(Network network) {
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD,
+ android.Manifest.permission.NETWORK_STACK,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
+ public void setAvoidUnvalidated(@NonNull Network network) {
try {
mService.setAvoidUnvalidated(network);
} catch (RemoteException e) {
@@ -4517,7 +4580,10 @@
* Resets all connectivity manager settings back to factory defaults.
* @hide
*/
- @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK})
public void factoryReset() {
try {
mService.factoryReset();
@@ -5049,19 +5115,6 @@
}
/**
- * Listener for {@link #setOemNetworkPreference(OemNetworkPreferences, Executor,
- * OnSetOemNetworkPreferenceListener)}.
- * @hide
- */
- @SystemApi
- public interface OnSetOemNetworkPreferenceListener {
- /**
- * Called when setOemNetworkPreference() successfully completes.
- */
- void onComplete();
- }
-
- /**
* Used by automotive devices to set the network preferences used to direct traffic at an
* application level as per the given OemNetworkPreferences. An example use-case would be an
* automotive OEM wanting to provide connectivity for applications critical to the usage of a
@@ -5083,16 +5136,16 @@
@RequiresPermission(android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE)
public void setOemNetworkPreference(@NonNull final OemNetworkPreferences preference,
@Nullable @CallbackExecutor final Executor executor,
- @Nullable final OnSetOemNetworkPreferenceListener listener) {
+ @Nullable final Runnable listener) {
Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null");
if (null != listener) {
Objects.requireNonNull(executor, "Executor must be non-null");
}
- final IOnSetOemNetworkPreferenceListener listenerInternal = listener == null ? null :
- new IOnSetOemNetworkPreferenceListener.Stub() {
+ final IOnCompleteListener listenerInternal = listener == null ? null :
+ new IOnCompleteListener.Stub() {
@Override
public void onComplete() {
- executor.execute(listener::onComplete);
+ executor.execute(listener::run);
}
};
@@ -5104,6 +5157,52 @@
}
}
+ /**
+ * Request that a user profile is put by default on a network matching a given preference.
+ *
+ * See the documentation for the individual preferences for a description of the supported
+ * behaviors.
+ *
+ * @param profile the profile concerned.
+ * @param preference the preference for this profile.
+ * @param executor an executor to execute the listener on. Optional if listener is null.
+ * @param listener an optional listener to listen for completion of the operation.
+ * @throws IllegalArgumentException if {@code profile} is not a valid user profile.
+ * @throws SecurityException if missing the appropriate permissions.
+ * @hide
+ */
+ // This function is for establishing per-profile default networking and can only be called by
+ // the device policy manager, running as the system server. It would make no sense to call it
+ // on a context for a user because it does not establish a setting on behalf of a user, rather
+ // it establishes a setting for a user on behalf of the DPM.
+ @SuppressLint({"UserHandle"})
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
+ public void setProfileNetworkPreference(@NonNull final UserHandle profile,
+ @ProfileNetworkPreference final int preference,
+ @Nullable @CallbackExecutor final Executor executor,
+ @Nullable final Runnable listener) {
+ if (null != listener) {
+ Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener");
+ }
+ final IOnCompleteListener proxy;
+ if (null == listener) {
+ proxy = null;
+ } else {
+ proxy = new IOnCompleteListener.Stub() {
+ @Override
+ public void onComplete() {
+ executor.execute(listener::run);
+ }
+ };
+ }
+ try {
+ mService.setProfileNetworkPreference(profile, preference, proxy);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
// The first network ID of IPSec tunnel interface.
private static final int TUN_INTF_NETID_START = 0xFC00; // 0xFC00 = 64512
// The network ID range of IPSec tunnel interface.
@@ -5124,7 +5223,7 @@
/**
* Get private DNS mode from settings.
*
- * @param cr The ContentResolver to query private DNS mode from settings.
+ * @param context The Context to query the private DNS mode from settings.
* @return A string of private DNS mode as one of the PRIVATE_DNS_MODE_* constants.
*
* @hide
@@ -5132,7 +5231,8 @@
@SystemApi(client = MODULE_LIBRARIES)
@NonNull
@PrivateDnsMode
- public static String getPrivateDnsMode(@NonNull ContentResolver cr) {
+ public static String getPrivateDnsMode(@NonNull Context context) {
+ final ContentResolver cr = context.getContentResolver();
String mode = Settings.Global.getString(cr, PRIVATE_DNS_MODE);
if (TextUtils.isEmpty(mode)) mode = Settings.Global.getString(cr, PRIVATE_DNS_DEFAULT_MODE);
// If both PRIVATE_DNS_MODE and PRIVATE_DNS_DEFAULT_MODE are not set, choose
diff --git a/framework/src/android/net/ConnectivitySettingsManager.java b/framework/src/android/net/ConnectivitySettingsManager.java
new file mode 100644
index 0000000..bbd8393
--- /dev/null
+++ b/framework/src/android/net/ConnectivitySettingsManager.java
@@ -0,0 +1,241 @@
+/*
+ * 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 android.net;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A manager class for connectivity module settings.
+ *
+ * @hide
+ */
+public class ConnectivitySettingsManager {
+
+ private ConnectivitySettingsManager() {}
+
+ /** Data activity timeout settings */
+
+ /**
+ * Inactivity timeout to track mobile data activity.
+ *
+ * If set to a positive integer, it indicates the inactivity timeout value in seconds to
+ * infer the data activity of mobile network. After a period of no activity on mobile
+ * networks with length specified by the timeout, an {@code ACTION_DATA_ACTIVITY_CHANGE}
+ * intent is fired to indicate a transition of network status from "active" to "idle". Any
+ * subsequent activity on mobile networks triggers the firing of {@code
+ * ACTION_DATA_ACTIVITY_CHANGE} intent indicating transition from "idle" to "active".
+ *
+ * Network activity refers to transmitting or receiving data on the network interfaces.
+ *
+ * Tracking is disabled if set to zero or negative value.
+ */
+ public static final String DATA_ACTIVITY_TIMEOUT_MOBILE = "data_activity_timeout_mobile";
+
+ /**
+ * Timeout to tracking Wifi data activity. Same as {@code DATA_ACTIVITY_TIMEOUT_MOBILE}
+ * but for Wifi network.
+ */
+ public static final String DATA_ACTIVITY_TIMEOUT_WIFI = "data_activity_timeout_wifi";
+
+ /** Dns resolver settings */
+
+ /**
+ * Sample validity in seconds to configure for the system DNS resolver.
+ */
+ public static final String DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS =
+ "dns_resolver_sample_validity_seconds";
+
+ /**
+ * Success threshold in percent for use with the system DNS resolver.
+ */
+ public static final String DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT =
+ "dns_resolver_success_threshold_percent";
+
+ /**
+ * Minimum number of samples needed for statistics to be considered meaningful in the
+ * system DNS resolver.
+ */
+ public static final String DNS_RESOLVER_MIN_SAMPLES = "dns_resolver_min_samples";
+
+ /**
+ * Maximum number taken into account for statistics purposes in the system DNS resolver.
+ */
+ public static final String DNS_RESOLVER_MAX_SAMPLES = "dns_resolver_max_samples";
+
+ /** Network switch notification settings */
+
+ /**
+ * The maximum number of notifications shown in 24 hours when switching networks.
+ */
+ public static final String NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT =
+ "network_switch_notification_daily_limit";
+
+ /**
+ * The minimum time in milliseconds between notifications when switching networks.
+ */
+ public static final String NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS =
+ "network_switch_notification_rate_limit_millis";
+
+ /** Captive portal settings */
+
+ /**
+ * The URL used for HTTP captive portal detection upon a new connection.
+ * A 204 response code from the server is used for validation.
+ */
+ public static final String CAPTIVE_PORTAL_HTTP_URL = "captive_portal_http_url";
+
+ /**
+ * What to do when connecting a network that presents a captive portal.
+ * Must be one of the CAPTIVE_PORTAL_MODE_* constants above.
+ *
+ * The default for this setting is CAPTIVE_PORTAL_MODE_PROMPT.
+ */
+ public static final String CAPTIVE_PORTAL_MODE = "captive_portal_mode";
+
+ /**
+ * Don't attempt to detect captive portals.
+ */
+ public static final int CAPTIVE_PORTAL_MODE_IGNORE = 0;
+
+ /**
+ * When detecting a captive portal, display a notification that
+ * prompts the user to sign in.
+ */
+ public static final int CAPTIVE_PORTAL_MODE_PROMPT = 1;
+
+ /**
+ * When detecting a captive portal, immediately disconnect from the
+ * network and do not reconnect to that network in the future.
+ */
+ public static final int CAPTIVE_PORTAL_MODE_AVOID = 2;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ CAPTIVE_PORTAL_MODE_IGNORE,
+ CAPTIVE_PORTAL_MODE_PROMPT,
+ CAPTIVE_PORTAL_MODE_AVOID,
+ })
+ public @interface CaptivePortalMode {}
+
+ /** Global http proxy settings */
+
+ /**
+ * Host name for global http proxy. Set via ConnectivityManager.
+ */
+ public static final String GLOBAL_HTTP_PROXY_HOST = "global_http_proxy_host";
+
+ /**
+ * Integer host port for global http proxy. Set via ConnectivityManager.
+ */
+ public static final String GLOBAL_HTTP_PROXY_PORT = "global_http_proxy_port";
+
+ /**
+ * Exclusion list for global proxy. This string contains a list of
+ * comma-separated domains where the global proxy does not apply.
+ * Domains should be listed in a comma- separated list. Example of
+ * acceptable formats: ".domain1.com,my.domain2.com" Use
+ * ConnectivityManager to set/get.
+ */
+ public static final String GLOBAL_HTTP_PROXY_EXCLUSION_LIST =
+ "global_http_proxy_exclusion_list";
+
+ /**
+ * The location PAC File for the proxy.
+ */
+ public static final String GLOBAL_HTTP_PROXY_PAC = "global_proxy_pac_url";
+
+ /** Private dns settings */
+
+ /**
+ * The requested Private DNS mode (string), and an accompanying specifier (string).
+ *
+ * Currently, the specifier holds the chosen provider name when the mode requests
+ * a specific provider. It may be used to store the provider name even when the
+ * mode changes so that temporarily disabling and re-enabling the specific
+ * provider mode does not necessitate retyping the provider hostname.
+ */
+ public static final String PRIVATE_DNS_MODE = "private_dns_mode";
+
+ /**
+ * The specific Private DNS provider name.
+ */
+ public static final String PRIVATE_DNS_SPECIFIER = "private_dns_specifier";
+
+ /**
+ * Forced override of the default mode (hardcoded as "automatic", nee "opportunistic").
+ * This allows changing the default mode without effectively disabling other modes,
+ * all of which require explicit user action to enable/configure. See also b/79719289.
+ *
+ * Value is a string, suitable for assignment to PRIVATE_DNS_MODE above.
+ */
+ public static final String PRIVATE_DNS_DEFAULT_MODE = "private_dns_default_mode";
+
+ /** Other settings */
+
+ /**
+ * The number of milliseconds to hold on to a PendingIntent based request. This delay gives
+ * the receivers of the PendingIntent an opportunity to make a new network request before
+ * the Network satisfying the request is potentially removed.
+ */
+ public static final String CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS =
+ "connectivity_release_pending_intent_delay_ms";
+
+ /**
+ * Whether the mobile data connection should remain active even when higher
+ * priority networks like WiFi are active, to help make network switching faster.
+ *
+ * See ConnectivityService for more info.
+ *
+ * (0 = disabled, 1 = enabled)
+ */
+ public static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on";
+
+ /**
+ * Whether the wifi data connection should remain active even when higher
+ * priority networks like Ethernet are active, to keep both networks.
+ * In the case where higher priority networks are connected, wifi will be
+ * unused unless an application explicitly requests to use it.
+ *
+ * See ConnectivityService for more info.
+ *
+ * (0 = disabled, 1 = enabled)
+ */
+ public static final String WIFI_ALWAYS_REQUESTED = "wifi_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
+ * avoids such networks. Valid values are:
+ *
+ * 0: Don't avoid bad wifi, don't prompt the user. Get stuck on bad wifi like it's 2013.
+ * null: Ask the user whether to switch away from bad wifi.
+ * 1: Avoid bad wifi.
+ */
+ public static final String NETWORK_AVOID_BAD_WIFI = "network_avoid_bad_wifi";
+
+ /**
+ * User setting for ConnectivityManager.getMeteredMultipathPreference(). This value may be
+ * overridden by the system based on device or application state. If null, the value
+ * specified by config_networkMeteredMultipathPreference is used.
+ */
+ public static final String NETWORK_METERED_MULTIPATH_PREFERENCE =
+ "network_metered_multipath_preference";
+}
diff --git a/framework/src/android/net/IConnectivityManager.aidl b/framework/src/android/net/IConnectivityManager.aidl
index 1bbf1a9..d83cc16 100644
--- a/framework/src/android/net/IConnectivityManager.aidl
+++ b/framework/src/android/net/IConnectivityManager.aidl
@@ -20,7 +20,7 @@
import android.net.ConnectionInfo;
import android.net.ConnectivityDiagnosticsManager;
import android.net.IConnectivityDiagnosticsCallback;
-import android.net.IOnSetOemNetworkPreferenceListener;
+import android.net.IOnCompleteListener;
import android.net.INetworkActivityListener;
import android.net.IQosCallback;
import android.net.ISocketKeepaliveCallback;
@@ -43,6 +43,7 @@
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
import android.os.ResultReceiver;
+import android.os.UserHandle;
import com.android.connectivity.aidl.INetworkAgent;
@@ -215,5 +216,8 @@
void unregisterQosCallback(in IQosCallback callback);
void setOemNetworkPreference(in OemNetworkPreferences preference,
- in IOnSetOemNetworkPreferenceListener listener);
+ in IOnCompleteListener listener);
+
+ void setProfileNetworkPreference(in UserHandle profile, int preference,
+ in IOnCompleteListener listener);
}
diff --git a/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl b/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
deleted file mode 100644
index 7979afc..0000000
--- a/framework/src/android/net/IOnSetOemNetworkPreferenceListener.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- *
- * 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 android.net;
-
-/** @hide */
-oneway interface IOnSetOemNetworkPreferenceListener {
- void onComplete();
-}
diff --git a/framework/src/android/net/Network.java b/framework/src/android/net/Network.java
index 46141e0..7245db3 100644
--- a/framework/src/android/net/Network.java
+++ b/framework/src/android/net/Network.java
@@ -30,10 +30,10 @@
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
-import com.android.okhttp.internalandroidapi.Dns;
-import com.android.okhttp.internalandroidapi.HttpURLConnectionFactory;
import libcore.io.IoUtils;
+import libcore.net.http.Dns;
+import libcore.net.http.HttpURLConnectionFactory;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -299,7 +299,7 @@
// Set configuration on the HttpURLConnectionFactory that will be good for all
// connections created by this Network. Configuration that might vary is left
// until openConnection() and passed as arguments.
- HttpURLConnectionFactory urlConnectionFactory = new HttpURLConnectionFactory();
+ HttpURLConnectionFactory urlConnectionFactory = HttpURLConnectionFactory.createInstance();
urlConnectionFactory.setDns(dnsLookup); // Let traffic go via dnsLookup
// A private connection pool just for this Network.
urlConnectionFactory.setNewConnectionPool(httpMaxConnections,
diff --git a/framework/src/android/net/NetworkAgent.java b/framework/src/android/net/NetworkAgent.java
index b3ab0ee..a127c6f 100644
--- a/framework/src/android/net/NetworkAgent.java
+++ b/framework/src/android/net/NetworkAgent.java
@@ -37,7 +37,6 @@
import com.android.connectivity.aidl.INetworkAgent;
import com.android.connectivity.aidl.INetworkAgentRegistry;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.Protocol;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -125,7 +124,10 @@
*/
public final int providerId;
- private static final int BASE = Protocol.BASE_NETWORK_AGENT;
+ // ConnectivityService parses message constants from itself and NetworkAgent with MessageUtils
+ // for debugging purposes, and crashes if some messages have the same values.
+ // TODO: have ConnectivityService store message names in different maps and remove this base
+ private static final int BASE = 200;
/**
* Sent by ConnectivityService to the NetworkAgent to inform it of
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index 058f3c9..182bc71 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.ConnectivityManager.NetworkCallback;
@@ -32,6 +33,7 @@
import android.os.Process;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.Range;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
@@ -153,7 +155,7 @@
setTransportInfo(null);
}
mSignalStrength = nc.mSignalStrength;
- setUids(nc.mUids); // Will make the defensive copy
+ mUids = (nc.mUids == null) ? null : new ArraySet<>(nc.mUids);
setAdministratorUids(nc.getAdministratorUids());
mOwnerUid = nc.mOwnerUid;
mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
@@ -1458,9 +1460,8 @@
* @hide
*/
public @NonNull NetworkCapabilities setSingleUid(int uid) {
- final ArraySet<UidRange> identity = new ArraySet<>(1);
- identity.add(new UidRange(uid, uid));
- setUids(identity);
+ mUids = new ArraySet<>(1);
+ mUids.add(new UidRange(uid, uid));
return this;
}
@@ -1469,22 +1470,34 @@
* This makes a copy of the set so that callers can't modify it after the call.
* @hide
*/
- public @NonNull NetworkCapabilities setUids(Set<UidRange> uids) {
- if (null == uids) {
- mUids = null;
- } else {
- mUids = new ArraySet<>(uids);
- }
+ public @NonNull NetworkCapabilities setUids(@Nullable Set<Range<Integer>> uids) {
+ mUids = UidRange.fromIntRanges(uids);
return this;
}
/**
* Get the list of UIDs this network applies to.
* This returns a copy of the set so that callers can't modify the original object.
+ *
+ * @return the list of UIDs this network applies to. If {@code null}, then the network applies
+ * to all UIDs.
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("NullableCollection")
+ public @Nullable Set<Range<Integer>> getUids() {
+ return UidRange.toIntRanges(mUids);
+ }
+
+ /**
+ * Get the list of UIDs this network applies to.
+ * This returns a copy of the set so that callers can't modify the original object.
* @hide
*/
- public @Nullable Set<UidRange> getUids() {
- return null == mUids ? null : new ArraySet<>(mUids);
+ public @Nullable Set<UidRange> getUidRanges() {
+ if (mUids == null) return null;
+
+ return new ArraySet<>(mUids);
}
/**
@@ -2655,6 +2668,21 @@
}
/**
+ * Set the list of UIDs this network applies to.
+ *
+ * @param uids the list of UIDs this network applies to, or {@code null} if this network
+ * applies to all UIDs.
+ * @return this builder
+ * @hide
+ */
+ @NonNull
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public Builder setUids(@Nullable Set<Range<Integer>> uids) {
+ mCaps.setUids(uids);
+ return this;
+ }
+
+ /**
* Builds the instance of the capabilities.
*
* @return the built instance of NetworkCapabilities.
diff --git a/framework/src/android/net/NetworkRequest.java b/framework/src/android/net/NetworkRequest.java
index 3fd95ee..cf131f0 100644
--- a/framework/src/android/net/NetworkRequest.java
+++ b/framework/src/android/net/NetworkRequest.java
@@ -36,6 +36,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.NetworkCapabilities.NetCapability;
@@ -45,6 +46,7 @@
import android.os.Parcelable;
import android.os.Process;
import android.text.TextUtils;
+import android.util.Range;
import android.util.proto.ProtoOutputStream;
import java.util.Arrays;
@@ -140,7 +142,7 @@
REQUEST,
BACKGROUND_REQUEST,
TRACK_SYSTEM_DEFAULT,
- TRACK_BEST,
+ LISTEN_FOR_BEST,
};
/**
@@ -277,11 +279,14 @@
* Set the watched UIDs for this request. This will be reset and wiped out unless
* the calling app holds the CHANGE_NETWORK_STATE permission.
*
- * @param uids The watched UIDs as a set of UidRanges, or null for everything.
+ * @param uids The watched UIDs as a set of {@code Range<Integer>}, or null for everything.
* @return The builder to facilitate chaining.
* @hide
*/
- public Builder setUids(Set<UidRange> uids) {
+ @NonNull
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public Builder setUids(@Nullable Set<Range<Integer>> uids) {
mNetworkCapabilities.setUids(uids);
return this;
}
@@ -514,6 +519,15 @@
}
/**
+ * Returns true iff. this NetworkRequest is of type LISTEN_FOR_BEST.
+ *
+ * @hide
+ */
+ public boolean isListenForBest() {
+ return type == Type.LISTEN_FOR_BEST;
+ }
+
+ /**
* Returns true iff. the contained NetworkRequest is one that:
*
* - should be associated with at most one satisfying network
diff --git a/framework/src/android/net/OemNetworkPreferences.java b/framework/src/android/net/OemNetworkPreferences.java
index 48bd297..5a76cd6 100644
--- a/framework/src/android/net/OemNetworkPreferences.java
+++ b/framework/src/android/net/OemNetworkPreferences.java
@@ -73,6 +73,14 @@
private final Bundle mNetworkMappings;
/**
+ * Return whether this object is empty.
+ * @hide
+ */
+ public boolean isEmpty() {
+ return mNetworkMappings.keySet().size() == 0;
+ }
+
+ /**
* Return the currently built application package name to {@link OemNetworkPreference} mappings.
* @return the current network preferences map.
*/
diff --git a/framework/src/android/net/UidRange.java b/framework/src/android/net/UidRange.java
index 26518d3..bc67c74 100644
--- a/framework/src/android/net/UidRange.java
+++ b/framework/src/android/net/UidRange.java
@@ -20,8 +20,11 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Range;
import java.util.Collection;
+import java.util.Set;
/**
* An inclusive range of UIDs.
@@ -149,4 +152,32 @@
}
return false;
}
+
+ /**
+ * Convert a set of {@code Range<Integer>} to a set of {@link UidRange}.
+ */
+ @Nullable
+ public static ArraySet<UidRange> fromIntRanges(@Nullable Set<Range<Integer>> ranges) {
+ if (null == ranges) return null;
+
+ final ArraySet<UidRange> uids = new ArraySet<>();
+ for (Range<Integer> range : ranges) {
+ uids.add(new UidRange(range.getLower(), range.getUpper()));
+ }
+ return uids;
+ }
+
+ /**
+ * Convert a set of {@link UidRange} to a set of {@code Range<Integer>}.
+ */
+ @Nullable
+ public static ArraySet<Range<Integer>> toIntRanges(@Nullable Set<UidRange> ranges) {
+ if (null == ranges) return null;
+
+ final ArraySet<Range<Integer>> uids = new ArraySet<>();
+ for (UidRange range : ranges) {
+ uids.add(new Range<Integer>(range.start, range.stop));
+ }
+ return uids;
+ }
}
diff --git a/framework/src/android/net/VpnTransportInfo.java b/framework/src/android/net/VpnTransportInfo.java
index c510079..cd8f4c0 100644
--- a/framework/src/android/net/VpnTransportInfo.java
+++ b/framework/src/android/net/VpnTransportInfo.java
@@ -22,9 +22,6 @@
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import android.util.SparseArray;
-
-import com.android.internal.util.MessageUtils;
import java.util.Objects;
@@ -38,9 +35,6 @@
*/
@SystemApi(client = MODULE_LIBRARIES)
public final class VpnTransportInfo implements TransportInfo, Parcelable {
- private static final SparseArray<String> sTypeToString =
- MessageUtils.findMessageNames(new Class[]{VpnManager.class}, new String[]{"TYPE_VPN_"});
-
/** Type of this VPN. */
public final int type;
@@ -63,8 +57,7 @@
@Override
public String toString() {
- final String typeString = sTypeToString.get(type, "VPN_TYPE_???");
- return String.format("VpnTransportInfo{%s}", typeString);
+ return String.format("VpnTransportInfo{type=%d}", type);
}
@Override
diff --git a/framework/src/android/net/util/MultinetworkPolicyTracker.java b/framework/src/android/net/util/MultinetworkPolicyTracker.java
index 739ddad..6a49aa2 100644
--- a/framework/src/android/net/util/MultinetworkPolicyTracker.java
+++ b/framework/src/android/net/util/MultinetworkPolicyTracker.java
@@ -16,8 +16,8 @@
package android.net.util;
-import static android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI;
-import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
+import static android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
+import static android.net.ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE;
import android.annotation.NonNull;
import android.content.BroadcastReceiver;
@@ -110,8 +110,8 @@
mHandler = handler;
mAvoidBadWifiCallback = avoidBadWifiCallback;
mSettingsUris = Arrays.asList(
- Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI),
- Settings.Global.getUriFor(NETWORK_METERED_MULTIPATH_PREFERENCE));
+ Settings.Global.getUriFor(NETWORK_AVOID_BAD_WIFI),
+ Settings.Global.getUriFor(NETWORK_METERED_MULTIPATH_PREFERENCE));
mResolver = mContext.getContentResolver();
mSettingObserver = new SettingObserver();
mBroadcastReceiver = new BroadcastReceiver() {
diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml
index 7d98c76..06c8192 100644
--- a/service/ServiceConnectivityResources/res/values/config.xml
+++ b/service/ServiceConnectivityResources/res/values/config.xml
@@ -42,4 +42,14 @@
-->
</string-array>
+ <string-array translatable="false" name="config_legacy_networktype_restore_timers">
+ <item>2,60000</item><!-- mobile_mms -->
+ <item>3,60000</item><!-- mobile_supl -->
+ <item>4,60000</item><!-- mobile_dun -->
+ <item>5,60000</item><!-- mobile_hipri -->
+ <item>10,60000</item><!-- mobile_fota -->
+ <item>11,60000</item><!-- mobile_ims -->
+ <item>12,60000</item><!-- mobile_cbs -->
+ </string-array>
+
</resources>
\ No newline at end of file
diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml
index 00ec2df..da8aee5 100644
--- a/service/ServiceConnectivityResources/res/values/overlayable.xml
+++ b/service/ServiceConnectivityResources/res/values/overlayable.xml
@@ -17,11 +17,11 @@
<overlayable name="ServiceConnectivityResourcesConfig">
<policy type="product|system|vendor">
<!-- Configuration values for ConnectivityService -->
+ <item type="array" name="config_legacy_networktype_restore_timers"/>
<item type="string" name="config_networkCaptivePortalServerUrl"/>
<item type="integer" name="config_networkTransitionTimeout"/>
<item type="array" name="config_wakeonlan_supported_interfaces"/>
-
</policy>
</overlayable>
</resources>
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 92d9b08..527c211 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -17,6 +17,10 @@
package com.android.server;
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
+import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
+import static android.content.pm.PackageManager.FEATURE_WATCH;
+import static android.content.pm.PackageManager.FEATURE_WIFI;
+import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_ATTEMPTED_BITMASK;
import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_PROBES_SUCCEEDED_BITMASK;
@@ -28,15 +32,30 @@
import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_PACKET_FAIL_RATE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
+import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_MOBILE_CBS;
+import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
+import static android.net.ConnectivityManager.TYPE_MOBILE_EMERGENCY;
+import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
+import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
+import static android.net.ConnectivityManager.TYPE_MOBILE_IA;
+import static android.net.ConnectivityManager.TYPE_MOBILE_IMS;
+import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
+import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
import static android.net.ConnectivityManager.TYPE_NONE;
+import static android.net.ConnectivityManager.TYPE_PROXY;
import static android.net.ConnectivityManager.TYPE_VPN;
+import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
@@ -55,6 +74,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.uidRulesToString;
+import static android.net.NetworkRequest.Type.LISTEN_FOR_BEST;
import static android.net.shared.NetworkMonitorUtils.isPrivateDnsValidationRequired;
import static android.os.Process.INVALID_UID;
import static android.os.Process.VPN_UID;
@@ -86,6 +106,7 @@
import android.net.ConnectivityDiagnosticsManager.DataStallReport;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
+import android.net.ConnectivitySettingsManager;
import android.net.DataStallReportParcelable;
import android.net.DnsResolverServiceManager;
import android.net.ICaptivePortal;
@@ -97,7 +118,7 @@
import android.net.INetworkMonitor;
import android.net.INetworkMonitorCallbacks;
import android.net.INetworkPolicyListener;
-import android.net.IOnSetOemNetworkPreferenceListener;
+import android.net.IOnCompleteListener;
import android.net.IQosCallback;
import android.net.ISocketKeepaliveCallback;
import android.net.InetAddresses;
@@ -110,7 +131,6 @@
import android.net.NetworkAgent;
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
-import android.net.NetworkConfig;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMonitorManager;
@@ -192,13 +212,13 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.LocationPermissionChecker;
import com.android.internal.util.MessageUtils;
import com.android.modules.utils.BasicShellCommandHandler;
import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
+import com.android.net.module.util.LocationPermissionChecker;
import com.android.net.module.util.NetworkCapabilitiesUtils;
import com.android.net.module.util.PermissionUtils;
import com.android.server.connectivity.AutodestructReference;
@@ -214,6 +234,7 @@
import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
import com.android.server.connectivity.NetworkRanker;
import com.android.server.connectivity.PermissionMonitor;
+import com.android.server.connectivity.ProfileNetworkPreferences;
import com.android.server.connectivity.ProxyTracker;
import com.android.server.connectivity.QosCallbackTracker;
import com.android.server.net.NetworkPolicyManagerInternal;
@@ -264,7 +285,7 @@
/**
* Default URL to use for {@link #getCaptivePortalServerUrl()}. This should not be changed
* by OEMs for configuration purposes, as this value is overridden by
- * Settings.Global.CAPTIVE_PORTAL_HTTP_URL.
+ * ConnectivitySettingsManager.CAPTIVE_PORTAL_HTTP_URL.
* R.string.config_networkCaptivePortalServerUrl should be overridden instead for this purpose
* (preferably via runtime resource overlays).
*/
@@ -297,7 +318,7 @@
protected int mNascentDelayMs;
// How long to delay to removal of a pending intent based request.
- // See Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
+ // See ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS
private final int mReleasePendingIntentDelayMs;
private MockableSystemProperties mSystemProperties;
@@ -558,8 +579,8 @@
private static final int EVENT_SET_REQUIRE_VPN_FOR_UIDS = 47;
/**
- * used internally when setting the default networks for OemNetworkPreferences.
- * obj = OemNetworkPreferences
+ * Used internally when setting the default networks for OemNetworkPreferences.
+ * obj = Pair<OemNetworkPreferences, listener>
*/
private static final int EVENT_SET_OEM_NETWORK_PREFERENCE = 48;
@@ -569,6 +590,12 @@
private static final int EVENT_REPORT_NETWORK_ACTIVITY = 49;
/**
+ * Used internally when setting a network preference for a user profile.
+ * obj = Pair<ProfileNetworkPreference, Listener>
+ */
+ private static final int EVENT_SET_PROFILE_NETWORK_PREFERENCE = 50;
+
+ /**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown.
*/
@@ -617,11 +644,8 @@
private UserManager mUserManager;
- private NetworkConfig[] mNetConfigs;
- private int mNetworksDefined;
-
// the set of network types that can only be enabled by system/sig apps
- private List mProtectedNetworks;
+ private List<Integer> mProtectedNetworks;
private Set<String> mWolSupportedInterfaces;
@@ -711,18 +735,63 @@
* They are therefore not thread-safe with respect to each other.
* - getNetworkForType() can be called at any time on binder threads. It is synchronized
* on mTypeLists to be thread-safe with respect to a concurrent remove call.
+ * - getRestoreTimerForType(type) is also synchronized on mTypeLists.
* - dump is thread-safe with respect to concurrent add and remove calls.
*/
private final ArrayList<NetworkAgentInfo> mTypeLists[];
@NonNull
private final ConnectivityService mService;
+ // Restore timers for requestNetworkForFeature (network type -> timer in ms). Types without
+ // an entry have no timer (equivalent to -1). Lazily loaded.
+ @NonNull
+ private ArrayMap<Integer, Integer> mRestoreTimers = new ArrayMap<>();
+
LegacyTypeTracker(@NonNull ConnectivityService service) {
mService = service;
mTypeLists = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
}
- public void addSupportedType(int type) {
+ public void loadSupportedTypes(@NonNull Context ctx, @NonNull TelephonyManager tm) {
+ final PackageManager pm = ctx.getPackageManager();
+ if (pm.hasSystemFeature(FEATURE_WIFI)) {
+ addSupportedType(TYPE_WIFI);
+ }
+ if (pm.hasSystemFeature(FEATURE_WIFI_DIRECT)) {
+ addSupportedType(TYPE_WIFI_P2P);
+ }
+ if (tm.isDataCapable()) {
+ // Telephony does not have granular support for these types: they are either all
+ // supported, or none is supported
+ addSupportedType(TYPE_MOBILE);
+ addSupportedType(TYPE_MOBILE_MMS);
+ addSupportedType(TYPE_MOBILE_SUPL);
+ addSupportedType(TYPE_MOBILE_DUN);
+ addSupportedType(TYPE_MOBILE_HIPRI);
+ addSupportedType(TYPE_MOBILE_FOTA);
+ addSupportedType(TYPE_MOBILE_IMS);
+ addSupportedType(TYPE_MOBILE_CBS);
+ addSupportedType(TYPE_MOBILE_IA);
+ addSupportedType(TYPE_MOBILE_EMERGENCY);
+ }
+ if (pm.hasSystemFeature(FEATURE_BLUETOOTH)) {
+ addSupportedType(TYPE_BLUETOOTH);
+ }
+ if (pm.hasSystemFeature(FEATURE_WATCH)) {
+ // TYPE_PROXY is only used on Wear
+ addSupportedType(TYPE_PROXY);
+ }
+ // Ethernet is often not specified in the configs, although many devices can use it via
+ // USB host adapters. Add it as long as the ethernet service is here.
+ if (ctx.getSystemService(Context.ETHERNET_SERVICE) != null) {
+ addSupportedType(TYPE_ETHERNET);
+ }
+
+ // Always add TYPE_VPN as a supported type
+ addSupportedType(TYPE_VPN);
+ }
+
+ private void addSupportedType(int type) {
if (mTypeLists[type] != null) {
throw new IllegalStateException(
"legacy list for type " + type + "already initialized");
@@ -743,6 +812,35 @@
return null;
}
+ public int getRestoreTimerForType(int type) {
+ synchronized (mTypeLists) {
+ if (mRestoreTimers == null) {
+ mRestoreTimers = loadRestoreTimers();
+ }
+ return mRestoreTimers.getOrDefault(type, -1);
+ }
+ }
+
+ private ArrayMap<Integer, Integer> loadRestoreTimers() {
+ final String[] configs = mService.mResources.get().getStringArray(
+ com.android.connectivity.resources.R.array
+ .config_legacy_networktype_restore_timers);
+ final ArrayMap<Integer, Integer> ret = new ArrayMap<>(configs.length);
+ for (final String config : configs) {
+ final String[] splits = TextUtils.split(config, ",");
+ if (splits.length != 2) {
+ logwtf("Invalid restore timer token count: " + config);
+ continue;
+ }
+ try {
+ ret.put(Integer.parseInt(splits[0]), Integer.parseInt(splits[1]));
+ } catch (NumberFormatException e) {
+ logwtf("Invalid restore timer number format: " + config, e);
+ }
+ }
+ return ret;
+ }
+
private void maybeLogBroadcast(NetworkAgentInfo nai, DetailedState state, int type,
boolean isDefaultNetwork) {
if (DBG) {
@@ -1136,7 +1234,7 @@
new ConnectivityDiagnosticsHandler(mHandlerThread.getLooper());
mReleasePendingIntentDelayMs = Settings.Secure.getInt(context.getContentResolver(),
- Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
+ ConnectivitySettingsManager.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS, 5_000);
mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS);
// TODO: Consider making the timer customizable.
@@ -1165,64 +1263,12 @@
mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mPendingIntentWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
- mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1];
-
- // TODO: What is the "correct" way to do determine if this is a wifi only device?
- boolean wifiOnly = mSystemProperties.getBoolean("ro.radio.noril", false);
- log("wifiOnly=" + wifiOnly);
- String[] naStrings = context.getResources().getStringArray(
- com.android.internal.R.array.networkAttributes);
- for (String naString : naStrings) {
- try {
- NetworkConfig n = new NetworkConfig(naString);
- if (VDBG) log("naString=" + naString + " config=" + n);
- if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) {
- loge("Error in networkAttributes - ignoring attempt to define type " +
- n.type);
- continue;
- }
- if (wifiOnly && ConnectivityManager.isNetworkTypeMobile(n.type)) {
- log("networkAttributes - ignoring mobile as this dev is wifiOnly " +
- n.type);
- continue;
- }
- if (mNetConfigs[n.type] != null) {
- loge("Error in networkAttributes - ignoring attempt to redefine type " +
- n.type);
- continue;
- }
- mLegacyTypeTracker.addSupportedType(n.type);
-
- mNetConfigs[n.type] = n;
- mNetworksDefined++;
- } catch(Exception e) {
- // ignore it - leave the entry null
- }
- }
-
- // Forcibly add TYPE_VPN as a supported type, if it has not already been added via config.
- if (mNetConfigs[TYPE_VPN] == null) {
- // mNetConfigs is used only for "restore time", which isn't applicable to VPNs, so we
- // don't need to add TYPE_VPN to mNetConfigs.
- mLegacyTypeTracker.addSupportedType(TYPE_VPN);
- mNetworksDefined++; // used only in the log() statement below.
- }
-
- // Do the same for Ethernet, since it's often not specified in the configs, although many
- // devices can use it via USB host adapters.
- if (mNetConfigs[TYPE_ETHERNET] == null
- && mContext.getSystemService(Context.ETHERNET_SERVICE) != null) {
- mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET);
- mNetworksDefined++;
- }
-
- if (VDBG) log("mNetworksDefined=" + mNetworksDefined);
-
- mProtectedNetworks = new ArrayList<Integer>();
+ mLegacyTypeTracker.loadSupportedTypes(mContext, mTelephonyManager);
+ mProtectedNetworks = new ArrayList<>();
int[] protectedNetworks = context.getResources().getIntArray(
com.android.internal.R.array.config_protectedNetworks);
for (int p : protectedNetworks) {
- if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) {
+ if (mLegacyTypeTracker.isTypeSupported(p) && !mProtectedNetworks.contains(p)) {
mProtectedNetworks.add(p);
} else {
if (DBG) loge("Ignoring protectedNetwork " + p);
@@ -1260,10 +1306,10 @@
mQosCallbackTracker = new QosCallbackTracker(mHandler, mNetworkRequestCounter);
final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
+ ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
LingerMonitor.DEFAULT_NOTIFICATION_DAILY_LIMIT);
final long rateLimit = Settings.Global.getLong(mContext.getContentResolver(),
- Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
+ ConnectivitySettingsManager.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
@@ -1289,11 +1335,16 @@
}
private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) {
+ return createDefaultNetworkCapabilitiesForUidRange(new UidRange(uid, uid));
+ }
+
+ private static NetworkCapabilities createDefaultNetworkCapabilitiesForUidRange(
+ @NonNull final UidRange uids) {
final NetworkCapabilities netCap = new NetworkCapabilities();
netCap.addCapability(NET_CAPABILITY_INTERNET);
netCap.addCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
netCap.removeCapability(NET_CAPABILITY_NOT_VPN);
- netCap.setSingleUid(uid);
+ netCap.setUids(UidRange.toIntRanges(Collections.singleton(uids)));
return netCap;
}
@@ -1376,10 +1427,10 @@
}
private void handleConfigureAlwaysOnNetworks() {
- handleAlwaysOnNetworkRequest(
- mDefaultMobileDataRequest, Settings.Global.MOBILE_DATA_ALWAYS_ON, true);
- handleAlwaysOnNetworkRequest(mDefaultWifiRequest, Settings.Global.WIFI_ALWAYS_REQUESTED,
- false);
+ handleAlwaysOnNetworkRequest(mDefaultMobileDataRequest,
+ ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON, true /* defaultValue */);
+ handleAlwaysOnNetworkRequest(mDefaultWifiRequest,
+ ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED, false /* defaultValue */);
handleAlwaysOnNetworkRequest(mDefaultVehicleRequest,
com.android.internal.R.bool.config_vehicleInternalNetworkAlwaysRequested);
}
@@ -1392,12 +1443,12 @@
// Watch for whether or not to keep mobile data always on.
mSettingsObserver.observe(
- Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON),
+ Settings.Global.getUriFor(ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON),
EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
// Watch for whether or not to keep wifi always on.
mSettingsObserver.observe(
- Settings.Global.getUriFor(Settings.Global.WIFI_ALWAYS_REQUESTED),
+ Settings.Global.getUriFor(ConnectivitySettingsManager.WIFI_ALWAYS_REQUESTED),
EVENT_CONFIGURE_ALWAYS_ON_NETWORKS);
}
@@ -2603,13 +2654,6 @@
} catch (RemoteException | ServiceSpecificException e) {
loge("Can't set TCP buffer sizes:" + e);
}
-
- final Integer rwndValue = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.TCP_DEFAULT_INIT_RWND,
- mSystemProperties.getInt("net.tcp.default_init_rwnd", 0));
- if (rwndValue != 0) {
- mSystemProperties.setTcpInitRwnd(rwndValue);
- }
}
@Override
@@ -2626,9 +2670,8 @@
// if the system property isn't set, use the value for the apn type
int ret = RESTORE_DEFAULT_NETWORK_DELAY;
- if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) &&
- (mNetConfigs[networkType] != null)) {
- ret = mNetConfigs[networkType].restoreTime;
+ if (mLegacyTypeTracker.isTypeSupported(networkType)) {
+ ret = mLegacyTypeTracker.getRestoreTimerForType(networkType);
}
return ret;
}
@@ -2861,7 +2904,7 @@
if (0 == defaultRequest.mRequests.size()) {
pw.println("none, this should never occur.");
} else {
- pw.println(defaultRequest.mRequests.get(0).networkCapabilities.getUids());
+ pw.println(defaultRequest.mRequests.get(0).networkCapabilities.getUidRanges());
}
pw.decreaseIndent();
pw.decreaseIndent();
@@ -3067,7 +3110,8 @@
nai.lastCaptivePortalDetected = visible;
nai.everCaptivePortalDetected |= visible;
if (nai.lastCaptivePortalDetected &&
- Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) {
+ ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID
+ == getCaptivePortalMode()) {
if (DBG) log("Avoiding captive portal network: " + nai.toShortString());
nai.onPreventAutomaticReconnect();
teardownUnneededNetwork(nai);
@@ -3178,8 +3222,8 @@
private int getCaptivePortalMode() {
return Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.CAPTIVE_PORTAL_MODE,
- Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
+ ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE,
+ ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT);
}
private boolean maybeHandleNetworkAgentInfoMessage(Message msg) {
@@ -3663,6 +3707,7 @@
mNetworkRequestInfoLogs.log("REGISTER " + 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()
@@ -3755,18 +3800,19 @@
// listen requests won't keep up a network satisfying it. If this is not a multilayer
// request, return immediately. For multilayer requests, check to see if any of the
// multilayer requests may have a potential satisfier.
- if (!nri.isMultilayerRequest() && nri.mRequests.get(0).isListen()) {
+ if (!nri.isMultilayerRequest() && (nri.mRequests.get(0).isListen()
+ || nri.mRequests.get(0).isListenForBest())) {
return false;
}
for (final NetworkRequest req : nri.mRequests) {
// This multilayer listen request is satisfied therefore no further requests need to be
// evaluated deeming this network not a potential satisfier.
- if (req.isListen() && nri.getActiveRequest() == req) {
+ if ((req.isListen() || req.isListenForBest()) && nri.getActiveRequest() == req) {
return false;
}
// As non-multilayer listen requests have already returned, the below would only happen
// for a multilayer request therefore continue to the next request if available.
- if (req.isListen()) {
+ if (req.isListen() || req.isListenForBest()) {
continue;
}
// If this Network is already the highest scoring Network for a request, or if
@@ -4530,12 +4576,17 @@
handleSetRequireVpnForUids(toBool(msg.arg1), (UidRange[]) msg.obj);
break;
case EVENT_SET_OEM_NETWORK_PREFERENCE: {
- final Pair<OemNetworkPreferences, IOnSetOemNetworkPreferenceListener> arg =
- (Pair<OemNetworkPreferences,
- IOnSetOemNetworkPreferenceListener>) msg.obj;
+ final Pair<OemNetworkPreferences, IOnCompleteListener> arg =
+ (Pair<OemNetworkPreferences, IOnCompleteListener>) msg.obj;
handleSetOemNetworkPreference(arg.first, arg.second);
break;
}
+ case EVENT_SET_PROFILE_NETWORK_PREFERENCE: {
+ final Pair<ProfileNetworkPreferences.Preference, IOnCompleteListener> arg =
+ (Pair<ProfileNetworkPreferences.Preference, IOnCompleteListener>)
+ msg.obj;
+ handleSetProfileNetworkPreference(arg.first, arg.second);
+ }
case EVENT_REPORT_NETWORK_ACTIVITY:
mNetworkActivityTracker.handleReportNetworkActivity();
break;
@@ -4834,6 +4885,10 @@
Log.wtf(TAG, s);
}
+ private static void logwtf(String s, Throwable t) {
+ Log.wtf(TAG, s, t);
+ }
+
private static void loge(String s) {
Log.e(TAG, s);
}
@@ -5106,6 +5161,9 @@
private void onUserRemoved(UserHandle user) {
mPermissionMonitor.onUserRemoved(user);
+ // If there was a network preference for this user, remove it.
+ handleSetProfileNetworkPreference(new ProfileNetworkPreferences.Preference(user, null),
+ null /* listener */);
if (mOemNetworkPreferences.getNetworkPreferences().size() > 0) {
handleSetOemNetworkPreference(mOemNetworkPreferences, null);
}
@@ -5264,9 +5322,8 @@
private Set<UidRange> getUids() {
// networkCapabilities.getUids() returns a defensive copy.
// multilayer requests will all have the same uids so return the first one.
- final Set<UidRange> uids = null == mRequests.get(0).networkCapabilities.getUids()
- ? new ArraySet<>() : mRequests.get(0).networkCapabilities.getUids();
- return uids;
+ final Set<UidRange> uids = mRequests.get(0).networkCapabilities.getUidRanges();
+ return (null == uids) ? new ArraySet<>() : uids;
}
NetworkRequestInfo(@NonNull final NetworkRequest r, @Nullable final PendingIntent pi,
@@ -5549,8 +5606,10 @@
// request if the app changes network state. http://b/29964605
enforceMeteredApnPolicy(networkCapabilities);
break;
- case TRACK_BEST:
- throw new UnsupportedOperationException("Not implemented yet");
+ case LISTEN_FOR_BEST:
+ enforceAccessPermission();
+ networkCapabilities = new NetworkCapabilities(networkCapabilities);
+ break;
default:
throw new IllegalArgumentException("Unsupported request type " + reqType);
}
@@ -5558,11 +5617,17 @@
ensureSufficientPermissionsForRequest(networkCapabilities,
Binder.getCallingPid(), callingUid, callingPackageName);
- // Set the UID range for this request to the single UID of the requester, or to an empty
- // set of UIDs if the caller has the appropriate permission and UIDs have not been set.
+ // 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);
@@ -5896,10 +5961,16 @@
@GuardedBy("mBlockedAppUids")
private final HashSet<Integer> mBlockedAppUids = new HashSet<>();
- // Current OEM network preferences.
+ // Current OEM network preferences. This object must only be written to on the handler thread.
+ // Since it is immutable and always non-null, other threads may read it if they only care
+ // about seeing a consistent object but not that it is current.
@NonNull
private OemNetworkPreferences mOemNetworkPreferences =
new OemNetworkPreferences.Builder().build();
+ // Current per-profile network preferences. This object follows the same threading rules as
+ // the OEM network preferences above.
+ @NonNull
+ private ProfileNetworkPreferences mProfileNetworkPreferences = new ProfileNetworkPreferences();
// The always-on request for an Internet-capable network that apps without a specific default
// fall back to.
@@ -6058,7 +6129,7 @@
for (final NetworkRequestInfo nri : mDefaultNetworkRequests) {
// Currently, all network requests will have the same uids therefore checking the first
// one is sufficient. If/when uids are tracked at the nri level, this can change.
- final Set<UidRange> uids = nri.mRequests.get(0).networkCapabilities.getUids();
+ final Set<UidRange> uids = nri.mRequests.get(0).networkCapabilities.getUidRanges();
if (null == uids) {
continue;
}
@@ -6499,7 +6570,7 @@
return;
}
- final Set<UidRange> ranges = nai.networkCapabilities.getUids();
+ final Set<UidRange> ranges = nai.networkCapabilities.getUidRanges();
final int vpnAppUid = nai.networkCapabilities.getOwnerUid();
// TODO: this create a window of opportunity for apps to receive traffic between the time
// when the old rules are removed and the time when new rules are added. To fix this,
@@ -6864,8 +6935,8 @@
private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc,
NetworkCapabilities newNc) {
- Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids();
- Set<UidRange> newRanges = null == newNc ? null : newNc.getUids();
+ Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUidRanges();
+ Set<UidRange> newRanges = null == newNc ? null : newNc.getUidRanges();
if (null == prevRanges) prevRanges = new ArraySet<>();
if (null == newRanges) newRanges = new ArraySet<>();
final Set<UidRange> prevRangesCopy = new ArraySet<>(prevRanges);
@@ -8088,7 +8159,7 @@
}
settingUrl = Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.CAPTIVE_PORTAL_HTTP_URL);
+ ConnectivitySettingsManager.CAPTIVE_PORTAL_HTTP_URL);
if (!TextUtils.isEmpty(settingUrl)) {
return settingUrl;
}
@@ -8170,11 +8241,11 @@
// restore private DNS settings to default mode (opportunistic)
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_PRIVATE_DNS)) {
Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OPPORTUNISTIC);
+ ConnectivitySettingsManager.PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OPPORTUNISTIC);
}
Settings.Global.putString(mContext.getContentResolver(),
- Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
+ ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null);
}
@Override
@@ -8879,13 +8950,13 @@
private int transportTypeToLegacyType(int type) {
switch (type) {
case NetworkCapabilities.TRANSPORT_CELLULAR:
- return ConnectivityManager.TYPE_MOBILE;
+ return TYPE_MOBILE;
case NetworkCapabilities.TRANSPORT_WIFI:
- return ConnectivityManager.TYPE_WIFI;
+ return TYPE_WIFI;
case NetworkCapabilities.TRANSPORT_BLUETOOTH:
- return ConnectivityManager.TYPE_BLUETOOTH;
+ return TYPE_BLUETOOTH;
case NetworkCapabilities.TRANSPORT_ETHERNET:
- return ConnectivityManager.TYPE_ETHERNET;
+ return TYPE_ETHERNET;
default:
loge("Unexpected transport in transportTypeToLegacyType: " + type);
}
@@ -8926,13 +8997,13 @@
if (networkAgent.networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_CELLULAR)) {
timeout = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.DATA_ACTIVITY_TIMEOUT_MOBILE,
+ ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_MOBILE,
10);
type = NetworkCapabilities.TRANSPORT_CELLULAR;
} else if (networkAgent.networkCapabilities.hasTransport(
NetworkCapabilities.TRANSPORT_WIFI)) {
timeout = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.DATA_ACTIVITY_TIMEOUT_WIFI,
+ ConnectivitySettingsManager.DATA_ACTIVITY_TIMEOUT_WIFI,
15);
type = NetworkCapabilities.TRANSPORT_WIFI;
} else {
@@ -9100,6 +9171,143 @@
mQosCallbackTracker.unregisterCallback(callback);
}
+ // Network preference per-profile and OEM network preferences can't be set at the same
+ // time, because it is unclear what should happen if both preferences are active for
+ // one given UID. To make it possible, the stack would have to clarify what would happen
+ // in case both are active at the same time. The implementation may have to be adjusted
+ // to implement the resulting rules. For example, a priority could be defined between them,
+ // where the OEM preference would be considered less or more important than the enterprise
+ // preference ; this would entail implementing the priorities somehow, e.g. by doing
+ // UID arithmetic with UID ranges or passing a priority to netd so that the routing rules
+ // are set at the right level. Other solutions are possible, e.g. merging of the
+ // preferences for the relevant UIDs.
+ private static void throwConcurrentPreferenceException() {
+ throw new IllegalStateException("Can't set NetworkPreferenceForUser and "
+ + "set OemNetworkPreference at the same time");
+ }
+
+ /**
+ * Request that a user profile is put by default on a network matching a given preference.
+ *
+ * See the documentation for the individual preferences for a description of the supported
+ * behaviors.
+ *
+ * @param profile the profile concerned.
+ * @param preference the preference for this profile, as one of the PROFILE_NETWORK_PREFERENCE_*
+ * constants.
+ * @param listener an optional listener to listen for completion of the operation.
+ */
+ @Override
+ public void setProfileNetworkPreference(@NonNull final UserHandle profile,
+ @ConnectivityManager.ProfileNetworkPreference final int preference,
+ @Nullable final IOnCompleteListener listener) {
+ Objects.requireNonNull(profile);
+ PermissionUtils.enforceNetworkStackPermission(mContext);
+ if (DBG) {
+ log("setProfileNetworkPreference " + profile + " to " + preference);
+ }
+ if (profile.getIdentifier() < 0) {
+ throw new IllegalArgumentException("Must explicitly specify a user handle ("
+ + "UserHandle.CURRENT not supported)");
+ }
+ final UserManager um;
+ try {
+ um = mContext.createContextAsUser(profile, 0 /* flags */)
+ .getSystemService(UserManager.class);
+ } catch (IllegalStateException e) {
+ throw new IllegalArgumentException("Profile does not exist");
+ }
+ if (!um.isManagedProfile()) {
+ throw new IllegalArgumentException("Profile must be a managed profile");
+ }
+ // Strictly speaking, mOemNetworkPreferences should only be touched on the
+ // handler thread. However it is an immutable object, so reading the reference is
+ // safe - it's just possible the value is slightly outdated. For the final check,
+ // see #handleSetProfileNetworkPreference. But if this can be caught here it is a
+ // lot easier to understand, so opportunistically check it.
+ if (!mOemNetworkPreferences.isEmpty()) {
+ throwConcurrentPreferenceException();
+ }
+ final NetworkCapabilities nc;
+ switch (preference) {
+ case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT:
+ nc = null;
+ break;
+ case ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE:
+ final UidRange uids = UidRange.createForUser(profile);
+ nc = createDefaultNetworkCapabilitiesForUidRange(uids);
+ nc.addCapability(NET_CAPABILITY_ENTERPRISE);
+ nc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+ break;
+ default:
+ throw new IllegalArgumentException(
+ "Invalid preference in setProfileNetworkPreference");
+ }
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_PROFILE_NETWORK_PREFERENCE,
+ new Pair<>(new ProfileNetworkPreferences.Preference(profile, nc), listener)));
+ }
+
+ private void validateNetworkCapabilitiesOfProfileNetworkPreference(
+ @Nullable final NetworkCapabilities nc) {
+ if (null == nc) return; // Null caps are always allowed. It means to remove the setting.
+ ensureRequestableCapabilities(nc);
+ }
+
+ private ArraySet<NetworkRequestInfo> createNrisFromProfileNetworkPreferences(
+ @NonNull final ProfileNetworkPreferences prefs) {
+ final ArraySet<NetworkRequestInfo> result = new ArraySet<>();
+ for (final ProfileNetworkPreferences.Preference pref : prefs.preferences) {
+ // The NRI for a user should be comprised of two layers:
+ // - The request for the capabilities
+ // - The request for the default network, for fallback. Create an image of it to
+ // have the correct UIDs in it (also a request can only be part of one NRI, because
+ // of lookups in 1:1 associations like mNetworkRequests).
+ // Note that denying a fallback can be implemented simply by not adding the second
+ // request.
+ final ArrayList<NetworkRequest> nrs = new ArrayList<>();
+ nrs.add(createNetworkRequest(NetworkRequest.Type.REQUEST, pref.capabilities));
+ nrs.add(createDefaultRequest());
+ setNetworkRequestUids(nrs, UidRange.fromIntRanges(pref.capabilities.getUids()));
+ final NetworkRequestInfo nri = new NetworkRequestInfo(nrs);
+ result.add(nri);
+ }
+ return result;
+ }
+
+ private void handleSetProfileNetworkPreference(
+ @NonNull final ProfileNetworkPreferences.Preference preference,
+ @Nullable final IOnCompleteListener listener) {
+ // setProfileNetworkPreference and setOemNetworkPreference are mutually exclusive, in
+ // particular because it's not clear what preference should win in case both apply
+ // to the same app.
+ // The binder call has already checked this, but as mOemNetworkPreferences is only
+ // touched on the handler thread, it's theoretically not impossible that it has changed
+ // since.
+ if (!mOemNetworkPreferences.isEmpty()) {
+ // This may happen on a device with an OEM preference set when a user is removed.
+ // In this case, it's safe to ignore. In particular this happens in the tests.
+ loge("handleSetProfileNetworkPreference, but OEM network preferences not empty");
+ return;
+ }
+
+ validateNetworkCapabilitiesOfProfileNetworkPreference(preference.capabilities);
+
+ mProfileNetworkPreferences = mProfileNetworkPreferences.plus(preference);
+ final ArraySet<NetworkRequestInfo> nris =
+ createNrisFromProfileNetworkPreferences(mProfileNetworkPreferences);
+ replaceDefaultNetworkRequestsForPreference(nris);
+ // Finally, rematch.
+ rematchAllNetworksAndRequests();
+
+ if (null != listener) {
+ try {
+ listener.onComplete();
+ } catch (RemoteException e) {
+ loge("Listener for setProfileNetworkPreference has died");
+ }
+ }
+ }
+
private void enforceAutomotiveDevice() {
final boolean isAutomotiveDevice =
mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
@@ -9118,17 +9326,26 @@
* Calling this will overwrite the existing preference.
*
* @param preference {@link OemNetworkPreferences} The application network preference to be set.
- * @param listener {@link ConnectivityManager.OnSetOemNetworkPreferenceListener} Listener used
+ * @param listener {@link ConnectivityManager.OnCompleteListener} Listener used
* to communicate completion of setOemNetworkPreference();
*/
@Override
public void setOemNetworkPreference(
@NonNull final OemNetworkPreferences preference,
- @Nullable final IOnSetOemNetworkPreferenceListener listener) {
+ @Nullable final IOnCompleteListener listener) {
enforceAutomotiveDevice();
enforceOemNetworkPreferencesPermission();
+ if (!mProfileNetworkPreferences.isEmpty()) {
+ // Strictly speaking, mProfileNetworkPreferences should only be touched on the
+ // handler thread. However it is an immutable object, so reading the reference is
+ // safe - it's just possible the value is slightly outdated. For the final check,
+ // see #handleSetOemPreference. But if this can be caught here it is a
+ // lot easier to understand, so opportunistically check it.
+ throwConcurrentPreferenceException();
+ }
+
Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null");
validateOemNetworkPreferences(preference);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_OEM_NETWORK_PREFERENCE,
@@ -9147,11 +9364,22 @@
private void handleSetOemNetworkPreference(
@NonNull final OemNetworkPreferences preference,
- @Nullable final IOnSetOemNetworkPreferenceListener listener) {
+ @Nullable final IOnCompleteListener listener) {
Objects.requireNonNull(preference, "OemNetworkPreferences must be non-null");
if (DBG) {
log("set OEM network preferences :" + preference.toString());
}
+ // setProfileNetworkPreference and setOemNetworkPreference are mutually exclusive, in
+ // particular because it's not clear what preference should win in case both apply
+ // to the same app.
+ // The binder call has already checked this, but as mOemNetworkPreferences is only
+ // touched on the handler thread, it's theoretically not impossible that it has changed
+ // since.
+ if (!mProfileNetworkPreferences.isEmpty()) {
+ logwtf("handleSetOemPreference, but per-profile network preferences not empty");
+ return;
+ }
+
final ArraySet<NetworkRequestInfo> nris =
new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(preference);
replaceDefaultNetworkRequestsForPreference(nris);
@@ -9255,9 +9483,8 @@
private static void setNetworkRequestUids(@NonNull final List<NetworkRequest> requests,
@NonNull final Set<UidRange> uids) {
- final Set<UidRange> ranges = new ArraySet<>(uids);
for (final NetworkRequest req : requests) {
- req.networkCapabilities.setUids(ranges);
+ req.networkCapabilities.setUids(UidRange.toIntRanges(uids));
}
}
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index 7a5abf8..ffeb77d 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -18,15 +18,15 @@
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
+import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_MAX_SAMPLES;
+import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_MIN_SAMPLES;
+import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS;
+import static android.net.ConnectivitySettingsManager.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER;
import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE;
import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS;
-import static android.provider.Settings.Global.DNS_RESOLVER_MAX_SAMPLES;
-import static android.provider.Settings.Global.DNS_RESOLVER_MIN_SAMPLES;
-import static android.provider.Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS;
-import static android.provider.Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT;
-import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE;
-import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
-import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import android.annotation.NonNull;
import android.content.ContentResolver;
@@ -127,13 +127,17 @@
private static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8;
private static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64;
- public static PrivateDnsConfig getPrivateDnsConfig(ContentResolver cr) {
- final String mode = ConnectivityManager.getPrivateDnsMode(cr);
+ /**
+ * Get PrivateDnsConfig.
+ */
+ public static PrivateDnsConfig getPrivateDnsConfig(Context context) {
+ final String mode = ConnectivityManager.getPrivateDnsMode(context);
final boolean useTls = !TextUtils.isEmpty(mode) && !PRIVATE_DNS_MODE_OFF.equals(mode);
if (PRIVATE_DNS_MODE_PROVIDER_HOSTNAME.equals(mode)) {
- final String specifier = getStringSetting(cr, PRIVATE_DNS_SPECIFIER);
+ final String specifier = getStringSetting(context.getContentResolver(),
+ PRIVATE_DNS_SPECIFIER);
return new PrivateDnsConfig(specifier, null);
}
@@ -268,7 +272,7 @@
}
public PrivateDnsConfig getPrivateDnsConfig() {
- return getPrivateDnsConfig(mContentResolver);
+ return getPrivateDnsConfig(mContext);
}
public void removeNetwork(Network network) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 9dcc55b..e44dcf5 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -719,6 +719,7 @@
break;
case LISTEN:
+ case LISTEN_FOR_BEST:
case TRACK_DEFAULT:
case TRACK_SYSTEM_DEFAULT:
break;
diff --git a/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java b/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java
new file mode 100644
index 0000000..dd2815d
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/ProfileNetworkPreferences.java
@@ -0,0 +1,87 @@
+/*
+ * 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.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.NetworkCapabilities;
+import android.os.UserHandle;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A data class containing all the per-profile network preferences.
+ *
+ * A given profile can only have one preference.
+ */
+public class ProfileNetworkPreferences {
+ /**
+ * A single preference, as it applies to a given user profile.
+ */
+ public static class Preference {
+ @NonNull public final UserHandle user;
+ // Capabilities are only null when sending an object to remove the setting for a user
+ @Nullable public final NetworkCapabilities capabilities;
+
+ public Preference(@NonNull final UserHandle user,
+ @Nullable final NetworkCapabilities capabilities) {
+ this.user = user;
+ this.capabilities = null == capabilities ? null : new NetworkCapabilities(capabilities);
+ }
+
+ /** toString */
+ public String toString() {
+ return "[ProfileNetworkPreference user=" + user + " caps=" + capabilities + "]";
+ }
+ }
+
+ @NonNull public final List<Preference> preferences;
+
+ public ProfileNetworkPreferences() {
+ preferences = Collections.EMPTY_LIST;
+ }
+
+ private ProfileNetworkPreferences(@NonNull final List<Preference> list) {
+ preferences = Collections.unmodifiableList(list);
+ }
+
+ /**
+ * Returns a new object consisting of this object plus the passed preference.
+ *
+ * If a preference already exists for the same user, it will be replaced by the passed
+ * preference. Passing a Preference object containing a null capabilities object is equivalent
+ * to (and indeed, implemented as) removing the preference for this user.
+ */
+ public ProfileNetworkPreferences plus(@NonNull final Preference pref) {
+ final ArrayList<Preference> newPrefs = new ArrayList<>();
+ for (final Preference existingPref : preferences) {
+ if (!existingPref.user.equals(pref.user)) {
+ newPrefs.add(existingPref);
+ }
+ }
+ if (null != pref.capabilities) {
+ newPrefs.add(pref);
+ }
+ return new ProfileNetworkPreferences(newPrefs);
+ }
+
+ public boolean isEmpty() {
+ return preferences.isEmpty();
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index 8b9c836..f883307 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -16,10 +16,10 @@
package com.android.server.connectivity;
-import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST;
-import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_HOST;
-import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_PAC;
-import static android.provider.Settings.Global.GLOBAL_HTTP_PROXY_PORT;
+import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_EXCLUSION_LIST;
+import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_HOST;
+import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_PAC;
+import static android.net.ConnectivitySettingsManager.GLOBAL_HTTP_PROXY_PORT;
import static android.provider.Settings.Global.HTTP_PROXY;
import android.annotation.NonNull;
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index 0dfec75..a7ad695 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -69,6 +69,7 @@
import android.os.Build;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
+import android.util.Range;
import androidx.test.runner.AndroidJUnit4;
@@ -240,72 +241,93 @@
@Test
public void testSetUids() {
final NetworkCapabilities netCap = new NetworkCapabilities();
- final Set<UidRange> uids = new ArraySet<>();
- uids.add(new UidRange(50, 100));
- uids.add(new UidRange(3000, 4000));
- netCap.setUids(uids);
- assertTrue(netCap.appliesToUid(50));
- assertTrue(netCap.appliesToUid(80));
- assertTrue(netCap.appliesToUid(100));
+ // Null uids match all UIDs
+ netCap.setUids(null);
+ assertTrue(netCap.appliesToUid(10));
+ assertTrue(netCap.appliesToUid(200));
assertTrue(netCap.appliesToUid(3000));
- assertTrue(netCap.appliesToUid(3001));
- assertFalse(netCap.appliesToUid(10));
- assertFalse(netCap.appliesToUid(25));
- assertFalse(netCap.appliesToUid(49));
- assertFalse(netCap.appliesToUid(101));
- assertFalse(netCap.appliesToUid(2000));
- assertFalse(netCap.appliesToUid(100000));
-
+ assertTrue(netCap.appliesToUid(10010));
assertTrue(netCap.appliesToUidRange(new UidRange(50, 100)));
assertTrue(netCap.appliesToUidRange(new UidRange(70, 72)));
assertTrue(netCap.appliesToUidRange(new UidRange(3500, 3912)));
- assertFalse(netCap.appliesToUidRange(new UidRange(1, 100)));
- assertFalse(netCap.appliesToUidRange(new UidRange(49, 100)));
- assertFalse(netCap.appliesToUidRange(new UidRange(1, 10)));
- assertFalse(netCap.appliesToUidRange(new UidRange(60, 101)));
- assertFalse(netCap.appliesToUidRange(new UidRange(60, 3400)));
-
- NetworkCapabilities netCap2 = new NetworkCapabilities();
- // A new netcap object has null UIDs, so anything will satisfy it.
- assertTrue(netCap2.satisfiedByUids(netCap));
- // Still not equal though.
- assertFalse(netCap2.equalsUids(netCap));
- netCap2.setUids(uids);
- assertTrue(netCap2.satisfiedByUids(netCap));
- assertTrue(netCap.equalsUids(netCap2));
- assertTrue(netCap2.equalsUids(netCap));
-
- uids.add(new UidRange(600, 700));
- netCap2.setUids(uids);
- assertFalse(netCap2.satisfiedByUids(netCap));
- assertFalse(netCap.appliesToUid(650));
- assertTrue(netCap2.appliesToUid(650));
- netCap.combineCapabilities(netCap2);
- assertTrue(netCap2.satisfiedByUids(netCap));
- assertTrue(netCap.appliesToUid(650));
- assertFalse(netCap.appliesToUid(500));
-
- assertTrue(new NetworkCapabilities().satisfiedByUids(netCap));
- netCap.combineCapabilities(new NetworkCapabilities());
- assertTrue(netCap.appliesToUid(500));
assertTrue(netCap.appliesToUidRange(new UidRange(1, 100000)));
- assertFalse(netCap2.appliesToUid(500));
- assertFalse(netCap2.appliesToUidRange(new UidRange(1, 100000)));
- assertTrue(new NetworkCapabilities().satisfiedByUids(netCap));
+
+ if (isAtLeastS()) {
+ final Set<Range<Integer>> uids = new ArraySet<>();
+ uids.add(uidRange(50, 100));
+ uids.add(uidRange(3000, 4000));
+ netCap.setUids(uids);
+ assertTrue(netCap.appliesToUid(50));
+ assertTrue(netCap.appliesToUid(80));
+ assertTrue(netCap.appliesToUid(100));
+ assertTrue(netCap.appliesToUid(3000));
+ assertTrue(netCap.appliesToUid(3001));
+ assertFalse(netCap.appliesToUid(10));
+ assertFalse(netCap.appliesToUid(25));
+ assertFalse(netCap.appliesToUid(49));
+ assertFalse(netCap.appliesToUid(101));
+ assertFalse(netCap.appliesToUid(2000));
+ assertFalse(netCap.appliesToUid(100000));
+
+ assertTrue(netCap.appliesToUidRange(new UidRange(50, 100)));
+ assertTrue(netCap.appliesToUidRange(new UidRange(70, 72)));
+ assertTrue(netCap.appliesToUidRange(new UidRange(3500, 3912)));
+ assertFalse(netCap.appliesToUidRange(new UidRange(1, 100)));
+ assertFalse(netCap.appliesToUidRange(new UidRange(49, 100)));
+ assertFalse(netCap.appliesToUidRange(new UidRange(1, 10)));
+ assertFalse(netCap.appliesToUidRange(new UidRange(60, 101)));
+ assertFalse(netCap.appliesToUidRange(new UidRange(60, 3400)));
+
+ NetworkCapabilities netCap2 = new NetworkCapabilities();
+ // A new netcap object has null UIDs, so anything will satisfy it.
+ assertTrue(netCap2.satisfiedByUids(netCap));
+ // Still not equal though.
+ assertFalse(netCap2.equalsUids(netCap));
+ netCap2.setUids(uids);
+ assertTrue(netCap2.satisfiedByUids(netCap));
+ assertTrue(netCap.equalsUids(netCap2));
+ assertTrue(netCap2.equalsUids(netCap));
+
+ uids.add(uidRange(600, 700));
+ netCap2.setUids(uids);
+ assertFalse(netCap2.satisfiedByUids(netCap));
+ assertFalse(netCap.appliesToUid(650));
+ assertTrue(netCap2.appliesToUid(650));
+ netCap.combineCapabilities(netCap2);
+ assertTrue(netCap2.satisfiedByUids(netCap));
+ assertTrue(netCap.appliesToUid(650));
+ assertFalse(netCap.appliesToUid(500));
+
+ assertTrue(new NetworkCapabilities().satisfiedByUids(netCap));
+ netCap.combineCapabilities(new NetworkCapabilities());
+ assertTrue(netCap.appliesToUid(500));
+ assertTrue(netCap.appliesToUidRange(new UidRange(1, 100000)));
+ assertFalse(netCap2.appliesToUid(500));
+ assertFalse(netCap2.appliesToUidRange(new UidRange(1, 100000)));
+ assertTrue(new NetworkCapabilities().satisfiedByUids(netCap));
+
+ // Null uids satisfies everything.
+ netCap.setUids(null);
+ assertTrue(netCap2.satisfiedByUids(netCap));
+ assertTrue(netCap.satisfiedByUids(netCap2));
+ netCap2.setUids(null);
+ assertTrue(netCap2.satisfiedByUids(netCap));
+ assertTrue(netCap.satisfiedByUids(netCap2));
+ }
}
@Test
public void testParcelNetworkCapabilities() {
- final Set<UidRange> uids = new ArraySet<>();
- uids.add(new UidRange(50, 100));
- uids.add(new UidRange(3000, 4000));
+ final Set<Range<Integer>> uids = new ArraySet<>();
+ uids.add(uidRange(50, 100));
+ uids.add(uidRange(3000, 4000));
final NetworkCapabilities netCap = new NetworkCapabilities()
.addCapability(NET_CAPABILITY_INTERNET)
- .setUids(uids)
.addCapability(NET_CAPABILITY_EIMS)
.addCapability(NET_CAPABILITY_NOT_METERED);
if (isAtLeastS()) {
netCap.setSubIds(Set.of(TEST_SUBID1, TEST_SUBID2));
+ netCap.setUids(uids);
} else if (isAtLeastR()) {
netCap.setOwnerUid(123);
netCap.setAdministratorUids(new int[] {5, 11});
@@ -540,12 +562,16 @@
assertFalse(nc1.satisfiedByNetworkCapabilities(nc2));
}
- private ArraySet<UidRange> uidRange(int from, int to) {
- final ArraySet<UidRange> range = new ArraySet<>(1);
- range.add(new UidRange(from, to));
+ private ArraySet<Range<Integer>> uidRanges(int from, int to) {
+ final ArraySet<Range<Integer>> range = new ArraySet<>(1);
+ range.add(uidRange(from, to));
return range;
}
+ private Range<Integer> uidRange(int from, int to) {
+ return new Range<Integer>(from, to);
+ }
+
@Test @IgnoreUpTo(Build.VERSION_CODES.Q)
public void testSetAdministratorUids() {
NetworkCapabilities nc =
@@ -601,23 +627,23 @@
} catch (IllegalStateException expected) {}
nc1.setSSID(TEST_SSID);
- nc1.setUids(uidRange(10, 13));
- assertNotEquals(nc1, nc2);
- nc2.combineCapabilities(nc1); // Everything + 10~13 is still everything.
- assertNotEquals(nc1, nc2);
- nc1.combineCapabilities(nc2); // 10~13 + everything is everything.
- assertEquals(nc1, nc2);
- nc1.setUids(uidRange(10, 13));
- nc2.setUids(uidRange(20, 23));
- assertNotEquals(nc1, nc2);
- nc1.combineCapabilities(nc2);
- assertTrue(nc1.appliesToUid(12));
- assertFalse(nc2.appliesToUid(12));
- assertTrue(nc1.appliesToUid(22));
- assertTrue(nc2.appliesToUid(22));
-
- // Verify the subscription id list can be combined only when they are equal.
if (isAtLeastS()) {
+ nc1.setUids(uidRanges(10, 13));
+ assertNotEquals(nc1, nc2);
+ nc2.combineCapabilities(nc1); // Everything + 10~13 is still everything.
+ assertNotEquals(nc1, nc2);
+ nc1.combineCapabilities(nc2); // 10~13 + everything is everything.
+ assertEquals(nc1, nc2);
+ nc1.setUids(uidRanges(10, 13));
+ nc2.setUids(uidRanges(20, 23));
+ assertNotEquals(nc1, nc2);
+ nc1.combineCapabilities(nc2);
+ assertTrue(nc1.appliesToUid(12));
+ assertFalse(nc2.appliesToUid(12));
+ assertTrue(nc1.appliesToUid(22));
+ assertTrue(nc2.appliesToUid(22));
+
+ // Verify the subscription id list can be combined only when they are equal.
nc1.setSubIds(Set.of(TEST_SUBID1, TEST_SUBID2));
nc2.setSubIds(Set.of(TEST_SUBID2));
assertThrows(IllegalStateException.class, () -> nc2.combineCapabilities(nc1));
@@ -773,8 +799,11 @@
if (isAtLeastR()) {
assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSsid()));
}
-
- nc1.setUids(uidRange(10, 13));
+ if (isAtLeastS()) {
+ nc1.setUids(uidRanges(10, 13));
+ } else {
+ nc1.setUids(null);
+ }
nc2.set(nc1); // Overwrites, as opposed to combineCapabilities
assertEquals(nc1, nc2);
diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
index 01d8186..e2d43cb 100644
--- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
+++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java
@@ -44,11 +44,11 @@
import android.net.NetworkSpecifier;
import android.net.QosFilter;
import android.net.SocketKeepalive;
-import android.net.UidRange;
import android.os.ConditionVariable;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
+import android.util.Range;
import com.android.net.module.util.ArrayTrackRecord;
import com.android.server.connectivity.ConnectivityConstants;
@@ -222,7 +222,7 @@
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
- public void setUids(Set<UidRange> uids) {
+ public void setUids(Set<Range<Integer>> uids) {
mNetworkCapabilities.setUids(uids);
mNetworkAgent.sendNetworkCapabilities(mNetworkCapabilities);
}
diff --git a/tests/net/java/android/net/VpnTransportInfoTest.java b/tests/net/java/android/net/VpnTransportInfoTest.java
index d04c87b..b7a42ec 100644
--- a/tests/net/java/android/net/VpnTransportInfoTest.java
+++ b/tests/net/java/android/net/VpnTransportInfoTest.java
@@ -42,7 +42,13 @@
VpnTransportInfo v1 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
VpnTransportInfo v2 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE);
VpnTransportInfo v3 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM);
+ VpnTransportInfo v4 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY);
+ VpnTransportInfo v5 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM);
+
assertNotEquals(v1, v2);
+ assertNotEquals(v3, v4);
+ assertNotEquals(v4, v5);
+
assertEquals(v1, v3);
assertEquals(v1.hashCode(), v3.hashCode());
}
diff --git a/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt b/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt
index c1315f6..1945ce7 100644
--- a/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt
+++ b/tests/net/java/android/net/util/MultinetworkPolicyTrackerTest.kt
@@ -21,10 +21,10 @@
import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER
import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_PERFORMANCE
import android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY
+import android.net.ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI
+import android.net.ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE
import android.net.util.MultinetworkPolicyTracker.ActiveDataSubscriptionIdListener
import android.provider.Settings
-import android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI
-import android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index cc58edf..b25a541 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -23,6 +23,8 @@
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.Intent.ACTION_USER_UNLOCKED;
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
+import static android.content.pm.PackageManager.FEATURE_WIFI;
+import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
@@ -35,11 +37,14 @@
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
+import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
+import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
+import static android.net.ConnectivityManager.TYPE_PROXY;
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
@@ -174,6 +179,7 @@
import android.net.ConnectivityManager.PacketKeepalive;
import android.net.ConnectivityManager.PacketKeepaliveCallback;
import android.net.ConnectivityManager.TooManyRequestsException;
+import android.net.ConnectivitySettingsManager;
import android.net.ConnectivityThread;
import android.net.DataStallReportParcelable;
import android.net.EthernetManager;
@@ -183,7 +189,7 @@
import android.net.INetworkMonitor;
import android.net.INetworkMonitorCallbacks;
import android.net.INetworkPolicyListener;
-import android.net.IOnSetOemNetworkPreferenceListener;
+import android.net.IOnCompleteListener;
import android.net.IQosCallback;
import android.net.InetAddresses;
import android.net.InterfaceConfigurationParcel;
@@ -261,6 +267,7 @@
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
+import android.util.Range;
import android.util.SparseArray;
import androidx.test.InstrumentationRegistry;
@@ -378,6 +385,11 @@
// Set a non-zero value to verify the flow to set tcp init rwnd value.
private static final int TEST_TCP_INIT_RWND = 60;
+ // Used for testing the per-work-profile default network.
+ private static final int TEST_APP_ID = 103;
+ private static final int TEST_WORK_PROFILE_USER_ID = 2;
+ private static final int TEST_WORK_PROFILE_APP_UID =
+ UserHandle.getUid(TEST_WORK_PROFILE_USER_ID, TEST_APP_ID);
private static final String CLAT_PREFIX = "v4-";
private static final String MOBILE_IFNAME = "test_rmnet_data0";
private static final String WIFI_IFNAME = "test_wlan0";
@@ -421,6 +433,7 @@
private VpnManagerService mVpnManagerService;
private TestNetworkCallback mDefaultNetworkCallback;
private TestNetworkCallback mSystemDefaultNetworkCallback;
+ private TestNetworkCallback mProfileDefaultNetworkCallback;
// State variables required to emulate NetworkPolicyManagerService behaviour.
private int mUidRules = RULE_NONE;
@@ -542,13 +555,26 @@
return super.getSystemService(name);
}
+ final HashMap<UserHandle, UserManager> mUserManagers = new HashMap<>();
@Override
public Context createContextAsUser(UserHandle user, int flags) {
final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this));
doReturn(user).when(asUser).getUser();
+ doAnswer((inv) -> {
+ final UserManager um = mUserManagers.computeIfAbsent(user,
+ u -> mock(UserManager.class, AdditionalAnswers.delegatesTo(mUserManager)));
+ return um;
+ }).when(asUser).getSystemService(Context.USER_SERVICE);
return asUser;
}
+ public void setWorkProfile(@NonNull final UserHandle userHandle, boolean value) {
+ // This relies on all contexts for a given user returning the same UM mock
+ final UserManager umMock = createContextAsUser(userHandle, 0 /* flags */)
+ .getSystemService(UserManager.class);
+ doReturn(value).when(umMock).isManagedProfile();
+ }
+
@Override
public ContentResolver getContentResolver() {
return mContentResolver;
@@ -1079,6 +1105,10 @@
public void triggerUnfulfillable(NetworkRequest r) {
super.releaseRequestAsUnfulfillableByAnyFactory(r);
}
+
+ public void assertNoRequestChanged() {
+ assertNull(mRequestHistory.poll(0, r -> true));
+ }
}
private Set<UidRange> uidRangesForUids(int... uids) {
@@ -1130,7 +1160,7 @@
}
public void setUids(Set<UidRange> uids) {
- mNetworkCapabilities.setUids(uids);
+ mNetworkCapabilities.setUids(UidRange.toIntRanges(uids));
if (mAgentRegistered) {
mMockNetworkAgent.setNetworkCapabilities(mNetworkCapabilities, true);
}
@@ -1404,18 +1434,39 @@
fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
}
- private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback,
- int uid) {
+ private <T> T doAsUid(final int uid, @NonNull final Supplier<T> what) {
when(mDeps.getCallingUid()).thenReturn(uid);
try {
- mCm.registerNetworkCallback(request, callback);
- waitForIdle();
+ return what.get();
} finally {
returnRealCallingUid();
}
}
+ private void doAsUid(final int uid, @NonNull final Runnable what) {
+ doAsUid(uid, () -> {
+ what.run(); return Void.TYPE;
+ });
+ }
+
+ private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback,
+ int uid) {
+ doAsUid(uid, () -> {
+ mCm.registerNetworkCallback(request, callback);
+ });
+ }
+
+ private void registerDefaultNetworkCallbackAsUid(@NonNull final NetworkCallback callback,
+ final int uid) {
+ doAsUid(uid, () -> {
+ mCm.registerDefaultNetworkCallback(callback);
+ waitForIdle();
+ });
+ }
+
private static final int PRIMARY_USER = 0;
+ private static final UidRange PRIMARY_UIDRANGE =
+ UidRange.createForUser(UserHandle.of(PRIMARY_USER));
private static final int APP1_UID = UserHandle.getUid(PRIMARY_USER, 10100);
private static final int APP2_UID = UserHandle.getUid(PRIMARY_USER, 10101);
private static final int VPN_UID = UserHandle.getUid(PRIMARY_USER, 10043);
@@ -1461,6 +1512,9 @@
Looper.prepare();
}
mockDefaultPackages();
+ mockHasSystemFeature(FEATURE_WIFI, true);
+ mockHasSystemFeature(FEATURE_WIFI_DIRECT, true);
+ doReturn(true).when(mTelephonyManager).isDataCapable();
FakeSettingsProvider.clearSettingsProvider();
mServiceContext = new MockContext(InstrumentationRegistry.getContext(),
@@ -1503,7 +1557,7 @@
mQosCallbackTracker = mock(QosCallbackTracker.class);
// Ensure that the default setting for Captive Portals is used for most tests
- setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
+ setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_PROMPT);
setAlwaysOnNetworks(false);
setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
}
@@ -1513,10 +1567,7 @@
}
private ConnectivityService.Dependencies makeDependencies() {
- doReturn(TEST_TCP_INIT_RWND).when(mSystemProperties)
- .getInt("net.tcp.default_init_rwnd", 0);
doReturn(false).when(mSystemProperties).getBoolean("ro.radio.noril", false);
- doNothing().when(mSystemProperties).setTcpInitRwnd(anyInt());
final ConnectivityService.Dependencies deps = mock(ConnectivityService.Dependencies.class);
doReturn(mCsHandlerThread).when(deps).makeHandlerThread();
doReturn(mNetIdManager).when(deps).makeNetIdManager();
@@ -1574,6 +1625,7 @@
@After
public void tearDown() throws Exception {
unregisterDefaultNetworkCallbacks();
+ maybeTearDownEnterpriseNetwork();
setAlwaysOnNetworks(false);
if (mCellNetworkAgent != null) {
mCellNetworkAgent.disconnect();
@@ -1784,7 +1836,8 @@
assertTrue(mCm.isNetworkSupported(TYPE_WIFI));
assertTrue(mCm.isNetworkSupported(TYPE_MOBILE));
assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS));
- assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
+ assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_FOTA));
+ assertFalse(mCm.isNetworkSupported(TYPE_PROXY));
// Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our
// mocks, this assert exercises the ConnectivityService code path that ensures that
@@ -3357,7 +3410,7 @@
.addCapability(NET_CAPABILITY_VALIDATED).build();
mCm.registerNetworkCallback(validatedRequest, validatedCallback);
- setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
+ setCaptivePortalMode(ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE_AVOID);
// Bring up a network with a captive portal.
// Expect it to fail to connect and not result in any callbacks.
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
@@ -4007,20 +4060,21 @@
private void setCaptivePortalMode(int mode) {
ContentResolver cr = mServiceContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
+ Settings.Global.putInt(cr, ConnectivitySettingsManager.CAPTIVE_PORTAL_MODE, mode);
}
private void setAlwaysOnNetworks(boolean enable) {
ContentResolver cr = mServiceContext.getContentResolver();
- Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
+ Settings.Global.putInt(cr, ConnectivitySettingsManager.MOBILE_DATA_ALWAYS_ON,
+ enable ? 1 : 0);
mService.updateAlwaysOnNetworks();
waitForIdle();
}
private void setPrivateDnsSettings(String mode, String specifier) {
final ContentResolver cr = mServiceContext.getContentResolver();
- Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_MODE, mode);
- Settings.Global.putString(cr, Settings.Global.PRIVATE_DNS_SPECIFIER, specifier);
+ Settings.Global.putString(cr, ConnectivitySettingsManager.PRIVATE_DNS_MODE, mode);
+ Settings.Global.putString(cr, ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER, specifier);
mService.updatePrivateDnsSettings();
waitForIdle();
}
@@ -4258,7 +4312,7 @@
@Test
public void testAvoidBadWifiSetting() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver();
- final String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
+ final String settingName = ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI;
mPolicyTracker.mConfigRestrictsAvoidBadWifi = false;
String[] values = new String[] {null, "0", "1"};
@@ -4315,7 +4369,7 @@
TestNetworkCallback validatedWifiCallback = new TestNetworkCallback();
mCm.registerNetworkCallback(validatedWifiRequest, validatedWifiCallback);
- Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 0);
+ Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 0);
mPolicyTracker.reevaluate();
// Bring up validated cell.
@@ -4383,7 +4437,7 @@
validatedWifiCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
// Simulate the user selecting "switch" and checking the don't ask again checkbox.
- Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
+ Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
mPolicyTracker.reevaluate();
// We now switch to cell.
@@ -4396,11 +4450,11 @@
// Simulate the user turning the cellular fallback setting off and then on.
// We switch to wifi and then to cell.
- Settings.Global.putString(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, null);
+ Settings.Global.putString(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, null);
mPolicyTracker.reevaluate();
defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
assertEquals(mCm.getActiveNetwork(), wifiNetwork);
- Settings.Global.putInt(cr, Settings.Global.NETWORK_AVOID_BAD_WIFI, 1);
+ Settings.Global.putInt(cr, ConnectivitySettingsManager.NETWORK_AVOID_BAD_WIFI, 1);
mPolicyTracker.reevaluate();
defaultCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
assertEquals(mCm.getActiveNetwork(), cellNetwork);
@@ -4419,7 +4473,7 @@
@Test
public void testMeteredMultipathPreferenceSetting() throws Exception {
final ContentResolver cr = mServiceContext.getContentResolver();
- final String settingName = Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
+ final String settingName = ConnectivitySettingsManager.NETWORK_METERED_MULTIPATH_PREFERENCE;
for (int config : Arrays.asList(0, 3, 2)) {
for (String setting: Arrays.asList(null, "0", "2", "1")) {
@@ -6895,7 +6949,7 @@
final int uid = Process.myUid();
NetworkCapabilities nc = mCm.getNetworkCapabilities(mMockVpn.getNetwork());
assertNotNull("nc=" + nc, nc.getUids());
- assertEquals(nc.getUids(), uidRangesForUids(uid));
+ assertEquals(nc.getUids(), UidRange.toIntRanges(uidRangesForUids(uid)));
assertVpnTransportInfo(nc, VpnManager.TYPE_VPN_SERVICE);
// Set an underlying network and expect to see the VPN transports change.
@@ -6920,10 +6974,13 @@
// Expect that the VPN UID ranges contain both |uid| and the UID range for the newly-added
// restricted user.
+ final UidRange rRange = UidRange.createForUser(UserHandle.of(RESTRICTED_USER));
+ final Range<Integer> restrictUidRange = new Range<Integer>(rRange.start, rRange.stop);
+ final Range<Integer> singleUidRange = new Range<Integer>(uid, uid);
callback.expectCapabilitiesThat(mMockVpn, (caps)
-> caps.getUids().size() == 2
- && caps.getUids().contains(new UidRange(uid, uid))
- && caps.getUids().contains(createUidRange(RESTRICTED_USER))
+ && caps.getUids().contains(singleUidRange)
+ && caps.getUids().contains(restrictUidRange)
&& caps.hasTransport(TRANSPORT_VPN)
&& caps.hasTransport(TRANSPORT_WIFI));
@@ -6932,8 +6989,8 @@
callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
callback.expectCapabilitiesThat(mMockVpn, (caps)
-> caps.getUids().size() == 2
- && caps.getUids().contains(new UidRange(uid, uid))
- && caps.getUids().contains(createUidRange(RESTRICTED_USER))
+ && caps.getUids().contains(singleUidRange)
+ && caps.getUids().contains(restrictUidRange)
&& caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_WIFI));
@@ -6947,7 +7004,7 @@
// change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved.
callback.expectCapabilitiesThat(mMockVpn, (caps)
-> caps.getUids().size() == 1
- && caps.getUids().contains(new UidRange(uid, uid))
+ && caps.getUids().contains(singleUidRange)
&& caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_WIFI));
}
@@ -7605,7 +7662,7 @@
assertNotNull(underlying);
mMockVpn.setVpnType(VpnManager.TYPE_VPN_LEGACY);
// The legacy lockdown VPN only supports userId 0.
- final Set<UidRange> ranges = Collections.singleton(createUidRange(PRIMARY_USER));
+ final Set<UidRange> ranges = Collections.singleton(PRIMARY_UIDRANGE);
mMockVpn.registerAgent(ranges);
mMockVpn.setUnderlyingNetworks(new Network[]{underlying});
mMockVpn.connect(true);
@@ -7993,7 +8050,6 @@
// Switching default network updates TCP buffer sizes.
verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
- verify(mSystemProperties, times(1)).setTcpInitRwnd(eq(TEST_TCP_INIT_RWND));
// Add an IPv4 address. Expect prefix discovery to be stopped. Netd doesn't tell us that
// the NAT64 prefix was removed because one was never discovered.
cellLp.addLinkAddress(myIpv4);
@@ -8479,14 +8535,12 @@
mCellNetworkAgent.connect(false);
networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
- verify(mSystemProperties, times(1)).setTcpInitRwnd(eq(TEST_TCP_INIT_RWND));
// Change link Properties should have updated tcp buffer size.
LinkProperties lp = new LinkProperties();
lp.setTcpBufferSizes(testTcpBufferSizes);
mCellNetworkAgent.sendLinkProperties(lp);
networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
verifyTcpBufferSizeChange(testTcpBufferSizes);
- verify(mSystemProperties, times(2)).setTcpInitRwnd(eq(TEST_TCP_INIT_RWND));
// Clean up.
mCellNetworkAgent.disconnect();
networkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
@@ -8570,7 +8624,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
// The uid range needs to cover the test app so the network is visible to it.
- final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
mMockVpn.establish(lp, VPN_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
@@ -8598,7 +8652,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
- final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
@@ -8614,7 +8668,7 @@
lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
// The uid range needs to cover the test app so the network is visible to it.
- final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
@@ -8629,7 +8683,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
- final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
mMockVpn.establish(lp, VPN_UID, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
@@ -8681,7 +8735,7 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
// The uid range needs to cover the test app so the network is visible to it.
- final UidRange vpnRange = createUidRange(PRIMARY_USER);
+ final UidRange vpnRange = PRIMARY_UIDRANGE;
final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
mMockVpn.establish(lp, VPN_UID, vpnRanges);
assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
@@ -8962,7 +9016,7 @@
private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
throws Exception {
- final Set<UidRange> vpnRange = Collections.singleton(createUidRange(PRIMARY_USER));
+ final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
mMockVpn.setVpnType(vpnType);
mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange);
assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid);
@@ -9522,7 +9576,7 @@
lp.setInterfaceName("tun0");
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
- final UidRange vpnRange = createUidRange(PRIMARY_USER);
+ final UidRange vpnRange = PRIMARY_UIDRANGE;
Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
mMockVpn.establish(lp, VPN_UID, vpnRanges);
assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
@@ -9720,7 +9774,7 @@
.thenReturn(hasFeature);
}
- private UidRange getNriFirstUidRange(
+ private Range<Integer> getNriFirstUidRange(
@NonNull final ConnectivityService.NetworkRequestInfo nri) {
return nri.mRequests.get(0).networkCapabilities.getUids().iterator().next();
}
@@ -9903,11 +9957,11 @@
pref));
// Sort by uid to access nris by index
- nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).start));
- assertEquals(TEST_PACKAGE_UID, getNriFirstUidRange(nris.get(0)).start);
- assertEquals(TEST_PACKAGE_UID, getNriFirstUidRange(nris.get(0)).stop);
- assertEquals(testPackageNameUid2, getNriFirstUidRange(nris.get(1)).start);
- assertEquals(testPackageNameUid2, getNriFirstUidRange(nris.get(1)).stop);
+ nris.sort(Comparator.comparingInt(nri -> getNriFirstUidRange(nri).getLower()));
+ assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getLower());
+ assertEquals(TEST_PACKAGE_UID, (int) getNriFirstUidRange(nris.get(0)).getUpper());
+ assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getLower());
+ assertEquals(testPackageNameUid2, (int) getNriFirstUidRange(nris.get(1)).getUpper());
}
@Test
@@ -9937,17 +9991,17 @@
// UIDs for all users and all managed packages should be present.
// Two users each with two packages.
final int expectedUidSize = 2;
- final List<UidRange> uids =
+ final List<Range<Integer>> uids =
new ArrayList<>(nris.get(0).mRequests.get(0).networkCapabilities.getUids());
assertEquals(expectedUidSize, uids.size());
// Sort by uid to access nris by index
- uids.sort(Comparator.comparingInt(uid -> uid.start));
+ uids.sort(Comparator.comparingInt(uid -> uid.getLower()));
final int secondUserTestPackageUid = UserHandle.getUid(secondUser, TEST_PACKAGE_UID);
- assertEquals(TEST_PACKAGE_UID, uids.get(0).start);
- assertEquals(TEST_PACKAGE_UID, uids.get(0).stop);
- assertEquals(secondUserTestPackageUid, uids.get(1).start);
- assertEquals(secondUserTestPackageUid, uids.get(1).stop);
+ assertEquals(TEST_PACKAGE_UID, (int) uids.get(0).getLower());
+ assertEquals(TEST_PACKAGE_UID, (int) uids.get(0).getUpper());
+ assertEquals(secondUserTestPackageUid, (int) uids.get(1).getLower());
+ assertEquals(secondUserTestPackageUid, (int) uids.get(1).getUpper());
}
@Test
@@ -10114,9 +10168,12 @@
Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
mSystemDefaultNetworkCallback = new TestNetworkCallback();
mDefaultNetworkCallback = new TestNetworkCallback();
+ mProfileDefaultNetworkCallback = new TestNetworkCallback();
mCm.registerSystemDefaultNetworkCallback(mSystemDefaultNetworkCallback,
new Handler(ConnectivityThread.getInstanceLooper()));
mCm.registerDefaultNetworkCallback(mDefaultNetworkCallback);
+ registerDefaultNetworkCallbackAsUid(mProfileDefaultNetworkCallback,
+ TEST_WORK_PROFILE_APP_UID);
mServiceContext.setPermission(
Manifest.permission.NETWORK_SETTINGS, PERMISSION_DENIED);
}
@@ -10128,6 +10185,9 @@
if (null != mSystemDefaultNetworkCallback) {
mCm.unregisterNetworkCallback(mSystemDefaultNetworkCallback);
}
+ if (null != mProfileDefaultNetworkCallback) {
+ mCm.unregisterNetworkCallback(mProfileDefaultNetworkCallback);
+ }
}
private void setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(
@@ -10183,7 +10243,7 @@
oemPrefListener.expectOnComplete();
}
- private static class TestOemListenerCallback implements IOnSetOemNetworkPreferenceListener {
+ private static class TestOemListenerCallback implements IOnCompleteListener {
final CompletableFuture<Object> mDone = new CompletableFuture<>();
@Override
@@ -11121,11 +11181,494 @@
mCm.unregisterNetworkCallback(cellCb);
}
+ // Cannot be part of MockNetworkFactory since it requires method of the test.
+ private void expectNoRequestChanged(@NonNull MockNetworkFactory factory) {
+ waitForIdle();
+ factory.assertNoRequestChanged();
+ }
+
@Test
- public void testRegisterBestMatchingNetworkCallback() throws Exception {
- final NetworkRequest request = new NetworkRequest.Builder().build();
- assertThrows(UnsupportedOperationException.class,
- () -> mCm.registerBestMatchingNetworkCallback(request, new NetworkCallback(),
- mCsHandlerThread.getThreadHandler()));
+ public void testRegisterBestMatchingNetworkCallback_noIssueToFactory() throws Exception {
+ // Prepare mock mms factory.
+ final HandlerThread handlerThread = new HandlerThread("MockCellularFactory");
+ handlerThread.start();
+ NetworkCapabilities filter = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_CELLULAR)
+ .addCapability(NET_CAPABILITY_MMS);
+ final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
+ mServiceContext, "testFactory", filter, mCsHandlerThread);
+ testFactory.setScoreFilter(40);
+
+ try {
+ // Register the factory and expect it will see default request, because all requests
+ // are sent to all factories.
+ testFactory.register();
+ testFactory.expectRequestAdd();
+ testFactory.assertRequestCountEquals(1);
+ // The factory won't try to start the network since the default request doesn't
+ // match the filter (no INTERNET capability).
+ assertFalse(testFactory.getMyStartRequested());
+
+ // Register callback for listening best matching network. Verify that the request won't
+ // be sent to factory.
+ final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
+ mCm.registerBestMatchingNetworkCallback(
+ new NetworkRequest.Builder().addCapability(NET_CAPABILITY_MMS).build(),
+ bestMatchingCb, mCsHandlerThread.getThreadHandler());
+ bestMatchingCb.assertNoCallback();
+ expectNoRequestChanged(testFactory);
+ testFactory.assertRequestCountEquals(1);
+ assertFalse(testFactory.getMyStartRequested());
+
+ // Fire a normal mms request, verify the factory will only see the request.
+ final TestNetworkCallback mmsNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest mmsRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_MMS).build();
+ mCm.requestNetwork(mmsRequest, mmsNetworkCallback);
+ testFactory.expectRequestAdd();
+ testFactory.assertRequestCountEquals(2);
+ assertTrue(testFactory.getMyStartRequested());
+
+ // Unregister best matching callback, verify factory see no change.
+ mCm.unregisterNetworkCallback(bestMatchingCb);
+ expectNoRequestChanged(testFactory);
+ testFactory.assertRequestCountEquals(2);
+ assertTrue(testFactory.getMyStartRequested());
+ } finally {
+ testFactory.terminate();
+ }
+ }
+
+ @Test
+ public void testRegisterBestMatchingNetworkCallback_trackBestNetwork() throws Exception {
+ final TestNetworkCallback bestMatchingCb = new TestNetworkCallback();
+ mCm.registerBestMatchingNetworkCallback(
+ new NetworkRequest.Builder().addCapability(NET_CAPABILITY_TRUSTED).build(),
+ bestMatchingCb, mCsHandlerThread.getThreadHandler());
+
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ bestMatchingCb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(true);
+ bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+
+ // Change something on cellular to trigger capabilities changed, since the callback
+ // only cares about the best network, verify it received nothing from cellular.
+ mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
+ bestMatchingCb.assertNoCallback();
+
+ // Make cellular the best network again, verify the callback now tracks cellular.
+ mWiFiNetworkAgent.adjustScore(-50);
+ bestMatchingCb.expectAvailableCallbacksValidated(mCellNetworkAgent);
+
+ // Make cellular temporary non-trusted, which will not satisfying the request.
+ // Verify the callback switch from/to the other network accordingly.
+ mCellNetworkAgent.removeCapability(NET_CAPABILITY_TRUSTED);
+ bestMatchingCb.expectAvailableCallbacksValidated(mWiFiNetworkAgent);
+ mCellNetworkAgent.addCapability(NET_CAPABILITY_TRUSTED);
+ bestMatchingCb.expectAvailableDoubleValidatedCallbacks(mCellNetworkAgent);
+
+ // Verify the callback doesn't care about wifi disconnect.
+ mWiFiNetworkAgent.disconnect();
+ bestMatchingCb.assertNoCallback();
+ mCellNetworkAgent.disconnect();
+ bestMatchingCb.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+ }
+
+ private UidRangeParcel[] uidRangeFor(final UserHandle handle) {
+ UidRange range = UidRange.createForUser(handle);
+ return new UidRangeParcel[] { new UidRangeParcel(range.start, range.stop) };
+ }
+
+ private static class TestOnCompleteListener implements Runnable {
+ final class OnComplete {}
+ final ArrayTrackRecord<OnComplete>.ReadHead mHistory =
+ new ArrayTrackRecord<OnComplete>().newReadHead();
+
+ @Override
+ public void run() {
+ mHistory.add(new OnComplete());
+ }
+
+ public void expectOnComplete() {
+ assertNotNull(mHistory.poll(TIMEOUT_MS, it -> true));
+ }
+ }
+
+ private TestNetworkAgentWrapper makeEnterpriseNetworkAgent() throws Exception {
+ final NetworkCapabilities workNc = new NetworkCapabilities();
+ workNc.addCapability(NET_CAPABILITY_ENTERPRISE);
+ workNc.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+ return new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, new LinkProperties(), workNc);
+ }
+
+ private TestNetworkCallback mEnterpriseCallback;
+ private UserHandle setupEnterpriseNetwork() {
+ final UserHandle userHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
+ mServiceContext.setWorkProfile(userHandle, true);
+
+ // File a request to avoid the enterprise network being disconnected as soon as the default
+ // request goes away – it would make impossible to test that networkRemoveUidRanges
+ // is called, as the network would disconnect first for lack of a request.
+ mEnterpriseCallback = new TestNetworkCallback();
+ final NetworkRequest keepUpRequest = new NetworkRequest.Builder()
+ .addCapability(NET_CAPABILITY_ENTERPRISE)
+ .build();
+ mCm.requestNetwork(keepUpRequest, mEnterpriseCallback);
+ return userHandle;
+ }
+
+ private void maybeTearDownEnterpriseNetwork() {
+ if (null != mEnterpriseCallback) {
+ mCm.unregisterNetworkCallback(mEnterpriseCallback);
+ }
+ }
+
+ /**
+ * Make sure per-profile networking preference behaves as expected when the enterprise network
+ * goes up and down while the preference is active. Make sure they behave as expected whether
+ * there is a general default network or not.
+ */
+ @Test
+ public void testPreferenceForUserNetworkUpDown() throws Exception {
+ final InOrder inOrder = inOrder(mMockNetd);
+ final UserHandle testHandle = setupEnterpriseNetwork();
+ registerDefaultNetworkCallbacks();
+
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+
+ mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId,
+ INetd.PERMISSION_NONE);
+
+ final TestOnCompleteListener listener = new TestOnCompleteListener();
+ mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
+ r -> r.run(), listener);
+ listener.expectOnComplete();
+
+ // Setting a network preference for this user will create a new set of routing rules for
+ // the UID range that corresponds to this user, so as to define the default network
+ // for these apps separately. This is true because the multi-layer request relevant to
+ // this UID range contains a TRACK_DEFAULT, so the range will be moved through UID-specific
+ // rules to the correct network – in this case the system default network. The case where
+ // the default network for the profile happens to be the same as the system default
+ // is not handled specially, the rules are always active as long as a preference is set.
+ inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId,
+ uidRangeFor(testHandle));
+
+ // The enterprise network is not ready yet.
+ assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
+ mProfileDefaultNetworkCallback);
+
+ final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
+ workAgent.connect(false);
+
+ mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent);
+ mSystemDefaultNetworkCallback.assertNoCallback();
+ mDefaultNetworkCallback.assertNoCallback();
+ inOrder.verify(mMockNetd).networkCreatePhysical(workAgent.getNetwork().netId,
+ INetd.PERMISSION_SYSTEM);
+ inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId,
+ uidRangeFor(testHandle));
+ inOrder.verify(mMockNetd).networkRemoveUidRanges(mCellNetworkAgent.getNetwork().netId,
+ uidRangeFor(testHandle));
+
+ // Make sure changes to the work agent send callbacks to the app in the work profile, but
+ // not to the other apps.
+ workAgent.setNetworkValid(true /* isStrictMode */);
+ workAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
+ mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent,
+ nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED)
+ && nc.hasCapability(NET_CAPABILITY_ENTERPRISE));
+ assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
+
+ workAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
+ mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent, nc ->
+ nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+ assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
+
+ // Conversely, change a capability on the system-wide default network and make sure
+ // that only the apps outside of the work profile receive the callbacks.
+ mCellNetworkAgent.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED);
+ mSystemDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
+ nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+ mDefaultNetworkCallback.expectCapabilitiesThat(mCellNetworkAgent, nc ->
+ nc.hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED));
+ mProfileDefaultNetworkCallback.assertNoCallback();
+
+ // Disconnect and reconnect the system-wide default network and make sure that the
+ // apps on this network see the appropriate callbacks, and the app on the work profile
+ // doesn't because it continues to use the enterprise network.
+ mCellNetworkAgent.disconnect();
+ mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+ mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+ mProfileDefaultNetworkCallback.assertNoCallback();
+ inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId);
+
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ mProfileDefaultNetworkCallback.assertNoCallback();
+ inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId,
+ INetd.PERMISSION_NONE);
+
+ // When the agent disconnects, test that the app on the work profile falls back to the
+ // default network.
+ workAgent.disconnect();
+ mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent);
+ mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+ assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
+ inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId,
+ uidRangeFor(testHandle));
+ inOrder.verify(mMockNetd).networkDestroy(workAgent.getNetwork().netId);
+
+ mCellNetworkAgent.disconnect();
+ mSystemDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+ mDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+ mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+
+ // Waiting for the handler to be idle before checking for networkDestroy is necessary
+ // here because ConnectivityService calls onLost before the network is fully torn down.
+ waitForIdle();
+ inOrder.verify(mMockNetd).networkDestroy(mCellNetworkAgent.getNetwork().netId);
+
+ // If the control comes here, callbacks seem to behave correctly in the presence of
+ // a default network when the enterprise network goes up and down. Now, make sure they
+ // also behave correctly in the absence of a system-wide default network.
+ final TestNetworkAgentWrapper workAgent2 = makeEnterpriseNetworkAgent();
+ workAgent2.connect(false);
+
+ mProfileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent2);
+ assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
+ inOrder.verify(mMockNetd).networkCreatePhysical(workAgent2.getNetwork().netId,
+ INetd.PERMISSION_SYSTEM);
+ inOrder.verify(mMockNetd).networkAddUidRanges(workAgent2.getNetwork().netId,
+ uidRangeFor(testHandle));
+
+ workAgent2.setNetworkValid(true /* isStrictMode */);
+ workAgent2.mNetworkMonitor.forceReevaluation(Process.myUid());
+ mProfileDefaultNetworkCallback.expectCapabilitiesThat(workAgent2,
+ nc -> nc.hasCapability(NET_CAPABILITY_ENTERPRISE)
+ && !nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+ assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
+ inOrder.verify(mMockNetd, never()).networkAddUidRanges(anyInt(), any());
+
+ // When the agent disconnects, test that the app on the work profile falls back to the
+ // default network.
+ workAgent2.disconnect();
+ mProfileDefaultNetworkCallback.expectCallback(CallbackEntry.LOST, workAgent2);
+ assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
+ inOrder.verify(mMockNetd).networkDestroy(workAgent2.getNetwork().netId);
+
+ assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
+ mProfileDefaultNetworkCallback);
+
+ // Callbacks will be unregistered by tearDown()
+ }
+
+ /**
+ * Test that, in a given networking context, calling setPreferenceForUser to set per-profile
+ * defaults on then off works as expected.
+ */
+ @Test
+ public void testSetPreferenceForUserOnOff() throws Exception {
+ final InOrder inOrder = inOrder(mMockNetd);
+ final UserHandle testHandle = setupEnterpriseNetwork();
+
+ // Connect both a regular cell agent and an enterprise network first.
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+
+ final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
+ workAgent.connect(true);
+
+ final TestOnCompleteListener listener = new TestOnCompleteListener();
+ mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
+ r -> r.run(), listener);
+ listener.expectOnComplete();
+ inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId,
+ INetd.PERMISSION_NONE);
+ inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId,
+ uidRangeFor(testHandle));
+
+ registerDefaultNetworkCallbacks();
+
+ mSystemDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+ mDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+ mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
+
+ mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_DEFAULT,
+ r -> r.run(), listener);
+ listener.expectOnComplete();
+
+ mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+ assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback);
+ inOrder.verify(mMockNetd).networkRemoveUidRanges(workAgent.getNetwork().netId,
+ uidRangeFor(testHandle));
+
+ workAgent.disconnect();
+ mCellNetworkAgent.disconnect();
+
+ // Callbacks will be unregistered by tearDown()
+ }
+
+ /**
+ * Test per-profile default networks for two different profiles concurrently.
+ */
+ @Test
+ public void testSetPreferenceForTwoProfiles() throws Exception {
+ final InOrder inOrder = inOrder(mMockNetd);
+ final UserHandle testHandle2 = setupEnterpriseNetwork();
+ final UserHandle testHandle4 = UserHandle.of(TEST_WORK_PROFILE_USER_ID + 2);
+ mServiceContext.setWorkProfile(testHandle4, true);
+ registerDefaultNetworkCallbacks();
+
+ final TestNetworkCallback app4Cb = new TestNetworkCallback();
+ final int testWorkProfileAppUid4 =
+ UserHandle.getUid(testHandle4.getIdentifier(), TEST_APP_ID);
+ registerDefaultNetworkCallbackAsUid(app4Cb, testWorkProfileAppUid4);
+
+ // Connect both a regular cell agent and an enterprise network first.
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+
+ final TestNetworkAgentWrapper workAgent = makeEnterpriseNetworkAgent();
+ workAgent.connect(true);
+
+ mSystemDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ mProfileDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ app4Cb.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+ inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId,
+ INetd.PERMISSION_NONE);
+ inOrder.verify(mMockNetd).networkCreatePhysical(workAgent.getNetwork().netId,
+ INetd.PERMISSION_SYSTEM);
+
+ final TestOnCompleteListener listener = new TestOnCompleteListener();
+ mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
+ r -> r.run(), listener);
+ listener.expectOnComplete();
+ inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId,
+ uidRangeFor(testHandle2));
+
+ mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(workAgent);
+ assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
+ app4Cb);
+
+ mCm.setProfileNetworkPreference(testHandle4, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
+ r -> r.run(), listener);
+ listener.expectOnComplete();
+ inOrder.verify(mMockNetd).networkAddUidRanges(workAgent.getNetwork().netId,
+ uidRangeFor(testHandle4));
+
+ app4Cb.expectAvailableCallbacksValidated(workAgent);
+ assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
+ mProfileDefaultNetworkCallback);
+
+ mCm.setProfileNetworkPreference(testHandle2, PROFILE_NETWORK_PREFERENCE_DEFAULT,
+ r -> r.run(), listener);
+ listener.expectOnComplete();
+ inOrder.verify(mMockNetd).networkRemoveUidRanges(workAgent.getNetwork().netId,
+ uidRangeFor(testHandle2));
+
+ mProfileDefaultNetworkCallback.expectAvailableCallbacksValidated(mCellNetworkAgent);
+ assertNoCallbacks(mSystemDefaultNetworkCallback, mDefaultNetworkCallback,
+ app4Cb);
+
+ workAgent.disconnect();
+ mCellNetworkAgent.disconnect();
+
+ mCm.unregisterNetworkCallback(app4Cb);
+ // Other callbacks will be unregistered by tearDown()
+ }
+
+ @Test
+ public void testProfilePreferenceRemovedUponUserRemoved() throws Exception {
+ final InOrder inOrder = inOrder(mMockNetd);
+ final UserHandle testHandle = setupEnterpriseNetwork();
+
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+
+ final TestOnCompleteListener listener = new TestOnCompleteListener();
+ mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
+ r -> r.run(), listener);
+ listener.expectOnComplete();
+ inOrder.verify(mMockNetd).networkCreatePhysical(mCellNetworkAgent.getNetwork().netId,
+ INetd.PERMISSION_NONE);
+ inOrder.verify(mMockNetd).networkAddUidRanges(mCellNetworkAgent.getNetwork().netId,
+ uidRangeFor(testHandle));
+
+ final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
+ removedIntent.putExtra(Intent.EXTRA_USER, testHandle);
+ processBroadcast(removedIntent);
+
+ inOrder.verify(mMockNetd).networkRemoveUidRanges(mCellNetworkAgent.getNetwork().netId,
+ uidRangeFor(testHandle));
+ }
+
+ /**
+ * Make sure that OEM preference and per-profile preference can't be used at the same
+ * time and throw ISE if tried
+ */
+ @Test
+ public void testOemPreferenceAndProfilePreferenceExclusive() throws Exception {
+ final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
+ mServiceContext.setWorkProfile(testHandle, true);
+ final TestOnCompleteListener listener = new TestOnCompleteListener();
+
+ setupMultipleDefaultNetworksForOemNetworkPreferenceNotCurrentUidTest(
+ OEM_NETWORK_PREFERENCE_OEM_PAID_ONLY);
+ assertThrows("Should not be able to set per-profile pref while OEM prefs present",
+ IllegalStateException.class, () ->
+ mCm.setProfileNetworkPreference(testHandle,
+ PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
+ r -> r.run(), listener));
+
+ // Empty the OEM prefs
+ final TestOemListenerCallback oemPrefListener = new TestOemListenerCallback();
+ final OemNetworkPreferences emptyOemPref = new OemNetworkPreferences.Builder().build();
+ mService.setOemNetworkPreference(emptyOemPref, oemPrefListener);
+ oemPrefListener.expectOnComplete();
+
+ mCm.setProfileNetworkPreference(testHandle, PROFILE_NETWORK_PREFERENCE_ENTERPRISE,
+ r -> r.run(), listener);
+ listener.expectOnComplete();
+ assertThrows("Should not be able to set OEM prefs while per-profile pref is on",
+ IllegalStateException.class , () ->
+ mService.setOemNetworkPreference(emptyOemPref, oemPrefListener));
+ }
+
+ /**
+ * Make sure wrong preferences for per-profile default networking are rejected.
+ */
+ @Test
+ public void testProfileNetworkPrefWrongPreference() throws Exception {
+ final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
+ mServiceContext.setWorkProfile(testHandle, true);
+ assertThrows("Should not be able to set an illegal preference",
+ IllegalArgumentException.class,
+ () -> mCm.setProfileNetworkPreference(testHandle,
+ PROFILE_NETWORK_PREFERENCE_ENTERPRISE + 1, null, null));
+ }
+
+ /**
+ * Make sure requests for per-profile default networking for a non-work profile are
+ * rejected
+ */
+ @Test
+ public void testProfileNetworkPrefWrongProfile() throws Exception {
+ final UserHandle testHandle = UserHandle.of(TEST_WORK_PROFILE_USER_ID);
+ mServiceContext.setWorkProfile(testHandle, false);
+ assertThrows("Should not be able to set a user pref for a non-work profile",
+ IllegalArgumentException.class , () ->
+ mCm.setProfileNetworkPreference(testHandle,
+ PROFILE_NETWORK_PREFERENCE_ENTERPRISE, null, null));
}
}
diff --git a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
index a10a3c8..5ec1119 100644
--- a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
+++ b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
@@ -21,13 +21,29 @@
package com.android.server
+import android.content.Context
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.FEATURE_WIFI
+import android.content.pm.PackageManager.FEATURE_WIFI_DIRECT
import android.net.ConnectivityManager.TYPE_ETHERNET
import android.net.ConnectivityManager.TYPE_MOBILE
+import android.net.ConnectivityManager.TYPE_MOBILE_CBS
+import android.net.ConnectivityManager.TYPE_MOBILE_DUN
+import android.net.ConnectivityManager.TYPE_MOBILE_EMERGENCY
+import android.net.ConnectivityManager.TYPE_MOBILE_FOTA
+import android.net.ConnectivityManager.TYPE_MOBILE_HIPRI
+import android.net.ConnectivityManager.TYPE_MOBILE_IA
+import android.net.ConnectivityManager.TYPE_MOBILE_IMS
+import android.net.ConnectivityManager.TYPE_MOBILE_MMS
import android.net.ConnectivityManager.TYPE_MOBILE_SUPL
+import android.net.ConnectivityManager.TYPE_VPN
import android.net.ConnectivityManager.TYPE_WIFI
+import android.net.ConnectivityManager.TYPE_WIFI_P2P
import android.net.ConnectivityManager.TYPE_WIMAX
+import android.net.EthernetManager
import android.net.NetworkInfo.DetailedState.CONNECTED
import android.net.NetworkInfo.DetailedState.DISCONNECTED
+import android.telephony.TelephonyManager
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.server.ConnectivityService.LegacyTypeTracker
@@ -36,7 +52,6 @@
import org.junit.Assert.assertNull
import org.junit.Assert.assertSame
import org.junit.Assert.assertTrue
-import org.junit.Assert.fail
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
@@ -52,88 +67,130 @@
@RunWith(AndroidJUnit4::class)
@SmallTest
class LegacyTypeTrackerTest {
- private val supportedTypes = arrayOf(TYPE_MOBILE, TYPE_WIFI, TYPE_ETHERNET, TYPE_MOBILE_SUPL)
+ private val supportedTypes = arrayOf(TYPE_WIFI, TYPE_WIFI_P2P, TYPE_ETHERNET, TYPE_MOBILE,
+ TYPE_MOBILE_SUPL, TYPE_MOBILE_MMS, TYPE_MOBILE_SUPL, TYPE_MOBILE_DUN, TYPE_MOBILE_HIPRI,
+ TYPE_MOBILE_FOTA, TYPE_MOBILE_IMS, TYPE_MOBILE_CBS, TYPE_MOBILE_IA,
+ TYPE_MOBILE_EMERGENCY, TYPE_VPN)
private val mMockService = mock(ConnectivityService::class.java).apply {
doReturn(false).`when`(this).isDefaultNetwork(any())
}
- private val mTracker = LegacyTypeTracker(mMockService).apply {
- supportedTypes.forEach {
- addSupportedType(it)
- }
+ private val mPm = mock(PackageManager::class.java)
+ private val mContext = mock(Context::class.java).apply {
+ doReturn(true).`when`(mPm).hasSystemFeature(FEATURE_WIFI)
+ doReturn(true).`when`(mPm).hasSystemFeature(FEATURE_WIFI_DIRECT)
+ doReturn(mPm).`when`(this).packageManager
+ doReturn(mock(EthernetManager::class.java)).`when`(this).getSystemService(
+ Context.ETHERNET_SERVICE)
+ }
+ private val mTm = mock(TelephonyManager::class.java).apply {
+ doReturn(true).`when`(this).isDataCapable
+ }
+
+ private fun makeTracker() = LegacyTypeTracker(mMockService).apply {
+ loadSupportedTypes(mContext, mTm)
}
@Test
fun testSupportedTypes() {
- try {
- mTracker.addSupportedType(supportedTypes[0])
- fail("Expected IllegalStateException")
- } catch (expected: IllegalStateException) {}
+ val tracker = makeTracker()
supportedTypes.forEach {
- assertTrue(mTracker.isTypeSupported(it))
+ assertTrue(tracker.isTypeSupported(it))
}
- assertFalse(mTracker.isTypeSupported(UNSUPPORTED_TYPE))
+ assertFalse(tracker.isTypeSupported(UNSUPPORTED_TYPE))
+ }
+
+ @Test
+ fun testSupportedTypes_NoEthernet() {
+ doReturn(null).`when`(mContext).getSystemService(Context.ETHERNET_SERVICE)
+ assertFalse(makeTracker().isTypeSupported(TYPE_ETHERNET))
+ }
+
+ @Test
+ fun testSupportedTypes_NoTelephony() {
+ doReturn(false).`when`(mTm).isDataCapable
+ val tracker = makeTracker()
+ val nonMobileTypes = arrayOf(TYPE_WIFI, TYPE_WIFI_P2P, TYPE_ETHERNET, TYPE_VPN)
+ nonMobileTypes.forEach {
+ assertTrue(tracker.isTypeSupported(it))
+ }
+ supportedTypes.toSet().minus(nonMobileTypes).forEach {
+ assertFalse(tracker.isTypeSupported(it))
+ }
+ }
+
+ @Test
+ fun testSupportedTypes_NoWifiDirect() {
+ doReturn(false).`when`(mPm).hasSystemFeature(FEATURE_WIFI_DIRECT)
+ val tracker = makeTracker()
+ assertFalse(tracker.isTypeSupported(TYPE_WIFI_P2P))
+ supportedTypes.toSet().minus(TYPE_WIFI_P2P).forEach {
+ assertTrue(tracker.isTypeSupported(it))
+ }
}
@Test
fun testSupl() {
+ val tracker = makeTracker()
val mobileNai = mock(NetworkAgentInfo::class.java)
- mTracker.add(TYPE_MOBILE, mobileNai)
+ tracker.add(TYPE_MOBILE, mobileNai)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE)
reset(mMockService)
- mTracker.add(TYPE_MOBILE_SUPL, mobileNai)
+ tracker.add(TYPE_MOBILE_SUPL, mobileNai)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL)
reset(mMockService)
- mTracker.remove(TYPE_MOBILE_SUPL, mobileNai, false /* wasDefault */)
+ tracker.remove(TYPE_MOBILE_SUPL, mobileNai, false /* wasDefault */)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL)
reset(mMockService)
- mTracker.add(TYPE_MOBILE_SUPL, mobileNai)
+ tracker.add(TYPE_MOBILE_SUPL, mobileNai)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, CONNECTED, TYPE_MOBILE_SUPL)
reset(mMockService)
- mTracker.remove(mobileNai, false)
+ tracker.remove(mobileNai, false)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE_SUPL)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai, DISCONNECTED, TYPE_MOBILE)
}
@Test
fun testAddNetwork() {
+ val tracker = makeTracker()
val mobileNai = mock(NetworkAgentInfo::class.java)
val wifiNai = mock(NetworkAgentInfo::class.java)
- mTracker.add(TYPE_MOBILE, mobileNai)
- mTracker.add(TYPE_WIFI, wifiNai)
- assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai)
- assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai)
+ tracker.add(TYPE_MOBILE, mobileNai)
+ tracker.add(TYPE_WIFI, wifiNai)
+ assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai)
+ assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai)
// Make sure adding a second NAI does not change the results.
val secondMobileNai = mock(NetworkAgentInfo::class.java)
- mTracker.add(TYPE_MOBILE, secondMobileNai)
- assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai)
- assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai)
+ tracker.add(TYPE_MOBILE, secondMobileNai)
+ assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai)
+ assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai)
// Make sure removing a network that wasn't added for this type is a no-op.
- mTracker.remove(TYPE_MOBILE, wifiNai, false /* wasDefault */)
- assertSame(mTracker.getNetworkForType(TYPE_MOBILE), mobileNai)
- assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai)
+ tracker.remove(TYPE_MOBILE, wifiNai, false /* wasDefault */)
+ assertSame(tracker.getNetworkForType(TYPE_MOBILE), mobileNai)
+ assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai)
// Remove the top network for mobile and make sure the second one becomes the network
// of record for this type.
- mTracker.remove(TYPE_MOBILE, mobileNai, false /* wasDefault */)
- assertSame(mTracker.getNetworkForType(TYPE_MOBILE), secondMobileNai)
- assertSame(mTracker.getNetworkForType(TYPE_WIFI), wifiNai)
+ tracker.remove(TYPE_MOBILE, mobileNai, false /* wasDefault */)
+ assertSame(tracker.getNetworkForType(TYPE_MOBILE), secondMobileNai)
+ assertSame(tracker.getNetworkForType(TYPE_WIFI), wifiNai)
// Make sure adding a network for an unsupported type does not register it.
- mTracker.add(UNSUPPORTED_TYPE, mobileNai)
- assertNull(mTracker.getNetworkForType(UNSUPPORTED_TYPE))
+ tracker.add(UNSUPPORTED_TYPE, mobileNai)
+ assertNull(tracker.getNetworkForType(UNSUPPORTED_TYPE))
}
@Test
fun testBroadcastOnDisconnect() {
+ val tracker = makeTracker()
val mobileNai1 = mock(NetworkAgentInfo::class.java)
val mobileNai2 = mock(NetworkAgentInfo::class.java)
doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai1)
- mTracker.add(TYPE_MOBILE, mobileNai1)
+ tracker.add(TYPE_MOBILE, mobileNai1)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, CONNECTED, TYPE_MOBILE)
reset(mMockService)
doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai2)
- mTracker.add(TYPE_MOBILE, mobileNai2)
+ tracker.add(TYPE_MOBILE, mobileNai2)
verify(mMockService, never()).sendLegacyNetworkBroadcast(any(), any(), anyInt())
- mTracker.remove(TYPE_MOBILE, mobileNai1, false /* wasDefault */)
+ tracker.remove(TYPE_MOBILE, mobileNai1, false /* wasDefault */)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, DISCONNECTED, TYPE_MOBILE)
verify(mMockService).sendLegacyNetworkBroadcast(mobileNai2, CONNECTED, TYPE_MOBILE)
}
diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
index 5760211..692c50f 100644
--- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java
@@ -18,15 +18,15 @@
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF;
import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_DEFAULT_MODE;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE;
+import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_SPECIFIER;
import static android.net.NetworkCapabilities.MAX_TRANSPORT;
import static android.net.NetworkCapabilities.MIN_TRANSPORT;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_FAILURE;
import static android.net.resolv.aidl.IDnsResolverUnsolicitedEventListener.VALIDATION_RESULT_SUCCESS;
-import static android.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE;
-import static android.provider.Settings.Global.PRIVATE_DNS_MODE;
-import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import static com.android.testutils.MiscAsserts.assertContainsExactly;
import static com.android.testutils.MiscAsserts.assertContainsStringsExactly;
@@ -312,14 +312,14 @@
@Test
public void testOverrideDefaultMode() throws Exception {
// Hard-coded default is opportunistic mode.
- final PrivateDnsConfig cfgAuto = DnsManager.getPrivateDnsConfig(mContentResolver);
+ final PrivateDnsConfig cfgAuto = DnsManager.getPrivateDnsConfig(mCtx);
assertTrue(cfgAuto.useTls);
assertEquals("", cfgAuto.hostname);
assertEquals(new InetAddress[0], cfgAuto.ips);
// Pretend a gservices push sets the default to "off".
Settings.Global.putString(mContentResolver, PRIVATE_DNS_DEFAULT_MODE, "off");
- final PrivateDnsConfig cfgOff = DnsManager.getPrivateDnsConfig(mContentResolver);
+ final PrivateDnsConfig cfgOff = DnsManager.getPrivateDnsConfig(mCtx);
assertFalse(cfgOff.useTls);
assertEquals("", cfgOff.hostname);
assertEquals(new InetAddress[0], cfgOff.ips);
@@ -328,7 +328,7 @@
Settings.Global.putString(
mContentResolver, PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
Settings.Global.putString(mContentResolver, PRIVATE_DNS_SPECIFIER, "strictmode.com");
- final PrivateDnsConfig cfgStrict = DnsManager.getPrivateDnsConfig(mContentResolver);
+ final PrivateDnsConfig cfgStrict = DnsManager.getPrivateDnsConfig(mCtx);
assertTrue(cfgStrict.useTls);
assertEquals("strictmode.com", cfgStrict.hostname);
assertEquals(new InetAddress[0], cfgStrict.ips);
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 11fcea6..6ad4900 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -23,6 +23,7 @@
import static android.net.ConnectivityManager.NetworkCallback;
import static android.net.INetd.IF_STATE_DOWN;
import static android.net.INetd.IF_STATE_UP;
+import static android.os.UserHandle.PER_USER_RANGE;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -74,7 +75,6 @@
import android.net.NetworkCapabilities;
import android.net.NetworkInfo.DetailedState;
import android.net.RouteInfo;
-import android.net.UidRange;
import android.net.UidRangeParcel;
import android.net.VpnManager;
import android.net.VpnService;
@@ -181,8 +181,7 @@
mPackages.put(PKGS[i], PKG_UIDS[i]);
}
}
- private static final UidRange PRI_USER_RANGE =
- UidRange.createForUser(UserHandle.of(primaryUser.id));
+ private static final Range<Integer> PRI_USER_RANGE = uidRangeForUser(primaryUser.id);
@Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext;
@Mock private UserManager mUserManager;
@@ -260,6 +259,21 @@
.thenReturn(tunnelResp);
}
+ private Set<Range<Integer>> rangeSet(Range<Integer> ... ranges) {
+ final Set<Range<Integer>> range = new ArraySet<>();
+ for (Range<Integer> r : ranges) range.add(r);
+
+ return range;
+ }
+
+ private static Range<Integer> uidRangeForUser(int userId) {
+ return new Range<Integer>(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1);
+ }
+
+ private Range<Integer> uidRange(int start, int stop) {
+ return new Range<Integer>(start, stop);
+ }
+
@Test
public void testRestrictedProfilesAreAddedToVpn() {
setMockedUsers(primaryUser, secondaryUser, restrictedProfileA, restrictedProfileB);
@@ -268,12 +282,10 @@
// Assume the user can have restricted profiles.
doReturn(true).when(mUserManager).canHaveRestrictedProfile();
- final Set<UidRange> ranges =
+ final Set<Range<Integer>> ranges =
vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null);
- assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
- PRI_USER_RANGE, UidRange.createForUser(UserHandle.of(restrictedProfileA.id))
- })), ranges);
+ assertEquals(rangeSet(PRI_USER_RANGE, uidRangeForUser(restrictedProfileA.id)), ranges);
}
@Test
@@ -281,10 +293,10 @@
setMockedUsers(primaryUser, managedProfileA);
final Vpn vpn = createVpn(primaryUser.id);
- final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
+ final Set<Range<Integer>> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
null, null);
- assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges);
+ assertEquals(rangeSet(PRI_USER_RANGE), ranges);
}
@Test
@@ -292,35 +304,38 @@
setMockedUsers(primaryUser, restrictedProfileA, managedProfileA);
final Vpn vpn = createVpn(primaryUser.id);
- final Set<UidRange> ranges = new ArraySet<>();
+ final Set<Range<Integer>> ranges = new ArraySet<>();
vpn.addUserToRanges(ranges, primaryUser.id, null, null);
- assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges);
+ assertEquals(rangeSet(PRI_USER_RANGE), ranges);
}
@Test
public void testUidAllowAndDenylist() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
- final UidRange user = PRI_USER_RANGE;
+ final Range<Integer> user = PRI_USER_RANGE;
+ final int userStart = user.getLower();
+ final int userStop = user.getUpper();
final String[] packages = {PKGS[0], PKGS[1], PKGS[2]};
// Allowed list
- final Set<UidRange> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
- Arrays.asList(packages), null);
- assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
- new UidRange(user.start + PKG_UIDS[0], user.start + PKG_UIDS[0]),
- new UidRange(user.start + PKG_UIDS[1], user.start + PKG_UIDS[2])
- })), allow);
+ final Set<Range<Integer>> allow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
+ Arrays.asList(packages), null /* disallowedApplications */);
+ assertEquals(rangeSet(
+ uidRange(userStart + PKG_UIDS[0], userStart + PKG_UIDS[0]),
+ uidRange(userStart + PKG_UIDS[1], userStart + PKG_UIDS[2])),
+ allow);
// Denied list
- final Set<UidRange> disallow = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
- null, Arrays.asList(packages));
- assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] {
- new UidRange(user.start, user.start + PKG_UIDS[0] - 1),
- new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
- /* Empty range between UIDS[1] and UIDS[2], should be excluded, */
- new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
- })), disallow);
+ final Set<Range<Integer>> disallow =
+ vpn.createUserAndRestrictedProfilesRanges(primaryUser.id,
+ null /* allowedApplications */, Arrays.asList(packages));
+ assertEquals(rangeSet(
+ uidRange(userStart, userStart + PKG_UIDS[0] - 1),
+ uidRange(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1),
+ /* Empty range between UIDS[1] and UIDS[2], should be excluded, */
+ uidRange(userStart + PKG_UIDS[2] + 1, userStop)),
+ disallow);
}
@Test
@@ -350,84 +365,86 @@
@Test
public void testLockdownChangingPackage() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
- final UidRange user = PRI_USER_RANGE;
-
+ final Range<Integer> user = PRI_USER_RANGE;
+ final int userStart = user.getLower();
+ final int userStop = user.getUpper();
// Set always-on without lockdown.
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null));
// Set always-on with lockdown.
assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
+ new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop)
}));
// Switch to another app.
assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null));
verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
+ new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop)
}));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
+ new UidRangeParcel(userStart, userStart + PKG_UIDS[3] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop)
}));
}
@Test
public void testLockdownAllowlist() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
- final UidRange user = PRI_USER_RANGE;
-
+ final Range<Integer> user = PRI_USER_RANGE;
+ final int userStart = user.getLower();
+ final int userStop = user.getUpper();
// Set always-on with lockdown and allow app PKGS[2] from lockdown.
assertTrue(vpn.setAlwaysOnPackage(
PKGS[1], true, Collections.singletonList(PKGS[2])));
- verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
+ verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
+ new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop)
}));
// Change allowed app list to PKGS[3].
assertTrue(vpn.setAlwaysOnPackage(
PKGS[1], true, Collections.singletonList(PKGS[3])));
verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop)
}));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop)
}));
// Change the VPN app.
assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Collections.singletonList(PKGS[3])));
verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1)
+ new UidRangeParcel(userStart, userStart + PKG_UIDS[1] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStart + PKG_UIDS[3] - 1)
}));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start, user.start + PKG_UIDS[0] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1)
+ new UidRangeParcel(userStart, userStart + PKG_UIDS[0] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1)
}));
// Remove the list of allowed packages.
assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null));
verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[3] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[3] + 1, userStop)
}));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop),
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop),
}));
// Add the list of allowed packages.
assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Collections.singletonList(PKGS[1])));
verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStop)
}));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop)
}));
// Try allowing a package with a comma, should be rejected.
@@ -439,12 +456,12 @@
assertTrue(vpn.setAlwaysOnPackage(
PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app")));
verify(mConnectivityManager).setRequireVpnForUids(false, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[1] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[1] + 1, userStop)
}));
verify(mConnectivityManager).setRequireVpnForUids(true, toRanges(new UidRangeParcel[] {
- new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1),
- new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop)
+ new UidRangeParcel(userStart + PKG_UIDS[0] + 1, userStart + PKG_UIDS[2] - 1),
+ new UidRangeParcel(userStart + PKG_UIDS[2] + 1, userStop)
}));
}
@@ -452,7 +469,7 @@
public void testLockdownRuleRepeatability() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] {
- new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)};
+ new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper())};
// Given legacy lockdown is already enabled,
vpn.setLockdown(true);
verify(mConnectivityManager, times(1)).setRequireVpnForUids(true,
@@ -484,7 +501,7 @@
public void testLockdownRuleReversibility() throws Exception {
final Vpn vpn = createVpn(primaryUser.id);
final UidRangeParcel[] entireUser = {
- new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)
+ new UidRangeParcel(PRI_USER_RANGE.getLower(), PRI_USER_RANGE.getUpper())
};
final UidRangeParcel[] exceptPkg0 = {
new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1),