From 7a66717d89ef7438a05db6d78efa2658fe55a8dc Mon Sep 17 00:00:00 2001 From: Etan Cohen Date: Thu, 23 May 2019 09:16:26 -0700 Subject: [PATCH 001/229] [CM] Fix NPE due to unvalidated callback value Fix flaky test resulting from the above fix. Bug: 132950880 Fix: 133457081 Test: atest ConnectivityServiceTest Merged-In: Ia2cc04b42288ea987483e5ab0e0a10093dc49502 Change-Id: Ia2cc04b42288ea987483e5ab0e0a10093dc49502 (cherry picked from commit c8289e40a4c837e40fc402bada475f2319e179eb) --- tests/net/java/com/android/server/ConnectivityServiceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 03af9672c1..fa059fa9e8 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -3864,6 +3864,7 @@ public class ConnectivityServiceTest { } } + testFactory.expectRemoveRequests(1); if (preUnregister) { mCm.unregisterNetworkCallback(networkCallback); @@ -3873,7 +3874,6 @@ public class ConnectivityServiceTest { testFactory.triggerUnfulfillable(requests.get(newRequestId)); } else { // Simulate the factory releasing the request as unfulfillable and expect onUnavailable! - testFactory.expectRemoveRequests(1); testFactory.triggerUnfulfillable(requests.get(newRequestId)); networkCallback.expectCallback(CallbackState.UNAVAILABLE, null); From e7b9756d85cb8727814a059e861cfc5c831b00b7 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 4 Jun 2019 14:37:26 +0900 Subject: [PATCH 002/229] Allow passing in acceptUnvalidated without explicitlySelected This will allow wifi to tell ConnectivityService that partial connectivity is acceptable even if the network is not explicitly selected. This is needed when the user selects a partial connectivity network and tells the system to connect to the network, and never to ask again. In such cases, the system must switch to the network even if it is not explicitly selected. Bug: 130766237 Test: atest FrameworksNetTests Test: unit tests in an upcoming CL Change-Id: I13465090b7b1c0bf5dc83362387a5428d77b7e1d (cherry picked from commit e01696a4c499a9fa7087f20947fdb1581b9c0213) --- core/java/android/net/NetworkAgent.java | 19 ++++++++++++++++++- .../android/server/ConnectivityService.java | 10 +++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index c3483a3ddd..660cd848d1 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -433,7 +433,24 @@ public abstract class NetworkAgent extends Handler { * {@link #saveAcceptUnvalidated} to respect the user's choice. */ public void explicitlySelected(boolean acceptUnvalidated) { - queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED, acceptUnvalidated ? 1 : 0, 0); + explicitlySelected(true /* explicitlySelected */, acceptUnvalidated); + } + + /** + * Called by the bearer to indicate this network was manually selected by the user. + * This should be called before the NetworkInfo is marked CONNECTED so that this + * Network can be given special treatment at that time. If {@code acceptUnvalidated} is + * {@code true}, then the system will switch to this network. If it is {@code false} and the + * network cannot be validated, the system will ask the user whether to switch to this network. + * If the user confirms and selects "don't ask again", then the system will call + * {@link #saveAcceptUnvalidated} to persist the user's choice. Thus, if the transport ever + * calls this method with {@code acceptUnvalidated} set to {@code false}, it must also implement + * {@link #saveAcceptUnvalidated} to respect the user's choice. + */ + public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) { + queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED, + explicitlySelected ? 1 : 0, + acceptUnvalidated ? 1 : 0); } /** diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index a06795054e..843f9997a1 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2575,11 +2575,11 @@ public class ConnectivityService extends IConnectivityManager.Stub break; } case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: { - if (nai.everConnected && !nai.networkMisc.explicitlySelected) { - loge("ERROR: already-connected network explicitly selected."); + if (nai.everConnected) { + loge("ERROR: cannot call explicitlySelected on already-connected network"); } - nai.networkMisc.explicitlySelected = true; - nai.networkMisc.acceptUnvalidated = msg.arg1 == 1; + nai.networkMisc.explicitlySelected = (msg.arg1 == 1); + nai.networkMisc.acceptUnvalidated = (msg.arg1 == 1) && (msg.arg2 == 1); // Mark the network as temporarily accepting partial connectivity so that it // will be validated (and possibly become default) even if it only provides // partial internet access. Note that if user connects to partial connectivity @@ -2587,7 +2587,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // out of wifi coverage) and if the same wifi is available again, the device // will auto connect to this wifi even though the wifi has "no internet". // TODO: Evaluate using a separate setting in IpMemoryStore. - nai.networkMisc.acceptPartialConnectivity = msg.arg1 == 1; + nai.networkMisc.acceptPartialConnectivity = (msg.arg2 == 1); break; } case NetworkAgent.EVENT_SOCKET_KEEPALIVE: { From f269537490238f92d79b9b8707fb1190dbc39177 Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Mon, 29 Jul 2019 13:18:27 +0100 Subject: [PATCH 003/229] Add @UnsupportedAppUsage annotations for max-p. See go/UnsupportedAppUsage for more details. These have already been greylisted, however due to bugs/omissions in the tooling have been kept in go/greylist-txt instead of being annotated in the code. Exempted-From-Owner-Approval: Mechanical changes to the codebase which have been approved by Android API council and announced on android-eng@ Bug: 137350495 Test: m Change-Id: I5aa29a49b193db47aaee4d3a756c17f48cc9f0b1 --- core/java/android/net/IConnectivityManager.aidl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 61648dc7f1..5f662f9149 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -52,6 +52,7 @@ interface IConnectivityManager @UnsupportedAppUsage NetworkInfo getActiveNetworkInfo(); NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked); + @UnsupportedAppUsage(maxTargetSdk = 28) NetworkInfo getNetworkInfo(int networkType); NetworkInfo getNetworkInfoForUid(in Network network, int uid, boolean ignoreBlocked); @UnsupportedAppUsage @@ -112,6 +113,7 @@ interface IConnectivityManager int setUsbTethering(boolean enable, String callerPkg); + @UnsupportedAppUsage(maxTargetSdk = 28) void reportInetCondition(int networkType, int percentage); void reportNetworkConnectivity(in Network network, boolean hasConnectivity); From 03b44c560f88b262f288b776adb8baea7abcb389 Mon Sep 17 00:00:00 2001 From: Aurimas Liutikas Date: Wed, 28 Aug 2019 13:01:05 -0700 Subject: [PATCH 004/229] Add missing nullability annotations. To prepare for enabling MissingNullability Metalava check this CL works on adding missing nullability issues that metalava flags if we tell it to flag new things since API 29. This is not a complete CL, mostly addresses public api and toString/equals for @SystemApi Exempt-From-Owner-Approval: Large scale nullability clean up Bug: 124515653 Test: make -j checkapi Change-Id: I109260842cfc25f06e40694997fcbb4afa02c867 --- core/java/android/net/StaticIpConfiguration.java | 3 ++- core/java/android/net/apf/ApfCapabilities.java | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java index d6deba5d41..5bc9953e0d 100644 --- a/core/java/android/net/StaticIpConfiguration.java +++ b/core/java/android/net/StaticIpConfiguration.java @@ -236,6 +236,7 @@ public final class StaticIpConfiguration implements Parcelable { return lp; } + @NonNull @Override public String toString() { StringBuffer str = new StringBuffer(); @@ -267,7 +268,7 @@ public final class StaticIpConfiguration implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) return true; if (!(obj instanceof StaticIpConfiguration)) return false; diff --git a/core/java/android/net/apf/ApfCapabilities.java b/core/java/android/net/apf/ApfCapabilities.java index 4dd2ace59c..b1de74e817 100644 --- a/core/java/android/net/apf/ApfCapabilities.java +++ b/core/java/android/net/apf/ApfCapabilities.java @@ -17,6 +17,7 @@ package android.net.apf; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.content.res.Resources; @@ -91,6 +92,7 @@ public final class ApfCapabilities implements Parcelable { } }; + @NonNull @Override public String toString() { return String.format("%s{version: %d, maxSize: %d, format: %d}", getClass().getSimpleName(), @@ -98,7 +100,7 @@ public final class ApfCapabilities implements Parcelable { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (!(obj instanceof ApfCapabilities)) return false; final ApfCapabilities other = (ApfCapabilities) obj; return apfVersionSupported == other.apfVersionSupported From 785e9850c2abc0b0ed672b31ddbbd4e82e39476a Mon Sep 17 00:00:00 2001 From: Christopher Tate Date: Tue, 8 Oct 2019 15:49:43 -0700 Subject: [PATCH 005/229] Move PackageManagerInternal to services.jar The one messy internal caller is the settings provider, so a new @hide API on PackageManager was introduced to decouple the provider from LocalServices. That new entry point is only callable by uid 1000, paralleling the previous system-caller-only availability. Bug: 140833849 Test: system boots & runs normally Change-Id: I93ae38b8f55db7864893a97795aea63014bf5e12 --- .../com/android/server/connectivity/PermissionMonitorTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java index 702921836b..3fdba6eac5 100644 --- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -54,7 +54,6 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; -import android.content.pm.PackageList; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.UserInfo; @@ -70,6 +69,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.LocalServices; +import com.android.server.pm.PackageList; import org.junit.Before; import org.junit.Test; From fbfa7d09ffa56429a3d53fa8fade8a175f35c210 Mon Sep 17 00:00:00 2001 From: Jeongik Cha Date: Tue, 15 Oct 2019 17:03:51 +0900 Subject: [PATCH 006/229] Change AIDL module name Naming rule for aidl module is changed to make using unstable AIDL module more explicit So, to use unstable version AIDL module, use "-unstable" suffix version And also, module name without any suffix means latest frozen version. But wrt modules for C++ and NDK, module name with latest frozen version is not available for now. In b/139280289, more background is explained Test: m Bug: 139280289 Change-Id: Ib38e2cb114cc373ef50652f421ddaff9b4fbe5b9 --- tests/net/Android.bp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/net/Android.bp b/tests/net/Android.bp index b9b2238572..10f27e243c 100644 --- a/tests/net/Android.bp +++ b/tests/net/Android.bp @@ -37,7 +37,7 @@ java_defaults { "libvndksupport", "libziparchive", "libz", - "netd_aidl_interface-V2-cpp", + "netd_aidl_interface-cpp", ], } From fa065b1fc818bab0d390ec96aef7d07f38b555c3 Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Mon, 4 Nov 2019 11:16:45 +0000 Subject: [PATCH 007/229] Add @UnsupportedAppUsage to test apis that are known to be used by apps. go/testapi-enforcement Bug: 133832325 Test: m Change-Id: Ifc8db120640a1554dcbf1722e61e09c7ddc65dd6 Merged-In: Ifc8db120640a1554dcbf1722e61e09c7ddc65dd6 --- core/java/android/net/NetworkCapabilities.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index e3259ffa9d..88877e2547 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -478,6 +478,7 @@ public final class NetworkCapabilities implements Parcelable { * @return an array of capability values for this instance. * @hide */ + @UnsupportedAppUsage @TestApi public @NetCapability int[] getCapabilities() { return BitUtils.unpackBits(mNetworkCapabilities); From 32958fcc9870faf16d0fcef0a7e1cd2039f69153 Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Fri, 15 Nov 2019 19:12:49 +0000 Subject: [PATCH 008/229] Add @UnsupportedAppUsage annotations for greylist. go/cleanup-greylist-txt These have already been greylisted, however due to bugs/omissions in the tooling have been kept in go/greylist-txt instead of being annotated in the code. This is partial merge of aosp/Id6c1f5e403a0e66edb1102ee45f3bf19f244fb09. Telephony greylist cleanup has been done separately. Note that annotations outside of frameworks/base/ have been merged from AOSP. Bug: 137350495 Test: m Exempt-From-Owner-Approval: merge Change-Id: I015c466e8b69cc0fed5e9d394ba865aad11d8ba6 --- core/java/android/net/ConnectivityManager.java | 3 +++ core/java/android/net/LinkProperties.java | 2 ++ 2 files changed, 5 insertions(+) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index cfa3934b0c..1a33166dc1 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -1763,6 +1763,9 @@ public class ConnectivityManager { /** @hide */ public static class PacketKeepaliveCallback { + @UnsupportedAppUsage + public PacketKeepaliveCallback() { + } /** The requested keepalive was successfully started. */ @UnsupportedAppUsage public void onStarted() {} diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 3ec0aeac47..0706e755d1 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -111,6 +111,8 @@ public final class LinkProperties implements Parcelable { /** * @hide */ + @UnsupportedAppUsage(implicitMember = + "values()[Landroid/net/LinkProperties$ProvisioningChange;") public enum ProvisioningChange { @UnsupportedAppUsage STILL_NOT_PROVISIONED, From d472369791495022dcafe1230567f8a6642d3323 Mon Sep 17 00:00:00 2001 From: Edward Savage-Jones Date: Tue, 26 Nov 2019 13:18:08 +0100 Subject: [PATCH 009/229] Add NETWORK_AIRPLANE_MODE permission Add a permission to allow airplane mode to be toggled without holding the NETWORK_SETTINGS (or similar) permission. Bug: 141621384 Bug: 145164696 Test: TODO Change-Id: Iebe2f501fdd802d54fd3345ac2fb0a8c129faf71 --- core/java/android/net/ConnectivityManager.java | 1 + .../java/com/android/server/ConnectivityService.java | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 194068cd74..a5bc408ed6 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3155,6 +3155,7 @@ public class ConnectivityManager { * @hide */ @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_AIRPLANE_MODE, android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD, android.Manifest.permission.NETWORK_STACK}) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index bb7406a567..50246f5c1c 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2060,6 +2060,15 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } + private void enforceAirplaneModePermission() { + enforceAnyPermissionOf( + android.Manifest.permission.NETWORK_AIRPLANE_MODE, + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); + } + private boolean checkNetworkStackPermission() { return checkAnyPermissionOf( android.Manifest.permission.NETWORK_STACK, @@ -4900,7 +4909,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void setAirplaneMode(boolean enable) { - enforceNetworkStackSettingsOrSetup(); + enforceAirplaneModePermission(); final long ident = Binder.clearCallingIdentity(); try { final ContentResolver cr = mContext.getContentResolver(); From c70070914f917a045c14a1001d8a57c8ae78c1fc Mon Sep 17 00:00:00 2001 From: markchien Date: Mon, 30 Sep 2019 14:40:57 +0800 Subject: [PATCH 010/229] [Tether07] Migrate Tethering into module Now tethering would be run in dedicated service. TetheringManager is the interface used to communicate with TetheringService. The new call flow would be: ConnectivityManager -> ConnectivityService -> TetheringManager -> TetheringService. Note: the return value of #tether(), #untether() and #setUsbTethering() APIs would always be no error. Client can use #getLastTetherError() or #getTetheredIfaces or listen tether state change to check status of corresponding interface. Bug: 136040414 Bug: 144742179 Test: -build, flash, boot -atest TetheringTests -atest FrameworksNetTests Change-Id: I7e78c0e0a3e70f940a749ba2a39ece7c7ec5b9b3 --- .../android/server/ConnectivityService.java | 85 +++++++------------ tests/net/Android.bp | 1 - .../ConnectivityServiceIntegrationTest.kt | 5 +- .../server/ConnectivityServiceTest.java | 4 +- 4 files changed, 37 insertions(+), 58 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index bb7406a567..652dd40297 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -108,6 +108,7 @@ import android.net.PrivateDnsConfigParcel; import android.net.ProxyInfo; import android.net.RouteInfo; import android.net.SocketKeepalive; +import android.net.TetheringManager; import android.net.UidRange; import android.net.Uri; import android.net.VpnService; @@ -187,9 +188,7 @@ import com.android.server.connectivity.NetworkNotificationManager; import com.android.server.connectivity.NetworkNotificationManager.NotificationType; import com.android.server.connectivity.PermissionMonitor; import com.android.server.connectivity.ProxyTracker; -import com.android.server.connectivity.Tethering; import com.android.server.connectivity.Vpn; -import com.android.server.connectivity.tethering.TetheringDependencies; import com.android.server.net.BaseNetdEventCallback; import com.android.server.net.BaseNetworkObserver; import com.android.server.net.LockdownVpnTracker; @@ -233,7 +232,6 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final String DIAG_ARG = "--diag"; public static final String SHORT_ARG = "--short"; - private static final String TETHERING_ARG = "tethering"; private static final String NETWORK_ARG = "networks"; private static final String REQUEST_ARG = "requests"; @@ -280,7 +278,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private MockableSystemProperties mSystemProperties; - private Tethering mTethering; + private TetheringManager mTetheringManager; @VisibleForTesting protected final PermissionMonitor mPermissionMonitor; @@ -869,15 +867,10 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** - * @see Tethering + * Get a reference to the TetheringManager. */ - public Tethering makeTethering(@NonNull Context context, - @NonNull INetworkManagementService nms, - @NonNull INetworkStatsService statsService, - @NonNull INetworkPolicyManager policyManager, - @NonNull TetheringDependencies tetheringDeps) { - return new Tethering(context, nms, statsService, policyManager, - IoThread.get().getLooper(), getSystemProperties(), tetheringDeps); + public TetheringManager getTetheringManager() { + return TetheringManager.getInstance(); } /** @@ -1075,8 +1068,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - mTethering = deps.makeTethering(mContext, mNMS, mStatsService, mPolicyManager, - makeTetheringDependencies()); + mTetheringManager = mDeps.getTetheringManager(); mPermissionMonitor = new PermissionMonitor(mContext, mNetd); @@ -1111,7 +1103,6 @@ public class ConnectivityService extends IConnectivityManager.Stub mHandler); try { - mNMS.registerObserver(mTethering); mNMS.registerObserver(mDataActivityObserver); } catch (RemoteException e) { loge("Error registering observer :" + e); @@ -1145,19 +1136,6 @@ public class ConnectivityService extends IConnectivityManager.Stub registerPrivateDnsSettingsCallbacks(); } - private TetheringDependencies makeTetheringDependencies() { - return new TetheringDependencies() { - @Override - public boolean isTetheringSupported() { - return ConnectivityService.this.isTetheringSupported(); - } - @Override - public NetworkRequest getDefaultNetworkRequest() { - return mDefaultRequest; - } - }; - } - private static NetworkCapabilities createDefaultNetworkCapabilitiesForUid(int uid) { final NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addCapability(NET_CAPABILITY_INTERNET); @@ -1909,7 +1887,9 @@ public class ConnectivityService extends IConnectivityManager.Stub // TODO: relocate this specific callback in Tethering. if (restrictBackground) { log("onRestrictBackgroundChanged(true): disabling tethering"); - mTethering.untetherAll(); + mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI); + mTetheringManager.stopTethering(ConnectivityManager.TETHERING_USB); + mTetheringManager.stopTethering(ConnectivityManager.TETHERING_BLUETOOTH); } } }; @@ -2193,7 +2173,6 @@ public class ConnectivityService extends IConnectivityManager.Stub mPermissionMonitor.startMonitoring(); mProxyTracker.loadGlobalProxy(); registerNetdEventCallback(); - mTethering.systemReady(); synchronized (this) { mSystemReady = true; @@ -2405,9 +2384,6 @@ public class ConnectivityService extends IConnectivityManager.Stub if (ArrayUtils.contains(args, DIAG_ARG)) { dumpNetworkDiagnostics(pw); return; - } else if (ArrayUtils.contains(args, TETHERING_ARG)) { - mTethering.dump(fd, pw, args); - return; } else if (ArrayUtils.contains(args, NETWORK_ARG)) { dumpNetworks(pw); return; @@ -2469,10 +2445,13 @@ public class ConnectivityService extends IConnectivityManager.Stub mLegacyTypeTracker.dump(pw); pw.println(); - mTethering.dump(fd, pw, args); + mKeepaliveTracker.dump(pw); pw.println(); - mKeepaliveTracker.dump(pw); + pw.println("TetheringManager logs:"); + pw.increaseIndent(); + TetheringManager.getInstance().dump(pw); + pw.decreaseIndent(); pw.println(); dumpAvoidBadWifiSettings(pw); @@ -4004,7 +3983,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public int tether(String iface, String callerPkg) { ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); if (isTetheringSupported()) { - return mTethering.tether(iface); + return mTetheringManager.tether(iface); } else { return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; } @@ -4016,7 +3995,7 @@ public class ConnectivityService extends IConnectivityManager.Stub ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); if (isTetheringSupported()) { - return mTethering.untether(iface); + return mTetheringManager.untether(iface); } else { return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; } @@ -4028,7 +4007,7 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceTetherAccessPermission(); if (isTetheringSupported()) { - return mTethering.getLastTetherError(iface); + return mTetheringManager.getLastTetherError(iface); } else { return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; } @@ -4039,7 +4018,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public String[] getTetherableUsbRegexs() { enforceTetherAccessPermission(); if (isTetheringSupported()) { - return mTethering.getTetherableUsbRegexs(); + return mTetheringManager.getTetherableUsbRegexs(); } else { return new String[0]; } @@ -4049,7 +4028,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public String[] getTetherableWifiRegexs() { enforceTetherAccessPermission(); if (isTetheringSupported()) { - return mTethering.getTetherableWifiRegexs(); + return mTetheringManager.getTetherableWifiRegexs(); } else { return new String[0]; } @@ -4059,7 +4038,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public String[] getTetherableBluetoothRegexs() { enforceTetherAccessPermission(); if (isTetheringSupported()) { - return mTethering.getTetherableBluetoothRegexs(); + return mTetheringManager.getTetherableBluetoothRegexs(); } else { return new String[0]; } @@ -4069,7 +4048,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public int setUsbTethering(boolean enable, String callerPkg) { ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); if (isTetheringSupported()) { - return mTethering.setUsbTethering(enable); + return mTetheringManager.setUsbTethering(enable); } else { return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; } @@ -4080,25 +4059,25 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public String[] getTetherableIfaces() { enforceTetherAccessPermission(); - return mTethering.getTetherableIfaces(); + return mTetheringManager.getTetherableIfaces(); } @Override public String[] getTetheredIfaces() { enforceTetherAccessPermission(); - return mTethering.getTetheredIfaces(); + return mTetheringManager.getTetheredIfaces(); } @Override public String[] getTetheringErroredIfaces() { enforceTetherAccessPermission(); - return mTethering.getErroredIfaces(); + return mTetheringManager.getTetheringErroredIfaces(); } @Override public String[] getTetheredDhcpRanges() { enforceConnectivityInternalPermission(); - return mTethering.getTetheredDhcpRanges(); + return mTetheringManager.getTetheredDhcpRanges(); } @Override @@ -4126,7 +4105,8 @@ public class ConnectivityService extends IConnectivityManager.Stub Binder.restoreCallingIdentity(token); } - return tetherEnabledInSettings && adminUser && mTethering.hasTetherableConfiguration(); + return tetherEnabledInSettings && adminUser + && mTetheringManager.hasTetherableConfiguration(); } @Override @@ -4137,13 +4117,13 @@ public class ConnectivityService extends IConnectivityManager.Stub receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null); return; } - mTethering.startTethering(type, receiver, showProvisioningUi); + mTetheringManager.startTethering(type, receiver, showProvisioningUi); } @Override public void stopTethering(int type, String callerPkg) { ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - mTethering.stopTethering(type); + mTetheringManager.stopTethering(type); } /** @@ -4157,7 +4137,8 @@ public class ConnectivityService extends IConnectivityManager.Stub public void getLatestTetheringEntitlementResult(int type, ResultReceiver receiver, boolean showEntitlementUi, String callerPkg) { ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - mTethering.getLatestTetheringEntitlementResult(type, receiver, showEntitlementUi); + mTetheringManager.requestLatestTetheringEntitlementResult( + type, receiver, showEntitlementUi); } /** Register tethering event callback. */ @@ -4165,7 +4146,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg) { ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - mTethering.registerTetheringEventCallback(callback); + mTetheringManager.registerTetheringEventCallback(callback); } /** Unregister tethering event callback. */ @@ -4173,7 +4154,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg) { ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - mTethering.unregisterTetheringEventCallback(callback); + mTetheringManager.unregisterTetheringEventCallback(callback); } // Called when we lose the default network and have no replacement yet. diff --git a/tests/net/Android.bp b/tests/net/Android.bp index 10f27e243c..b2f384ac83 100644 --- a/tests/net/Android.bp +++ b/tests/net/Android.bp @@ -45,7 +45,6 @@ android_test { name: "FrameworksNetTests", defaults: ["FrameworksNetTests-jni-defaults"], srcs: [ - ":tethering-tests-src", "java/**/*.java", "java/**/*.kt", ], diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt index 334b26d821..25028fb3ca 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt @@ -32,6 +32,7 @@ import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET import android.net.NetworkCapabilities.TRANSPORT_CELLULAR import android.net.NetworkRequest import android.net.TestNetworkStackClient +import android.net.TetheringManager import android.net.metrics.IpConnectivityLog import android.os.ConditionVariable import android.os.IBinder @@ -48,7 +49,6 @@ import com.android.server.connectivity.DefaultNetworkMetrics import com.android.server.connectivity.IpConnectivityMetrics import com.android.server.connectivity.MockableSystemProperties import com.android.server.connectivity.ProxyTracker -import com.android.server.connectivity.Tethering import com.android.server.net.NetworkPolicyManagerInternal import com.android.testutils.TestableNetworkCallback import org.junit.After @@ -169,8 +169,7 @@ class ConnectivityServiceIntegrationTest { val deps = spy(ConnectivityService.Dependencies()) doReturn(networkStackClient).`when`(deps).networkStack doReturn(metricsLogger).`when`(deps).metricsLogger - doReturn(mock(Tethering::class.java)).`when`(deps).makeTethering( - any(), any(), any(), any(), any()) + doReturn(mock(TetheringManager::class.java)).`when`(deps).getTetheringManager() doReturn(mock(ProxyTracker::class.java)).`when`(deps).makeProxyTracker(any(), any()) doReturn(mock(MockableSystemProperties::class.java)).`when`(deps).systemProperties doReturn(TestNetIdManager()).`when`(deps).makeNetIdManager() diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 7ea9bcf36f..2a09f647a4 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -163,6 +163,7 @@ import android.net.ProxyInfo; import android.net.ResolverParamsParcel; import android.net.RouteInfo; import android.net.SocketKeepalive; +import android.net.TetheringManager; import android.net.UidRange; import android.net.metrics.IpConnectivityLog; import android.net.shared.NetworkMonitorUtils; @@ -210,7 +211,6 @@ import com.android.server.connectivity.MockableSystemProperties; import com.android.server.connectivity.Nat464Xlat; import com.android.server.connectivity.NetworkNotificationManager.NotificationType; import com.android.server.connectivity.ProxyTracker; -import com.android.server.connectivity.Tethering; import com.android.server.connectivity.Vpn; import com.android.server.net.NetworkPinner; import com.android.server.net.NetworkPolicyManagerInternal; @@ -1130,7 +1130,7 @@ public class ConnectivityServiceTest { doReturn(new TestNetIdManager()).when(deps).makeNetIdManager(); doReturn(mNetworkStack).when(deps).getNetworkStack(); doReturn(systemProperties).when(deps).getSystemProperties(); - doReturn(mock(Tethering.class)).when(deps).makeTethering(any(), any(), any(), any(), any()); + doReturn(mock(TetheringManager.class)).when(deps).getTetheringManager(); doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any()); doReturn(mMetricsService).when(deps).getMetricsLogger(); doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt()); From e031948c1a1fec938f709d7dc5fcd3c7b888c442 Mon Sep 17 00:00:00 2001 From: paulhu Date: Mon, 12 Aug 2019 16:25:11 +0800 Subject: [PATCH 011/229] Replace the permission of internal connectivity checks A number of connectivity checks that protect system-only methods check for CONNECTIVITY_INTERNAL, but CONNECTIVITY_INTERNAL is a signature|privileged permission. We should audit the permission checks, and convert checks that protect code that should not be called outside the system to a signature permission. So replace all CONNECTIVITY_INTERNAL to other proper permissions. Bug: 32963470 Test: atest FrameworksNetTests NetworkPolicyManagerServiceTest Change-Id: I8f2dd1cd0609056494eaf612d39820e273ae093f --- .../java/android/net/ConnectivityManager.java | 21 +++++-- .../android/server/ConnectivityService.java | 57 +++++++++++-------- .../connectivity/PermissionMonitor.java | 5 +- .../connectivity/PermissionMonitorTest.java | 17 +++--- 4 files changed, 63 insertions(+), 37 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 194068cd74..d95da91d20 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -1006,7 +1006,7 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) @Nullable public Network getActiveNetworkForUid(int uid) { return getActiveNetworkForUid(uid, false); @@ -1135,7 +1135,7 @@ public class ConnectivityManager { * * {@hide} */ - @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) @UnsupportedAppUsage public NetworkInfo getActiveNetworkInfoForUid(int uid) { return getActiveNetworkInfoForUid(uid, false); @@ -1370,10 +1370,14 @@ public class ConnectivityManager { * The system network validation may be using different strategies to detect captive portals, * so this method does not necessarily return a URL used by the system. It only returns a URL * that may be relevant for other components trying to detect captive portals. + * * @hide + * @deprecated This API returns URL which is not guaranteed to be one of the URLs used by the + * system. */ + @Deprecated @SystemApi - @RequiresPermission(android.Manifest.permission.LOCAL_MAC_ADDRESS) + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getCaptivePortalServerUrl() { try { return mService.getCaptivePortalServerUrl(); @@ -2399,6 +2403,7 @@ public class ConnectivityManager { * @return an array of 0 or more {@code String} of tethered dhcp ranges. * {@hide} */ + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String[] getTetheredDhcpRanges() { try { return mService.getTetheredDhcpRanges(); @@ -2978,7 +2983,7 @@ public class ConnectivityManager { * HTTP proxy. A {@code null} value will clear the global HTTP proxy. * @hide */ - @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void setGlobalProxy(ProxyInfo p) { try { mService.setGlobalProxy(p); @@ -3123,6 +3128,7 @@ public class ConnectivityManager { * Get the mobile provisioning url. * {@hide} */ + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String getMobileProvisioningUrl() { try { return mService.getMobileProvisioningUrl(); @@ -3169,6 +3175,7 @@ public class ConnectivityManager { /** {@hide} - returns the factory serial number */ @UnsupportedAppUsage + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public int registerNetworkFactory(Messenger messenger, String name) { try { return mService.registerNetworkFactory(messenger, name); @@ -3179,6 +3186,7 @@ public class ConnectivityManager { /** {@hide} */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void unregisterNetworkFactory(Messenger messenger) { try { mService.unregisterNetworkFactory(messenger); @@ -3196,6 +3204,7 @@ public class ConnectivityManager { * Register a NetworkAgent with ConnectivityService. * @return NetID corresponding to NetworkAgent. */ + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkMisc misc) { return registerNetworkAgent(messenger, ni, lp, nc, score, misc, @@ -3207,6 +3216,7 @@ public class ConnectivityManager { * Register a NetworkAgent with ConnectivityService. * @return NetID corresponding to NetworkAgent. */ + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkMisc misc, int factorySerialNumber) { try { @@ -4201,7 +4211,7 @@ public class ConnectivityManager { * * @hide */ - @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void startCaptivePortalApp(Network network) { try { mService.startCaptivePortalApp(network); @@ -4317,6 +4327,7 @@ public class ConnectivityManager { * Resets all connectivity manager settings back to factory defaults. * @hide */ + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void factoryReset() { try { mService.factoryReset(); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 36f44e48b8..b6e8db03a5 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1395,7 +1395,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) { - enforceConnectivityInternalPermission(); + NetworkStack.checkNetworkStackPermission(mContext); return getActiveNetworkForUidInternal(uid, ignoreBlocked); } @@ -1437,7 +1437,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) { - enforceConnectivityInternalPermission(); + NetworkStack.checkNetworkStackPermission(mContext); final NetworkState state = getUnfilteredActiveNetworkState(uid); filterNetworkStateForUid(state, uid, ignoreBlocked); return state.networkInfo; @@ -1656,8 +1656,8 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkState[] getAllNetworkState() { - // Require internal since we're handing out IMSI details - enforceConnectivityInternalPermission(); + // This contains IMSI details, so make sure the caller is privileged. + NetworkStack.checkNetworkStackPermission(mContext); final ArrayList result = Lists.newArrayList(); for (Network network : getAllNetworks()) { @@ -1735,7 +1735,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } enforceChangePermission(); if (mProtectedNetworks.contains(networkType)) { - enforceConnectivityInternalPermission(); + enforceConnectivityRestrictedNetworksPermission(); } InetAddress addr; @@ -2005,6 +2005,12 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } + private void enforceNetworkFactoryPermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.NETWORK_FACTORY, + "ConnectivityService"); + } + private boolean checkSettingsPermission() { return checkAnyPermissionOf( android.Manifest.permission.NETWORK_SETTINGS, @@ -2024,18 +2030,19 @@ public class ConnectivityService extends IConnectivityManager.Stub "ConnectivityService"); } - private void enforceConnectivityInternalPermission() { - enforceAnyPermissionOf( - android.Manifest.permission.CONNECTIVITY_INTERNAL, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); - } - private void enforceControlAlwaysOnVpnPermission() { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CONTROL_ALWAYS_ON_VPN, "ConnectivityService"); } + private void enforceNetworkStackOrSettingsPermission() { + enforceAnyPermissionOf( + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); + } + private void enforceNetworkStackSettingsOrSetup() { enforceAnyPermissionOf( android.Manifest.permission.NETWORK_SETTINGS, @@ -2063,7 +2070,11 @@ public class ConnectivityService extends IConnectivityManager.Stub "ConnectivityService"); return; } catch (SecurityException e) { /* fallback to ConnectivityInternalPermission */ } - enforceConnectivityInternalPermission(); + // TODO: Remove this fallback check after all apps have declared + // CONNECTIVITY_USE_RESTRICTED_NETWORKS. + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CONNECTIVITY_INTERNAL, + "ConnectivityService"); } private void enforceKeepalivePermission() { @@ -2072,7 +2083,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // Public because it's used by mLockdownTracker. public void sendConnectedBroadcast(NetworkInfo info) { - enforceConnectivityInternalPermission(); + NetworkStack.checkNetworkStackPermission(mContext); sendGeneralBroadcast(info, CONNECTIVITY_ACTION); } @@ -3589,7 +3600,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void startCaptivePortalApp(Network network) { - enforceConnectivityInternalPermission(); + enforceNetworkStackOrSettingsPermission(); mHandler.post(() -> { NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); if (nai == null) return; @@ -4080,7 +4091,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public String[] getTetheredDhcpRanges() { - enforceConnectivityInternalPermission(); + enforceSettingsPermission(); return mTetheringManager.getTetheredDhcpRanges(); } @@ -4304,7 +4315,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void setGlobalProxy(final ProxyInfo proxyProperties) { - enforceConnectivityInternalPermission(); + NetworkStack.checkNetworkStackPermission(mContext); mProxyTracker.setGlobalProxy(proxyProperties); } @@ -4843,7 +4854,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public String getMobileProvisioningUrl() { - enforceConnectivityInternalPermission(); + enforceSettingsPermission(); String url = getProvisioningUrlBaseFromFile(); if (TextUtils.isEmpty(url)) { url = mContext.getResources().getString(R.string.mobile_provisioning_url); @@ -4869,7 +4880,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void setProvisioningNotificationVisible(boolean visible, int networkType, String action) { - enforceConnectivityInternalPermission(); + enforceSettingsPermission(); if (!ConnectivityManager.isNetworkTypeValid(networkType)) { return; } @@ -5457,7 +5468,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public int registerNetworkFactory(Messenger messenger, String name) { - enforceConnectivityInternalPermission(); + enforceNetworkFactoryPermission(); NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel(), NetworkFactory.SerialNumber.nextSerialNumber()); mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi)); @@ -5472,7 +5483,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void unregisterNetworkFactory(Messenger messenger) { - enforceConnectivityInternalPermission(); + enforceNetworkFactoryPermission(); mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_FACTORY, messenger)); } @@ -5571,7 +5582,7 @@ public class ConnectivityService extends IConnectivityManager.Stub public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkMisc networkMisc, int factorySerialNumber) { - enforceConnectivityInternalPermission(); + enforceNetworkFactoryPermission(); LinkProperties lp = new LinkProperties(linkProperties); lp.ensureDirectlyConnectedRoutes(); @@ -6935,7 +6946,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public String getCaptivePortalServerUrl() { - enforceConnectivityInternalPermission(); + enforceNetworkStackOrSettingsPermission(); String settingUrl = mContext.getResources().getString( R.string.config_networkCaptivePortalServerUrl); @@ -6988,7 +6999,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void factoryReset() { - enforceConnectivityInternalPermission(); + enforceSettingsPermission(); if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) { return; diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java index 56f4959a97..f0b7150dd8 100644 --- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java +++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java @@ -17,7 +17,6 @@ package com.android.server.connectivity; import static android.Manifest.permission.CHANGE_NETWORK_STATE; -import static android.Manifest.permission.CONNECTIVITY_INTERNAL; import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; import static android.Manifest.permission.INTERNET; import static android.Manifest.permission.NETWORK_STACK; @@ -25,6 +24,7 @@ import static android.Manifest.permission.UPDATE_DEVICE_STATS; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_ANY_USER; +import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; import static android.os.Process.INVALID_UID; import static android.os.Process.SYSTEM_UID; @@ -259,7 +259,8 @@ public class PermissionMonitor { return true; } } - return hasPermission(app, CONNECTIVITY_INTERNAL) + + return hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK) || hasPermission(app, NETWORK_STACK) || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS); } diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java index 2738daaa53..39f849c340 100644 --- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -265,6 +265,8 @@ public class PermissionMonitorTest { assertFalse(mPermissionMonitor.hasNetworkPermission(app)); app = systemPackageInfoWithPermissions(CONNECTIVITY_USE_RESTRICTED_NETWORKS); assertFalse(mPermissionMonitor.hasNetworkPermission(app)); + app = systemPackageInfoWithPermissions(CONNECTIVITY_INTERNAL); + assertFalse(mPermissionMonitor.hasNetworkPermission(app)); } @Test @@ -274,7 +276,7 @@ public class PermissionMonitorTest { PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CHANGE_NETWORK_STATE)); assertTrue(hasRestrictedNetworkPermission( PARTITION_SYSTEM, VERSION_P, MOCK_UID1, NETWORK_STACK)); - assertTrue(hasRestrictedNetworkPermission( + assertFalse(hasRestrictedNetworkPermission( PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_INTERNAL)); assertTrue(hasRestrictedNetworkPermission( PARTITION_SYSTEM, VERSION_P, MOCK_UID1, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); @@ -283,7 +285,7 @@ public class PermissionMonitorTest { assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, MOCK_UID1)); assertFalse(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_Q, MOCK_UID1, CHANGE_WIFI_STATE)); + PARTITION_SYSTEM, VERSION_Q, MOCK_UID1, CONNECTIVITY_INTERNAL)); } @Test @@ -291,14 +293,14 @@ public class PermissionMonitorTest { doReturn(VERSION_P).when(mPermissionMonitor).getDeviceFirstSdkInt(); assertTrue(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_P, SYSTEM_UID)); assertTrue(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CHANGE_WIFI_STATE)); + PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CONNECTIVITY_INTERNAL)); assertTrue(hasRestrictedNetworkPermission( PARTITION_SYSTEM, VERSION_P, SYSTEM_UID, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); doReturn(VERSION_Q).when(mPermissionMonitor).getDeviceFirstSdkInt(); assertFalse(hasRestrictedNetworkPermission(PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID)); assertFalse(hasRestrictedNetworkPermission( - PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CHANGE_WIFI_STATE)); + PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CONNECTIVITY_INTERNAL)); assertTrue(hasRestrictedNetworkPermission( PARTITION_SYSTEM, VERSION_Q, SYSTEM_UID, CONNECTIVITY_USE_RESTRICTED_NETWORKS)); } @@ -319,7 +321,7 @@ public class PermissionMonitorTest { assertFalse(hasRestrictedNetworkPermission(PARTITION_VENDOR, VERSION_Q, MOCK_UID1)); assertFalse(hasRestrictedNetworkPermission( - PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CHANGE_WIFI_STATE)); + PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CONNECTIVITY_INTERNAL)); assertFalse(hasRestrictedNetworkPermission( PARTITION_VENDOR, VERSION_Q, MOCK_UID1, CHANGE_NETWORK_STATE)); } @@ -337,7 +339,7 @@ public class PermissionMonitorTest { public void testHasUseBackgroundNetworksPermission() throws Exception { assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(SYSTEM_UID)); assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID); - assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID, CHANGE_WIFI_STATE); + assertBackgroundPermission(false, SYSTEM_PACKAGE1, SYSTEM_UID, CONNECTIVITY_INTERNAL); assertBackgroundPermission(true, SYSTEM_PACKAGE1, SYSTEM_UID, CHANGE_NETWORK_STATE); assertBackgroundPermission(true, SYSTEM_PACKAGE1, SYSTEM_UID, NETWORK_STACK); @@ -348,8 +350,9 @@ public class PermissionMonitorTest { assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID2)); assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2); - assertBackgroundPermission(true, MOCK_PACKAGE2, MOCK_UID2, + assertBackgroundPermission(false, MOCK_PACKAGE2, MOCK_UID2, CONNECTIVITY_INTERNAL); + assertBackgroundPermission(true, MOCK_PACKAGE2, MOCK_UID2, NETWORK_STACK); } private class NetdMonitor { From 3d97148418e83e9d19e90bae6b60a102bbd20587 Mon Sep 17 00:00:00 2001 From: Jeffrey Huang Date: Thu, 5 Dec 2019 11:28:11 -0800 Subject: [PATCH 012/229] Rename writeToProto to be dumpDebug We want to eventually migrate some of these APIs to be @SystemApi for mainline modules. The #dumpDebug name is more appropriate than #writeToProto. Bug: 142279786 Test: Manual Change-Id: I60793e91cedf6b720d4ecef6a8484f4fed4ff30f --- core/java/android/net/Network.java | 2 +- core/java/android/net/NetworkCapabilities.java | 2 +- core/java/android/net/NetworkRequest.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index f12ba1367d..c6c73fe5b8 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -502,7 +502,7 @@ public class Network implements Parcelable { } /** @hide */ - public void writeToProto(ProtoOutputStream proto, long fieldId) { + public void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); proto.write(NetworkProto.NET_ID, netId); proto.end(token); diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 88877e2547..db20dbd063 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -1602,7 +1602,7 @@ public final class NetworkCapabilities implements Parcelable { } /** @hide */ - public void writeToProto(@NonNull ProtoOutputStream proto, long fieldId) { + public void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); for (int transport : getTransportTypes()) { diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index 4270740cc7..adc497a6d6 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -485,13 +485,13 @@ public class NetworkRequest implements Parcelable { } /** @hide */ - public void writeToProto(ProtoOutputStream proto, long fieldId) { + public void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); proto.write(NetworkRequestProto.TYPE, typeToProtoEnum(type)); proto.write(NetworkRequestProto.REQUEST_ID, requestId); proto.write(NetworkRequestProto.LEGACY_TYPE, legacyType); - networkCapabilities.writeToProto(proto, NetworkRequestProto.NETWORK_CAPABILITIES); + networkCapabilities.dumpDebug(proto, NetworkRequestProto.NETWORK_CAPABILITIES); proto.end(token); } From 5a916810c6ba7a2c1f53867ee7d39aca36e935d0 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 2 Oct 2019 01:39:46 +0800 Subject: [PATCH 013/229] Add keepalive related methods and fields to system APIs Add KeepalivePacketData to system API for mainline support. Also, remove InvalidPacketException class from SocketKeepalive and create a new InvalidPacketException class in android.net Bug: 139268426 Bug: 135998869 Bug: 138306002 Test: atest FrameworksNetTests atest NetworkStackTests atest FrameworksTelephonyTests ./frameworks/opt/net/wifi/tests/wifitests/runtests.sh atest android.net.cts atest android.net.wifi.cts atest android.telephony.cts Change-Id: I2d982e8abb5cb6b4c74a20483550b18cf814320d --- .../android/net/InvalidPacketException.java | 61 +++++++++++++++++++ .../java/android/net/KeepalivePacketData.java | 48 ++++++--------- .../android/net/NattKeepalivePacketData.java | 4 +- core/java/android/net/SocketKeepalive.java | 11 ---- .../server/connectivity/KeepaliveTracker.java | 7 ++- .../connectivity/TcpKeepaliveController.java | 2 +- .../net/TcpKeepalivePacketDataTest.java | 2 - 7 files changed, 88 insertions(+), 47 deletions(-) create mode 100644 core/java/android/net/InvalidPacketException.java diff --git a/core/java/android/net/InvalidPacketException.java b/core/java/android/net/InvalidPacketException.java new file mode 100644 index 0000000000..909998d456 --- /dev/null +++ b/core/java/android/net/InvalidPacketException.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2019 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 android.annotation.SystemApi; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Thrown when a packet is invalid. + * @hide + */ +@SystemApi +public class InvalidPacketException extends Exception { + public final int error; + + // Must match SocketKeepalive#ERROR_INVALID_IP_ADDRESS. + /** Invalid IP address. */ + public static final int ERROR_INVALID_IP_ADDRESS = -21; + + // Must match SocketKeepalive#ERROR_INVALID_PORT. + /** Invalid port number. */ + public static final int ERROR_INVALID_PORT = -22; + + // Must match SocketKeepalive#ERROR_INVALID_LENGTH. + /** Invalid packet length. */ + public static final int ERROR_INVALID_LENGTH = -23; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "ERROR_" }, value = { + ERROR_INVALID_IP_ADDRESS, + ERROR_INVALID_PORT, + ERROR_INVALID_LENGTH + }) + public @interface ErrorCode {} + + /** + * This packet is invalid. + * See the error code for details. + */ + public InvalidPacketException(@ErrorCode final int error) { + this.error = error; + } +} diff --git a/core/java/android/net/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java index 9b8b7322cd..2b8b7e69de 100644 --- a/core/java/android/net/KeepalivePacketData.java +++ b/core/java/android/net/KeepalivePacketData.java @@ -16,13 +16,13 @@ package android.net; -import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS; -import static android.net.SocketKeepalive.ERROR_INVALID_PORT; +import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS; +import static android.net.InvalidPacketException.ERROR_INVALID_PORT; -import android.net.SocketKeepalive.InvalidPacketException; +import android.annotation.NonNull; +import android.annotation.SystemApi; import android.net.util.IpUtils; import android.os.Parcel; -import android.os.Parcelable; import android.util.Log; import java.net.InetAddress; @@ -33,13 +33,16 @@ import java.net.InetAddress; * * @hide */ -public class KeepalivePacketData implements Parcelable { +@SystemApi +public class KeepalivePacketData { private static final String TAG = "KeepalivePacketData"; /** Source IP address */ + @NonNull public final InetAddress srcAddress; /** Destination IP address */ + @NonNull public final InetAddress dstAddress; /** Source port */ @@ -51,13 +54,14 @@ public class KeepalivePacketData implements Parcelable { /** Packet data. A raw byte string of packet data, not including the link-layer header. */ private final byte[] mPacket; - protected static final int IPV4_HEADER_LENGTH = 20; - protected static final int UDP_HEADER_LENGTH = 8; - // This should only be constructed via static factory methods, such as - // nattKeepalivePacket - protected KeepalivePacketData(InetAddress srcAddress, int srcPort, - InetAddress dstAddress, int dstPort, byte[] data) throws InvalidPacketException { + // nattKeepalivePacket. + /** + * A holding class for data necessary to build a keepalive packet. + */ + protected KeepalivePacketData(@NonNull InetAddress srcAddress, int srcPort, + @NonNull InetAddress dstAddress, int dstPort, + @NonNull byte[] data) throws InvalidPacketException { this.srcAddress = srcAddress; this.dstAddress = dstAddress; this.srcPort = srcPort; @@ -78,16 +82,12 @@ public class KeepalivePacketData implements Parcelable { } } + @NonNull public byte[] getPacket() { return mPacket.clone(); } - /* Parcelable Implementation */ - public int describeContents() { - return 0; - } - - /** Write to parcel */ + /** @hide */ public void writeToParcel(Parcel out, int flags) { out.writeString(srcAddress.getHostAddress()); out.writeString(dstAddress.getHostAddress()); @@ -96,6 +96,7 @@ public class KeepalivePacketData implements Parcelable { out.writeByteArray(mPacket); } + /** @hide */ protected KeepalivePacketData(Parcel in) { srcAddress = NetworkUtils.numericToInetAddress(in.readString()); dstAddress = NetworkUtils.numericToInetAddress(in.readString()); @@ -103,17 +104,4 @@ public class KeepalivePacketData implements Parcelable { dstPort = in.readInt(); mPacket = in.createByteArray(); } - - /** Parcelable Creator */ - public static final @android.annotation.NonNull Parcelable.Creator CREATOR = - new Parcelable.Creator() { - public KeepalivePacketData createFromParcel(Parcel in) { - return new KeepalivePacketData(in); - } - - public KeepalivePacketData[] newArray(int size) { - return new KeepalivePacketData[size]; - } - }; - } diff --git a/core/java/android/net/NattKeepalivePacketData.java b/core/java/android/net/NattKeepalivePacketData.java index a77c244d6b..3fb52f12a8 100644 --- a/core/java/android/net/NattKeepalivePacketData.java +++ b/core/java/android/net/NattKeepalivePacketData.java @@ -19,7 +19,6 @@ package android.net; import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS; import static android.net.SocketKeepalive.ERROR_INVALID_PORT; -import android.net.SocketKeepalive.InvalidPacketException; import android.net.util.IpUtils; import android.os.Parcel; import android.os.Parcelable; @@ -32,6 +31,9 @@ import java.nio.ByteOrder; /** @hide */ public final class NattKeepalivePacketData extends KeepalivePacketData implements Parcelable { + private static final int IPV4_HEADER_LENGTH = 20; + private static final int UDP_HEADER_LENGTH = 8; + // This should only be constructed via static factory methods, such as // nattKeepalivePacket private NattKeepalivePacketData(InetAddress srcAddress, int srcPort, diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java index ec73866a64..fb224fbe13 100644 --- a/core/java/android/net/SocketKeepalive.java +++ b/core/java/android/net/SocketKeepalive.java @@ -147,17 +147,6 @@ public abstract class SocketKeepalive implements AutoCloseable { } } - /** - * This packet is invalid. - * See the error code for details. - * @hide - */ - public static class InvalidPacketException extends ErrorCodeException { - public InvalidPacketException(final int error) { - super(error); - } - } - @NonNull final IConnectivityManager mService; @NonNull final Network mNetwork; @NonNull final ParcelFileDescriptor mPfd; diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 9bae902eb7..af8a3666e9 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -39,11 +39,11 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.net.ISocketKeepaliveCallback; +import android.net.InvalidPacketException; import android.net.KeepalivePacketData; import android.net.NattKeepalivePacketData; import android.net.NetworkAgent; import android.net.NetworkUtils; -import android.net.SocketKeepalive.InvalidPacketException; import android.net.SocketKeepalive.InvalidSocketException; import android.net.TcpKeepalivePacketData; import android.net.util.IpUtils; @@ -657,7 +657,10 @@ public class KeepaliveTracker { final TcpKeepalivePacketData packet; try { packet = TcpKeepaliveController.getTcpKeepalivePacket(fd); - } catch (InvalidPacketException | InvalidSocketException e) { + } catch (InvalidSocketException e) { + notifyErrorCallback(cb, e.error); + return; + } catch (InvalidPacketException e) { notifyErrorCallback(cb, e.error); return; } diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java index e570ef1e9b..1129899ee3 100644 --- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java +++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java @@ -30,8 +30,8 @@ import static android.system.OsConstants.IP_TTL; import static android.system.OsConstants.TIOCOUTQ; import android.annotation.NonNull; +import android.net.InvalidPacketException; import android.net.NetworkUtils; -import android.net.SocketKeepalive.InvalidPacketException; import android.net.SocketKeepalive.InvalidSocketException; import android.net.TcpKeepalivePacketData; import android.net.TcpKeepalivePacketDataParcelable; diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java index 5cb0d7e7a1..e632aafde7 100644 --- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java +++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java @@ -22,8 +22,6 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; -import android.net.SocketKeepalive.InvalidPacketException; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; From be9b5e5eead1e689d95839f26cb84639fd36d663 Mon Sep 17 00:00:00 2001 From: markchien Date: Mon, 16 Dec 2019 20:15:20 +0800 Subject: [PATCH 014/229] [Tether13] Move TetheringManager into framework Move tethering out of ConnectivityService. All client would use TetheringManager to talk with TetheringService directly. Bug: 144320246 Test: -build, flash, boot -atest TetheringTests Change-Id: Ib051bea724a256f9c4572b566e46ae7b9c4abe6e --- .../java/android/net/ConnectivityManager.java | 174 ++++---------- .../android/net/IConnectivityManager.aidl | 43 +--- .../android/server/ConnectivityService.java | 226 +++--------------- .../ConnectivityServiceIntegrationTest.kt | 2 - .../server/ConnectivityServiceTest.java | 2 - 5 files changed, 85 insertions(+), 362 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index d95da91d20..3ed51d7f13 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -50,6 +50,7 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.ServiceSpecificException; +import android.os.SystemClock; import android.provider.Settings; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -57,7 +58,6 @@ import android.util.ArrayMap; import android.util.Log; import android.util.SparseIntArray; -import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import com.android.internal.util.Protocol; @@ -802,6 +802,7 @@ public class ConnectivityManager { private INetworkManagementService mNMService; private INetworkPolicyManager mNPManager; + private TetheringManager mTetheringManager; /** * Tests if a given integer represents a valid network type. @@ -2339,6 +2340,28 @@ public class ConnectivityManager { return getInstanceOrNull(); } + private static final int TETHERING_TIMEOUT_MS = 60_000; + private final Object mTetheringLock = new Object(); + + private TetheringManager getTetheringManager() { + synchronized (mTetheringLock) { + if (mTetheringManager != null) { + return mTetheringManager; + } + final long before = System.currentTimeMillis(); + while ((mTetheringManager = (TetheringManager) mContext.getSystemService( + Context.TETHERING_SERVICE)) == null) { + if (System.currentTimeMillis() - before > TETHERING_TIMEOUT_MS) { + Log.e(TAG, "Timeout waiting tethering service not ready yet"); + throw new IllegalStateException("No tethering service yet"); + } + SystemClock.sleep(100); + } + + return mTetheringManager; + } + } + /** * Get the set of tetherable, available interfaces. This list is limited by * device configuration and current interface existence. @@ -2350,11 +2373,7 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage public String[] getTetherableIfaces() { - try { - return mService.getTetherableIfaces(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getTetheringManager().getTetherableIfaces(); } /** @@ -2367,11 +2386,7 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage public String[] getTetheredIfaces() { - try { - return mService.getTetheredIfaces(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getTetheringManager().getTetheredIfaces(); } /** @@ -2390,11 +2405,7 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage public String[] getTetheringErroredIfaces() { - try { - return mService.getTetheringErroredIfaces(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getTetheringManager().getTetheringErroredIfaces(); } /** @@ -2405,11 +2416,7 @@ public class ConnectivityManager { */ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public String[] getTetheredDhcpRanges() { - try { - return mService.getTetheredDhcpRanges(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getTetheringManager().getTetheredDhcpRanges(); } /** @@ -2438,13 +2445,7 @@ public class ConnectivityManager { */ @UnsupportedAppUsage public int tether(String iface) { - try { - String pkgName = mContext.getOpPackageName(); - Log.i(TAG, "tether caller:" + pkgName); - return mService.tether(iface, pkgName); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getTetheringManager().tether(iface); } /** @@ -2467,13 +2468,7 @@ public class ConnectivityManager { */ @UnsupportedAppUsage public int untether(String iface) { - try { - String pkgName = mContext.getOpPackageName(); - Log.i(TAG, "untether caller:" + pkgName); - return mService.untether(iface, pkgName); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getTetheringManager().untether(iface); } /** @@ -2498,16 +2493,7 @@ public class ConnectivityManager { @RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported() { - String pkgName = mContext.getOpPackageName(); - try { - return mService.isTetheringSupported(pkgName); - } catch (SecurityException e) { - // This API is not available to this caller, but for backward-compatibility - // this will just return false instead of throwing. - return false; - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getTetheringManager().isTetheringSupported(); } /** @@ -2576,14 +2562,7 @@ public class ConnectivityManager { } }; - try { - String pkgName = mContext.getOpPackageName(); - Log.i(TAG, "startTethering caller:" + pkgName); - mService.startTethering(type, wrappedCallback, showProvisioningUi, pkgName); - } catch (RemoteException e) { - Log.e(TAG, "Exception trying to start tethering.", e); - wrappedCallback.send(TETHER_ERROR_SERVICE_UNAVAIL, null); - } + getTetheringManager().startTethering(type, wrappedCallback, showProvisioningUi); } /** @@ -2599,13 +2578,7 @@ public class ConnectivityManager { @SystemApi @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int type) { - try { - String pkgName = mContext.getOpPackageName(); - Log.i(TAG, "stopTethering caller:" + pkgName); - mService.stopTethering(type, pkgName); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + getTetheringManager().stopTethering(type); } /** @@ -2627,10 +2600,6 @@ public class ConnectivityManager { public void onUpstreamChanged(@Nullable Network network) {} } - @GuardedBy("mTetheringEventCallbacks") - private final ArrayMap - mTetheringEventCallbacks = new ArrayMap<>(); - /** * Start listening to tethering change events. Any new added callback will receive the last * tethering status right away. If callback is registered when tethering has no upstream or @@ -2648,27 +2617,7 @@ public class ConnectivityManager { @NonNull final OnTetheringEventCallback callback) { Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null."); - synchronized (mTetheringEventCallbacks) { - Preconditions.checkArgument(!mTetheringEventCallbacks.containsKey(callback), - "callback was already registered."); - ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() { - @Override - public void onUpstreamChanged(Network network) throws RemoteException { - Binder.withCleanCallingIdentity(() -> - executor.execute(() -> { - callback.onUpstreamChanged(network); - })); - } - }; - try { - String pkgName = mContext.getOpPackageName(); - Log.i(TAG, "registerTetheringUpstreamCallback:" + pkgName); - mService.registerTetheringEventCallback(remoteCallback, pkgName); - mTetheringEventCallbacks.put(callback, remoteCallback); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + getTetheringManager().registerTetheringEventCallback(executor, callback); } /** @@ -2682,17 +2631,7 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback( @NonNull final OnTetheringEventCallback callback) { - synchronized (mTetheringEventCallbacks) { - ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback); - Preconditions.checkNotNull(remoteCallback, "callback was not registered."); - try { - String pkgName = mContext.getOpPackageName(); - Log.i(TAG, "unregisterTetheringEventCallback:" + pkgName); - mService.unregisterTetheringEventCallback(remoteCallback, pkgName); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + getTetheringManager().unregisterTetheringEventCallback(callback); } @@ -2709,11 +2648,7 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage public String[] getTetherableUsbRegexs() { - try { - return mService.getTetherableUsbRegexs(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getTetheringManager().getTetherableUsbRegexs(); } /** @@ -2729,11 +2664,7 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage public String[] getTetherableWifiRegexs() { - try { - return mService.getTetherableWifiRegexs(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getTetheringManager().getTetherableWifiRegexs(); } /** @@ -2749,11 +2680,7 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage public String[] getTetherableBluetoothRegexs() { - try { - return mService.getTetherableBluetoothRegexs(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getTetheringManager().getTetherableBluetoothRegexs(); } /** @@ -2775,13 +2702,7 @@ public class ConnectivityManager { */ @UnsupportedAppUsage public int setUsbTethering(boolean enable) { - try { - String pkgName = mContext.getOpPackageName(); - Log.i(TAG, "setUsbTethering caller:" + pkgName); - return mService.setUsbTethering(enable, pkgName); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getTetheringManager().setUsbTethering(enable); } /** {@hide} */ @@ -2829,11 +2750,7 @@ public class ConnectivityManager { @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage public int getLastTetherError(String iface) { - try { - return mService.getLastTetherError(iface); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getTetheringManager().getLastTetherError(iface); } /** @hide */ @@ -2899,14 +2816,8 @@ public class ConnectivityManager { } }; - try { - String pkgName = mContext.getOpPackageName(); - Log.i(TAG, "getLatestTetheringEntitlementResult:" + pkgName); - mService.getLatestTetheringEntitlementResult(type, wrappedListener, - showEntitlementUi, pkgName); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + getTetheringManager().requestLatestTetheringEntitlementResult(type, wrappedListener, + showEntitlementUi); } /** @@ -4331,6 +4242,7 @@ public class ConnectivityManager { public void factoryReset() { try { mService.factoryReset(); + getTetheringManager().stopAllTethering(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 5f662f9149..09c02efbcf 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -19,7 +19,6 @@ package android.net; import android.app.PendingIntent; import android.net.ConnectionInfo; import android.net.LinkProperties; -import android.net.ITetheringEventCallback; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; @@ -78,41 +77,31 @@ interface IConnectivityManager boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress); - int tether(String iface, String callerPkg); - - int untether(String iface, String callerPkg); - - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 29, + publicAlternatives = "Use {@code TetheringManager#getLastTetherError} as alternative") int getLastTetherError(String iface); - boolean isTetheringSupported(String callerPkg); - - void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi, - String callerPkg); - - void stopTethering(int type, String callerPkg); - - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 29, + publicAlternatives = "Use {@code TetheringManager#getTetherableIfaces} as alternative") String[] getTetherableIfaces(); - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 29, + publicAlternatives = "Use {@code TetheringManager#getTetheredIfaces} as alternative") String[] getTetheredIfaces(); - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 29, + publicAlternatives = "Use {@code TetheringManager#getTetheringErroredIfaces} " + + "as Alternative") String[] getTetheringErroredIfaces(); - String[] getTetheredDhcpRanges(); - - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 29, + publicAlternatives = "Use {@code TetheringManager#getTetherableUsbRegexs} as alternative") String[] getTetherableUsbRegexs(); - @UnsupportedAppUsage + @UnsupportedAppUsage(maxTargetSdk = 29, + publicAlternatives = "Use {@code TetheringManager#getTetherableWifiRegexs} as alternative") String[] getTetherableWifiRegexs(); - String[] getTetherableBluetoothRegexs(); - - int setUsbTethering(boolean enable, String callerPkg); - @UnsupportedAppUsage(maxTargetSdk = 28) void reportInetCondition(int networkType, int percentage); @@ -217,11 +206,5 @@ interface IConnectivityManager boolean isCallerCurrentAlwaysOnVpnApp(); boolean isCallerCurrentAlwaysOnVpnLockdownApp(); - void getLatestTetheringEntitlementResult(int type, in ResultReceiver receiver, - boolean showEntitlementUi, String callerPkg); - - void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg); - void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg); - IBinder startOrGetTestNetworkService(); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index b71943504b..bb78aceb3b 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -77,7 +77,6 @@ import android.net.INetworkPolicyListener; import android.net.INetworkPolicyManager; import android.net.INetworkStatsService; import android.net.ISocketKeepaliveCallback; -import android.net.ITetheringEventCallback; import android.net.InetAddresses; import android.net.IpMemoryStore; import android.net.IpPrefix; @@ -278,8 +277,6 @@ public class ConnectivityService extends IConnectivityManager.Stub private MockableSystemProperties mSystemProperties; - private TetheringManager mTetheringManager; - @VisibleForTesting protected final PermissionMonitor mPermissionMonitor; @@ -866,13 +863,6 @@ public class ConnectivityService extends IConnectivityManager.Stub return NetworkStackClient.getInstance(); } - /** - * Get a reference to the TetheringManager. - */ - public TetheringManager getTetheringManager() { - return TetheringManager.getInstance(); - } - /** * @see ProxyTracker */ @@ -1072,8 +1062,6 @@ public class ConnectivityService extends IConnectivityManager.Stub mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); - mTetheringManager = mDeps.getTetheringManager(); - mPermissionMonitor = new PermissionMonitor(mContext, mNetd); // Set up the listener for user state for creating user VPNs. @@ -1887,14 +1875,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } mHandler.sendMessage(mHandler.obtainMessage( EVENT_DATA_SAVER_CHANGED, restrictBackground ? 1 : 0, 0)); - - // TODO: relocate this specific callback in Tethering. - if (restrictBackground) { - log("onRestrictBackgroundChanged(true): disabling tethering"); - mTetheringManager.stopTethering(ConnectivityManager.TETHERING_WIFI); - mTetheringManager.stopTethering(ConnectivityManager.TETHERING_USB); - mTetheringManager.stopTethering(ConnectivityManager.TETHERING_BLUETOOTH); - } } }; @@ -2024,12 +2004,6 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, pid, uid); } - private void enforceTetherAccessPermission() { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.ACCESS_NETWORK_STATE, - "ConnectivityService"); - } - private void enforceControlAlwaysOnVpnPermission() { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CONTROL_ALWAYS_ON_VPN, @@ -2462,12 +2436,6 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.println(); mKeepaliveTracker.dump(pw); - pw.println(); - pw.println("TetheringManager logs:"); - pw.increaseIndent(); - TetheringManager.getInstance().dump(pw); - pw.decreaseIndent(); - pw.println(); dumpAvoidBadWifiSettings(pw); @@ -3993,183 +3961,55 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - // javadoc from interface - @Override - public int tether(String iface, String callerPkg) { - ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - if (isTetheringSupported()) { - return mTetheringManager.tether(iface); - } else { - return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; - } - } - - // javadoc from interface - @Override - public int untether(String iface, String callerPkg) { - ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - - if (isTetheringSupported()) { - return mTetheringManager.untether(iface); - } else { - return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; - } - } - - // javadoc from interface @Override + @Deprecated public int getLastTetherError(String iface) { - enforceTetherAccessPermission(); - - if (isTetheringSupported()) { - return mTetheringManager.getLastTetherError(iface); - } else { - return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; - } - } - - // TODO - proper iface API for selection by property, inspection, etc - @Override - public String[] getTetherableUsbRegexs() { - enforceTetherAccessPermission(); - if (isTetheringSupported()) { - return mTetheringManager.getTetherableUsbRegexs(); - } else { - return new String[0]; - } + final TetheringManager tm = (TetheringManager) mContext.getSystemService( + Context.TETHERING_SERVICE); + return tm.getLastTetherError(iface); } @Override - public String[] getTetherableWifiRegexs() { - enforceTetherAccessPermission(); - if (isTetheringSupported()) { - return mTetheringManager.getTetherableWifiRegexs(); - } else { - return new String[0]; - } - } - - @Override - public String[] getTetherableBluetoothRegexs() { - enforceTetherAccessPermission(); - if (isTetheringSupported()) { - return mTetheringManager.getTetherableBluetoothRegexs(); - } else { - return new String[0]; - } - } - - @Override - public int setUsbTethering(boolean enable, String callerPkg) { - ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - if (isTetheringSupported()) { - return mTetheringManager.setUsbTethering(enable); - } else { - return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; - } - } - - // TODO - move iface listing, queries, etc to new module - // javadoc from interface - @Override + @Deprecated public String[] getTetherableIfaces() { - enforceTetherAccessPermission(); - return mTetheringManager.getTetherableIfaces(); + final TetheringManager tm = (TetheringManager) mContext.getSystemService( + Context.TETHERING_SERVICE); + return tm.getTetherableIfaces(); } @Override + @Deprecated public String[] getTetheredIfaces() { - enforceTetherAccessPermission(); - return mTetheringManager.getTetheredIfaces(); + final TetheringManager tm = (TetheringManager) mContext.getSystemService( + Context.TETHERING_SERVICE); + return tm.getTetheredIfaces(); } + @Override + @Deprecated public String[] getTetheringErroredIfaces() { - enforceTetherAccessPermission(); - return mTetheringManager.getTetheringErroredIfaces(); + final TetheringManager tm = (TetheringManager) mContext.getSystemService( + Context.TETHERING_SERVICE); + + return tm.getTetheringErroredIfaces(); } @Override - public String[] getTetheredDhcpRanges() { - enforceSettingsPermission(); - return mTetheringManager.getTetheredDhcpRanges(); + @Deprecated + public String[] getTetherableUsbRegexs() { + final TetheringManager tm = (TetheringManager) mContext.getSystemService( + Context.TETHERING_SERVICE); + + return tm.getTetherableUsbRegexs(); } @Override - public boolean isTetheringSupported(String callerPkg) { - ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - return isTetheringSupported(); - } - - // if ro.tether.denied = true we default to no tethering - // gservices could set the secure setting to 1 though to enable it on a build where it - // had previously been turned off. - private boolean isTetheringSupported() { - int defaultVal = encodeBool(!mSystemProperties.get("ro.tether.denied").equals("true")); - boolean tetherSupported = toBool(Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.TETHER_SUPPORTED, defaultVal)); - boolean tetherEnabledInSettings = tetherSupported - && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING); - - // Elevate to system UID to avoid caller requiring MANAGE_USERS permission. - boolean adminUser = false; - final long token = Binder.clearCallingIdentity(); - try { - adminUser = mUserManager.isAdminUser(); - } finally { - Binder.restoreCallingIdentity(token); - } - - return tetherEnabledInSettings && adminUser - && mTetheringManager.hasTetherableConfiguration(); - } - - @Override - public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi, - String callerPkg) { - ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - if (!isTetheringSupported()) { - receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null); - return; - } - mTetheringManager.startTethering(type, receiver, showProvisioningUi); - } - - @Override - public void stopTethering(int type, String callerPkg) { - ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - mTetheringManager.stopTethering(type); - } - - /** - * Get the latest value of the tethering entitlement check. - * - * Note: Allow privileged apps who have TETHER_PRIVILEGED permission to access. If it turns - * out some such apps are observed to abuse this API, change to per-UID limits on this API - * if it's really needed. - */ - @Override - public void getLatestTetheringEntitlementResult(int type, ResultReceiver receiver, - boolean showEntitlementUi, String callerPkg) { - ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - mTetheringManager.requestLatestTetheringEntitlementResult( - type, receiver, showEntitlementUi); - } - - /** Register tethering event callback. */ - @Override - public void registerTetheringEventCallback(ITetheringEventCallback callback, - String callerPkg) { - ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - mTetheringManager.registerTetheringEventCallback(callback); - } - - /** Unregister tethering event callback. */ - @Override - public void unregisterTetheringEventCallback(ITetheringEventCallback callback, - String callerPkg) { - ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg); - mTetheringManager.unregisterTetheringEventCallback(callback); + @Deprecated + public String[] getTetherableWifiRegexs() { + final TetheringManager tm = (TetheringManager) mContext.getSystemService( + Context.TETHERING_SERVICE); + return tm.getTetherableWifiRegexs(); } // Called when we lose the default network and have no replacement yet. @@ -7050,14 +6890,6 @@ public class ConnectivityService extends IConnectivityManager.Stub // Turn airplane mode off setAirplaneMode(false); - if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) { - // Untether - String pkgName = mContext.getOpPackageName(); - for (String tether : getTetheredIfaces()) { - untether(tether, pkgName); - } - } - if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) { // Remove always-on package synchronized (mVpns) { diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt index 25028fb3ca..c4801aab5c 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt @@ -32,7 +32,6 @@ import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET import android.net.NetworkCapabilities.TRANSPORT_CELLULAR import android.net.NetworkRequest import android.net.TestNetworkStackClient -import android.net.TetheringManager import android.net.metrics.IpConnectivityLog import android.os.ConditionVariable import android.os.IBinder @@ -169,7 +168,6 @@ class ConnectivityServiceIntegrationTest { val deps = spy(ConnectivityService.Dependencies()) doReturn(networkStackClient).`when`(deps).networkStack doReturn(metricsLogger).`when`(deps).metricsLogger - doReturn(mock(TetheringManager::class.java)).`when`(deps).getTetheringManager() doReturn(mock(ProxyTracker::class.java)).`when`(deps).makeProxyTracker(any(), any()) doReturn(mock(MockableSystemProperties::class.java)).`when`(deps).systemProperties doReturn(TestNetIdManager()).`when`(deps).makeNetIdManager() diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index a24426b430..b2d363e278 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -164,7 +164,6 @@ import android.net.ProxyInfo; import android.net.ResolverParamsParcel; import android.net.RouteInfo; import android.net.SocketKeepalive; -import android.net.TetheringManager; import android.net.UidRange; import android.net.metrics.IpConnectivityLog; import android.net.shared.NetworkMonitorUtils; @@ -1133,7 +1132,6 @@ public class ConnectivityServiceTest { doReturn(new TestNetIdManager()).when(deps).makeNetIdManager(); doReturn(mNetworkStack).when(deps).getNetworkStack(); doReturn(systemProperties).when(deps).getSystemProperties(); - doReturn(mock(TetheringManager.class)).when(deps).getTetheringManager(); doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any()); doReturn(mMetricsService).when(deps).getMetricsLogger(); doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt()); From d4e7dd113d1a6426198d66be609729884b6f8610 Mon Sep 17 00:00:00 2001 From: Daulet Zhanguzin Date: Fri, 3 Jan 2020 09:46:50 +0000 Subject: [PATCH 015/229] Replace com.android.internal.util.Preconditions.checkNotNull with java.util.Objects.requireNonNull Bug: 126528330 Test: Treehugger Exempt-From-Owner-Approval: Global refactoring. Change-Id: Idb1b6ba41af3b52f3376b1157259af3c30328c4e --- .../android/server/ConnectivityService.java | 24 +++++++++---------- .../android/server/TestNetworkService.java | 21 ++++++++-------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index bb78aceb3b..deac1e3089 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -47,8 +47,6 @@ import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; -import static com.android.internal.util.Preconditions.checkNotNull; - import android.annotation.NonNull; import android.annotation.Nullable; import android.app.BroadcastOptions; @@ -904,7 +902,7 @@ public class ConnectivityService extends IConnectivityManager.Stub * @see IpConnectivityMetrics.Logger */ public IpConnectivityMetrics.Logger getMetricsLogger() { - return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class), + return Objects.requireNonNull(LocalServices.getService(IpConnectivityMetrics.Logger.class), "no IpConnectivityMetrics service"); } @@ -933,7 +931,7 @@ public class ConnectivityService extends IConnectivityManager.Stub IDnsResolver dnsresolver, IpConnectivityLog logger, INetd netd, Dependencies deps) { if (DBG) log("ConnectivityService starting up"); - mDeps = checkNotNull(deps, "missing Dependencies"); + mDeps = Objects.requireNonNull(deps, "missing Dependencies"); mSystemProperties = mDeps.getSystemProperties(); mNetIdManager = mDeps.makeNetIdManager(); @@ -962,14 +960,14 @@ public class ConnectivityService extends IConnectivityManager.Stub mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); - mContext = checkNotNull(context, "missing Context"); - mNMS = checkNotNull(netManager, "missing INetworkManagementService"); - mStatsService = checkNotNull(statsService, "missing INetworkStatsService"); - mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager"); - mPolicyManagerInternal = checkNotNull( + mContext = Objects.requireNonNull(context, "missing Context"); + mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService"); + mStatsService = Objects.requireNonNull(statsService, "missing INetworkStatsService"); + mPolicyManager = Objects.requireNonNull(policyManager, "missing INetworkPolicyManager"); + mPolicyManagerInternal = Objects.requireNonNull( LocalServices.getService(NetworkPolicyManagerInternal.class), "missing NetworkPolicyManagerInternal"); - mDnsResolver = checkNotNull(dnsresolver, "missing IDnsResolver"); + mDnsResolver = Objects.requireNonNull(dnsresolver, "missing IDnsResolver"); mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler); mNetd = netd; @@ -5195,7 +5193,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation) { - checkNotNull(operation, "PendingIntent cannot be null."); + Objects.requireNonNull(operation, "PendingIntent cannot be null."); networkCapabilities = new NetworkCapabilities(networkCapabilities); enforceNetworkRequestPermissions(networkCapabilities); enforceMeteredApnPolicy(networkCapabilities); @@ -5222,7 +5220,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void releasePendingNetworkRequest(PendingIntent operation) { - checkNotNull(operation, "PendingIntent cannot be null."); + Objects.requireNonNull(operation, "PendingIntent cannot be null."); mHandler.sendMessage(mHandler.obtainMessage(EVENT_RELEASE_NETWORK_REQUEST_WITH_INTENT, getCallingUid(), 0, operation)); } @@ -5280,7 +5278,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void pendingListenForNetwork(NetworkCapabilities networkCapabilities, PendingIntent operation) { - checkNotNull(operation, "PendingIntent cannot be null."); + Objects.requireNonNull(operation, "PendingIntent cannot be null."); if (!hasWifiNetworkListenPermission(networkCapabilities)) { enforceAccessPermission(); } diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index d19d2ddd7c..c27b0da780 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -16,8 +16,6 @@ package com.android.server; -import static com.android.internal.util.Preconditions.checkNotNull; - import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -55,6 +53,7 @@ import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.ArrayList; +import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; /** @hide */ @@ -82,9 +81,9 @@ class TestNetworkService extends ITestNetworkManager.Stub { mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper()); - mContext = checkNotNull(context, "missing Context"); - mNMS = checkNotNull(netManager, "missing INetworkManagementService"); - mNetd = checkNotNull(NetdService.getInstance(), "could not get netd instance"); + mContext = Objects.requireNonNull(context, "missing Context"); + mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService"); + mNetd = Objects.requireNonNull(NetdService.getInstance(), "could not get netd instance"); } /** @@ -96,7 +95,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { private TestNetworkInterface createInterface(boolean isTun, LinkAddress[] linkAddrs) { enforceTestNetworkPermissions(mContext); - checkNotNull(linkAddrs, "missing linkAddrs"); + Objects.requireNonNull(linkAddrs, "missing linkAddrs"); String ifacePrefix = isTun ? TEST_TUN_PREFIX : TEST_TAP_PREFIX; String iface = ifacePrefix + sTestTunIndex.getAndIncrement(); @@ -233,8 +232,8 @@ class TestNetworkService extends ITestNetworkManager.Stub { int callingUid, @NonNull IBinder binder) throws RemoteException, SocketException { - checkNotNull(looper, "missing Looper"); - checkNotNull(context, "missing Context"); + Objects.requireNonNull(looper, "missing Looper"); + Objects.requireNonNull(context, "missing Context"); // iface and binder validity checked by caller // Build network info with special testing type @@ -267,7 +266,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { // Find the currently assigned addresses, and add them to LinkProperties boolean allowIPv4 = false, allowIPv6 = false; NetworkInterface netIntf = NetworkInterface.getByName(iface); - checkNotNull(netIntf, "No such network interface found: " + netIntf); + Objects.requireNonNull(netIntf, "No such network interface found: " + netIntf); for (InterfaceAddress intfAddr : netIntf.getInterfaceAddresses()) { lp.addLinkAddress( @@ -305,8 +304,8 @@ class TestNetworkService extends ITestNetworkManager.Stub { @NonNull IBinder binder) { enforceTestNetworkPermissions(mContext); - checkNotNull(iface, "missing Iface"); - checkNotNull(binder, "missing IBinder"); + Objects.requireNonNull(iface, "missing Iface"); + Objects.requireNonNull(binder, "missing IBinder"); if (!(iface.startsWith(INetd.IPSEC_INTERFACE_PREFIX) || iface.startsWith(TEST_TUN_PREFIX))) { From 53dac33c7e92a6b20d835d872ecd433d4de6984a Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Tue, 10 Dec 2019 17:47:52 +0000 Subject: [PATCH 016/229] Use new UnsupportedAppUsage annotation. Existing annotations in libcore/ and frameworks/ will deleted after the migration. This also means that any java library that compiles @UnsupportedAppUsage requires a direct dependency on "unsupportedappusage" java_library. Bug: 145132366 Test: m && diff unsupportedappusage_index.csv Change-Id: I0c336de56bc4a041dc97ff9b7927f62f0b44b457 --- core/java/android/net/ConnectivityManager.java | 2 +- core/java/android/net/IpConfiguration.java | 3 +-- core/java/android/net/LinkAddress.java | 2 +- core/java/android/net/LinkProperties.java | 2 +- core/java/android/net/MacAddress.java | 2 +- core/java/android/net/Network.java | 2 +- core/java/android/net/NetworkAgent.java | 2 +- core/java/android/net/NetworkCapabilities.java | 2 +- core/java/android/net/NetworkInfo.java | 2 +- core/java/android/net/NetworkRequest.java | 2 +- core/java/android/net/NetworkState.java | 2 +- core/java/android/net/NetworkUtils.java | 2 +- core/java/android/net/ProxyInfo.java | 2 +- core/java/android/net/RouteInfo.java | 2 +- core/java/android/net/StaticIpConfiguration.java | 2 +- 15 files changed, 15 insertions(+), 16 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index fbd90bd9b1..6da16a82c8 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -27,8 +27,8 @@ import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; -import android.annotation.UnsupportedAppUsage; import android.app.PendingIntent; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.Intent; import android.net.IpSecManager.UdpEncapsulationSocket; diff --git a/core/java/android/net/IpConfiguration.java b/core/java/android/net/IpConfiguration.java index dddb64d8ce..23d5ff7f3a 100644 --- a/core/java/android/net/IpConfiguration.java +++ b/core/java/android/net/IpConfiguration.java @@ -20,8 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.SystemApi; -import android.annotation.UnsupportedAppUsage; -import android.net.StaticIpConfiguration; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java index 93dd2e4d77..bf8b38fc7f 100644 --- a/core/java/android/net/LinkAddress.java +++ b/core/java/android/net/LinkAddress.java @@ -30,7 +30,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index ed509cb3da..a825b4a85d 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -20,7 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java index 87295142be..74c9aac05b 100644 --- a/core/java/android/net/MacAddress.java +++ b/core/java/android/net/MacAddress.java @@ -19,7 +19,7 @@ package android.net; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.net.wifi.WifiInfo; import android.os.Parcel; import android.os.Parcelable; diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index c6c73fe5b8..c5681cb6d7 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -19,7 +19,7 @@ package android.net; import android.annotation.NonNull; import android.annotation.SystemApi; import android.annotation.TestApi; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.system.ErrnoException; diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index ff4bf2d347..60bd5730f8 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -17,7 +17,7 @@ package android.net; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Build; import android.os.Bundle; diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 4cee5f3e1f..33c39d4898 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -21,7 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.net.ConnectivityManager.NetworkCallback; import android.os.Build; import android.os.Parcel; diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java index 92f105f771..d0c5363165 100644 --- a/core/java/android/net/NetworkInfo.java +++ b/core/java/android/net/NetworkInfo.java @@ -17,7 +17,7 @@ package android.net; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index 2992127354..431773dc26 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -20,7 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.net.NetworkCapabilities.NetCapability; import android.net.NetworkCapabilities.Transport; import android.os.Build; diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java index 292cf50ac4..e449615287 100644 --- a/core/java/android/net/NetworkState.java +++ b/core/java/android/net/NetworkState.java @@ -16,7 +16,7 @@ package android.net; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index d0f54b4c7f..44ac901e21 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -20,7 +20,7 @@ import static android.system.OsConstants.AF_INET; import static android.system.OsConstants.AF_INET6; import android.annotation.NonNull; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.net.shared.Inet4AddressUtils; import android.os.Build; import android.system.ErrnoException; diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java index 9d92db4486..ffe9ae9521 100644 --- a/core/java/android/net/ProxyInfo.java +++ b/core/java/android/net/ProxyInfo.java @@ -18,7 +18,7 @@ package android.net; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index 52d3fc48a3..ea6002ca29 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -21,7 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java index 990c114228..f24a9bd530 100644 --- a/core/java/android/net/StaticIpConfiguration.java +++ b/core/java/android/net/StaticIpConfiguration.java @@ -20,7 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; -import android.annotation.UnsupportedAppUsage; +import android.compat.annotation.UnsupportedAppUsage; import android.net.shared.InetAddressUtils; import android.os.Parcel; import android.os.Parcelable; From 7879adc8b13fa17876c3f8c525773df1e16f7937 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Wed, 8 Jan 2020 11:08:10 +0800 Subject: [PATCH 017/229] Expose clearCapabilities for mainline module Support telephony mainline module usage. Bug: 138306002 Test: Build and make api-stubs-docs-update-current-api Change-Id: I0a462da4e87cae2c7d4a9b9a92de061a086c5752 --- core/java/android/net/NetworkRequest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index 431773dc26..9731f3ca18 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -247,9 +247,8 @@ public class NetworkRequest implements Parcelable { * removing even the capabilities that are set by default when the object is constructed. * * @return The builder to facilitate chaining. - * @hide */ - @UnsupportedAppUsage + @NonNull public Builder clearCapabilities() { mNetworkCapabilities.clearAll(); return this; From c58ecd5f33249c733753880adc3bb87d36d97d5c Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Sun, 12 Jan 2020 20:27:32 +0900 Subject: [PATCH 018/229] Make NetworkAgent stop subclassing Handler. Subclassing Handler is not appropriate for a system API because it is an implementation detail and allows users of this class to post messages to the handler in ways that allow inappropriate access to internals that aren't part of the API contract. Also fix some lint errors. Test: builds Bug: 138306002 Change-Id: I79478ceff6bbcae879d1025098d177de0d15dbee --- core/java/android/net/NetworkAgent.java | 225 ++++++++++++------------ 1 file changed, 117 insertions(+), 108 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 5f6cc6eced..d71d215e34 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -43,11 +43,12 @@ import java.util.concurrent.atomic.AtomicBoolean; * * @hide */ -public abstract class NetworkAgent extends Handler { +public abstract class NetworkAgent { // Guaranteed to be valid (not NETID_UNSET), otherwise registerNetworkAgent() would have thrown // an exception. public final int netId; + private final Handler mHandler; private volatile AsyncChannel mAsyncChannel; private final String LOG_TAG; private static final boolean DBG = true; @@ -234,7 +235,7 @@ public abstract class NetworkAgent extends Handler { public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc, int providerId) { - super(looper); + mHandler = new NetworkAgentHandler(looper); LOG_TAG = logTag; mContext = context; mProviderId = providerId; @@ -245,116 +246,124 @@ public abstract class NetworkAgent extends Handler { if (VDBG) log("Registering NetworkAgent"); ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE); - netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni), - new LinkProperties(lp), new NetworkCapabilities(nc), score, misc, providerId); + netId = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(ni), + new LinkProperties(lp), new NetworkCapabilities(nc), score, misc, + providerId); } - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { - if (mAsyncChannel != null) { - log("Received new connection while already connected!"); - } else { - if (VDBG) log("NetworkAgent fully connected"); - AsyncChannel ac = new AsyncChannel(); - ac.connected(null, this, msg.replyTo); - ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, - AsyncChannel.STATUS_SUCCESSFUL); - synchronized (mPreConnectedQueue) { - mAsyncChannel = ac; - for (Message m : mPreConnectedQueue) { - ac.sendMessage(m); - } - mPreConnectedQueue.clear(); - } - } - break; - } - case AsyncChannel.CMD_CHANNEL_DISCONNECT: { - if (VDBG) log("CMD_CHANNEL_DISCONNECT"); - if (mAsyncChannel != null) mAsyncChannel.disconnect(); - break; - } - case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { - if (DBG) log("NetworkAgent channel lost"); - // let the client know CS is done with us. - unwanted(); - synchronized (mPreConnectedQueue) { - mAsyncChannel = null; - } - break; - } - case CMD_SUSPECT_BAD: { - log("Unhandled Message " + msg); - break; - } - case CMD_REQUEST_BANDWIDTH_UPDATE: { - long currentTimeMs = System.currentTimeMillis(); - if (VDBG) { - log("CMD_REQUEST_BANDWIDTH_UPDATE request received."); - } - if (currentTimeMs >= (mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS)) { - mPollLceScheduled = false; - if (mPollLcePending.getAndSet(true) == false) { - pollLceData(); - } - } else { - // deliver the request at a later time rather than discard it completely. - if (!mPollLceScheduled) { - long waitTime = mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS - - currentTimeMs + 1; - mPollLceScheduled = sendEmptyMessageDelayed( - CMD_REQUEST_BANDWIDTH_UPDATE, waitTime); - } - } - break; - } - case CMD_REPORT_NETWORK_STATUS: { - String redirectUrl = ((Bundle)msg.obj).getString(REDIRECT_URL_KEY); - if (VDBG) { - log("CMD_REPORT_NETWORK_STATUS(" + - (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") + redirectUrl); - } - networkStatus(msg.arg1, redirectUrl); - break; - } - case CMD_SAVE_ACCEPT_UNVALIDATED: { - saveAcceptUnvalidated(msg.arg1 != 0); - break; - } - case CMD_START_SOCKET_KEEPALIVE: { - startSocketKeepalive(msg); - break; - } - case CMD_STOP_SOCKET_KEEPALIVE: { - stopSocketKeepalive(msg); - break; - } + private class NetworkAgentHandler extends Handler { + NetworkAgentHandler(Looper looper) { + super(looper); + } - case CMD_SET_SIGNAL_STRENGTH_THRESHOLDS: { - ArrayList thresholds = - ((Bundle) msg.obj).getIntegerArrayList("thresholds"); - // TODO: Change signal strength thresholds API to use an ArrayList - // rather than convert to int[]. - int[] intThresholds = new int[(thresholds != null) ? thresholds.size() : 0]; - for (int i = 0; i < intThresholds.length; i++) { - intThresholds[i] = thresholds.get(i); + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { + if (mAsyncChannel != null) { + log("Received new connection while already connected!"); + } else { + if (VDBG) log("NetworkAgent fully connected"); + AsyncChannel ac = new AsyncChannel(); + ac.connected(null, this, msg.replyTo); + ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, + AsyncChannel.STATUS_SUCCESSFUL); + synchronized (mPreConnectedQueue) { + mAsyncChannel = ac; + for (Message m : mPreConnectedQueue) { + ac.sendMessage(m); + } + mPreConnectedQueue.clear(); + } + } + break; + } + case AsyncChannel.CMD_CHANNEL_DISCONNECT: { + if (VDBG) log("CMD_CHANNEL_DISCONNECT"); + if (mAsyncChannel != null) mAsyncChannel.disconnect(); + break; + } + case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { + if (DBG) log("NetworkAgent channel lost"); + // let the client know CS is done with us. + unwanted(); + synchronized (mPreConnectedQueue) { + mAsyncChannel = null; + } + break; + } + case CMD_SUSPECT_BAD: { + log("Unhandled Message " + msg); + break; + } + case CMD_REQUEST_BANDWIDTH_UPDATE: { + long currentTimeMs = System.currentTimeMillis(); + if (VDBG) { + log("CMD_REQUEST_BANDWIDTH_UPDATE request received."); + } + if (currentTimeMs >= (mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS)) { + mPollLceScheduled = false; + if (!mPollLcePending.getAndSet(true)) { + pollLceData(); + } + } else { + // deliver the request at a later time rather than discard it completely. + if (!mPollLceScheduled) { + long waitTime = mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS + - currentTimeMs + 1; + mPollLceScheduled = sendEmptyMessageDelayed( + CMD_REQUEST_BANDWIDTH_UPDATE, waitTime); + } + } + break; + } + case CMD_REPORT_NETWORK_STATUS: { + String redirectUrl = ((Bundle) msg.obj).getString(REDIRECT_URL_KEY); + if (VDBG) { + log("CMD_REPORT_NETWORK_STATUS(" + + (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") + + redirectUrl); + } + networkStatus(msg.arg1, redirectUrl); + break; + } + case CMD_SAVE_ACCEPT_UNVALIDATED: { + saveAcceptUnvalidated(msg.arg1 != 0); + break; + } + case CMD_START_SOCKET_KEEPALIVE: { + startSocketKeepalive(msg); + break; + } + case CMD_STOP_SOCKET_KEEPALIVE: { + stopSocketKeepalive(msg); + break; + } + + case CMD_SET_SIGNAL_STRENGTH_THRESHOLDS: { + ArrayList thresholds = + ((Bundle) msg.obj).getIntegerArrayList("thresholds"); + // TODO: Change signal strength thresholds API to use an ArrayList + // rather than convert to int[]. + int[] intThresholds = new int[(thresholds != null) ? thresholds.size() : 0]; + for (int i = 0; i < intThresholds.length; i++) { + intThresholds[i] = thresholds.get(i); + } + setSignalStrengthThresholds(intThresholds); + break; + } + case CMD_PREVENT_AUTOMATIC_RECONNECT: { + preventAutomaticReconnect(); + break; + } + case CMD_ADD_KEEPALIVE_PACKET_FILTER: { + addKeepalivePacketFilter(msg); + break; + } + case CMD_REMOVE_KEEPALIVE_PACKET_FILTER: { + removeKeepalivePacketFilter(msg); + break; } - setSignalStrengthThresholds(intThresholds); - break; - } - case CMD_PREVENT_AUTOMATIC_RECONNECT: { - preventAutomaticReconnect(); - break; - } - case CMD_ADD_KEEPALIVE_PACKET_FILTER: { - addKeepalivePacketFilter(msg); - break; - } - case CMD_REMOVE_KEEPALIVE_PACKET_FILTER: { - removeKeepalivePacketFilter(msg); - break; } } } From 8dd13a8109cfa8e8693f10ba802a1b50b29c43fb Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Sun, 12 Jan 2020 22:28:37 +0900 Subject: [PATCH 019/229] Rename NetworkMisc to NetworkAgentConfig. NetworkMisc is not really an appropriate name for a system API. Bug: 138306002 Test: builds, boots, wifi works, telephony works Test: atest FrameworksNetTests FrameworksWifiTests FrameworksTelephonyTests Change-Id: I621cfbe165996c67b201ca2dd2f95a5ab9af10ee --- .../java/android/net/ConnectivityManager.java | 8 +-- .../android/net/IConnectivityManager.aidl | 5 +- core/java/android/net/NetworkAgent.java | 8 +-- ...tworkMisc.java => NetworkAgentConfig.java} | 47 ++++++++------- .../android/server/ConnectivityService.java | 60 ++++++++++--------- .../server/connectivity/Nat464Xlat.java | 3 +- .../server/connectivity/NetworkAgentInfo.java | 24 ++++---- .../android/server/NetworkAgentWrapper.java | 4 +- .../connectivity/LingerMonitorTest.java | 6 +- .../server/connectivity/Nat464XlatTest.java | 14 ++--- 10 files changed, 94 insertions(+), 85 deletions(-) rename core/java/android/net/{NetworkMisc.java => NetworkAgentConfig.java} (72%) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 8317df5597..4bf3e90569 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3173,8 +3173,8 @@ public class ConnectivityManager { */ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, - NetworkCapabilities nc, int score, NetworkMisc misc) { - return registerNetworkAgent(messenger, ni, lp, nc, score, misc, NetworkProvider.ID_NONE); + NetworkCapabilities nc, int score, NetworkAgentConfig config) { + return registerNetworkAgent(messenger, ni, lp, nc, score, config, NetworkProvider.ID_NONE); } /** @@ -3184,9 +3184,9 @@ public class ConnectivityManager { */ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, - NetworkCapabilities nc, int score, NetworkMisc misc, int providerId) { + NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) { try { - return mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc, providerId); + return mService.registerNetworkAgent(messenger, ni, lp, nc, score, config, providerId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index e6a0379ff6..7691beba32 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -20,9 +20,9 @@ import android.app.PendingIntent; import android.net.ConnectionInfo; import android.net.LinkProperties; import android.net.Network; +import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkInfo; -import android.net.NetworkMisc; import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; import android.net.NetworkState; @@ -153,7 +153,8 @@ interface IConnectivityManager void declareNetworkRequestUnfulfillable(in NetworkRequest request); int registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp, - in NetworkCapabilities nc, int score, in NetworkMisc misc, in int factorySerialNumber); + in NetworkCapabilities nc, int score, in NetworkAgentConfig config, + in int factorySerialNumber); NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, in Messenger messenger, int timeoutSec, in IBinder binder, int legacy); diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index d71d215e34..fc72eecd41 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -223,8 +223,8 @@ public abstract class NetworkAgent { this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE); } public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, - NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { - this(looper, context, logTag, ni, nc, lp, score, misc, NetworkProvider.ID_NONE); + NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) { + this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE); } public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, @@ -233,7 +233,7 @@ public abstract class NetworkAgent { } public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, - NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc, + NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, int providerId) { mHandler = new NetworkAgentHandler(looper); LOG_TAG = logTag; @@ -247,7 +247,7 @@ public abstract class NetworkAgent { ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE); netId = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(ni), - new LinkProperties(lp), new NetworkCapabilities(nc), score, misc, + new LinkProperties(lp), new NetworkCapabilities(nc), score, config, providerId); } diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkAgentConfig.java similarity index 72% rename from core/java/android/net/NetworkMisc.java rename to core/java/android/net/NetworkAgentConfig.java index 4ad52d5aa1..3a383a44cd 100644 --- a/core/java/android/net/NetworkMisc.java +++ b/core/java/android/net/NetworkAgentConfig.java @@ -16,6 +16,8 @@ package android.net; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; @@ -26,7 +28,7 @@ import android.os.Parcelable; * * @hide */ -public class NetworkMisc implements Parcelable { +public class NetworkAgentConfig implements Parcelable { /** * If the {@link Network} is a VPN, whether apps are allowed to bypass the @@ -83,17 +85,17 @@ public class NetworkMisc implements Parcelable { */ public boolean hasShownBroken; - public NetworkMisc() { + public NetworkAgentConfig() { } - public NetworkMisc(NetworkMisc nm) { - if (nm != null) { - allowBypass = nm.allowBypass; - explicitlySelected = nm.explicitlySelected; - acceptUnvalidated = nm.acceptUnvalidated; - subscriberId = nm.subscriberId; - provisioningNotificationDisabled = nm.provisioningNotificationDisabled; - skip464xlat = nm.skip464xlat; + public NetworkAgentConfig(@Nullable NetworkAgentConfig nac) { + if (nac != null) { + allowBypass = nac.allowBypass; + explicitlySelected = nac.explicitlySelected; + acceptUnvalidated = nac.acceptUnvalidated; + subscriberId = nac.subscriberId; + provisioningNotificationDisabled = nac.provisioningNotificationDisabled; + skip464xlat = nac.skip464xlat; } } @@ -112,22 +114,23 @@ public class NetworkMisc implements Parcelable { out.writeInt(skip464xlat ? 1 : 0); } - public static final @android.annotation.NonNull Creator CREATOR = new Creator() { + public static final @NonNull Creator CREATOR = + new Creator() { @Override - public NetworkMisc createFromParcel(Parcel in) { - NetworkMisc networkMisc = new NetworkMisc(); - networkMisc.allowBypass = in.readInt() != 0; - networkMisc.explicitlySelected = in.readInt() != 0; - networkMisc.acceptUnvalidated = in.readInt() != 0; - networkMisc.subscriberId = in.readString(); - networkMisc.provisioningNotificationDisabled = in.readInt() != 0; - networkMisc.skip464xlat = in.readInt() != 0; - return networkMisc; + public NetworkAgentConfig createFromParcel(Parcel in) { + NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig(); + networkAgentConfig.allowBypass = in.readInt() != 0; + networkAgentConfig.explicitlySelected = in.readInt() != 0; + networkAgentConfig.acceptUnvalidated = in.readInt() != 0; + networkAgentConfig.subscriberId = in.readString(); + networkAgentConfig.provisioningNotificationDisabled = in.readInt() != 0; + networkAgentConfig.skip464xlat = in.readInt() != 0; + return networkAgentConfig; } @Override - public NetworkMisc[] newArray(int size) { - return new NetworkMisc[size]; + public NetworkAgentConfig[] newArray(int size) { + return new NetworkAgentConfig[size]; } }; } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index e5fdd8a908..26c12c141e 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -84,12 +84,12 @@ import android.net.MatchAllNetworkSpecifier; import android.net.NattSocketKeepalive; import android.net.Network; import android.net.NetworkAgent; +import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkConfig; import android.net.NetworkFactory; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; -import android.net.NetworkMisc; import android.net.NetworkMonitorManager; import android.net.NetworkPolicyManager; import android.net.NetworkProvider; @@ -2631,8 +2631,8 @@ public class ConnectivityService extends IConnectivityManager.Stub if (nai.everConnected) { loge("ERROR: cannot call explicitlySelected on already-connected network"); } - nai.networkMisc.explicitlySelected = toBool(msg.arg1); - nai.networkMisc.acceptUnvalidated = toBool(msg.arg1) && toBool(msg.arg2); + nai.networkAgentConfig.explicitlySelected = toBool(msg.arg1); + nai.networkAgentConfig.acceptUnvalidated = toBool(msg.arg1) && toBool(msg.arg2); // Mark the network as temporarily accepting partial connectivity so that it // will be validated (and possibly become default) even if it only provides // partial internet access. Note that if user connects to partial connectivity @@ -2640,7 +2640,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // out of wifi coverage) and if the same wifi is available again, the device // will auto connect to this wifi even though the wifi has "no internet". // TODO: Evaluate using a separate setting in IpMemoryStore. - nai.networkMisc.acceptPartialConnectivity = toBool(msg.arg2); + nai.networkAgentConfig.acceptPartialConnectivity = toBool(msg.arg2); break; } case NetworkAgent.EVENT_SOCKET_KEEPALIVE: { @@ -2672,10 +2672,10 @@ public class ConnectivityService extends IConnectivityManager.Stub } // Only show the notification when the private DNS is broken and the // PRIVATE_DNS_BROKEN notification hasn't shown since last valid. - if (privateDnsBroken && !nai.networkMisc.hasShownBroken) { + if (privateDnsBroken && !nai.networkAgentConfig.hasShownBroken) { showNetworkNotification(nai, NotificationType.PRIVATE_DNS_BROKEN); } - nai.networkMisc.hasShownBroken = privateDnsBroken; + nai.networkAgentConfig.hasShownBroken = privateDnsBroken; } else if (nai.networkCapabilities.isPrivateDnsBroken()) { // If probePrivateDnsCompleted is false but nai.networkCapabilities says // private DNS is broken, it means this network is being reevaluated. @@ -2685,7 +2685,7 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.networkCapabilities.setPrivateDnsBroken(false); final int oldScore = nai.getCurrentScore(); updateCapabilities(oldScore, nai, nai.networkCapabilities); - nai.networkMisc.hasShownBroken = false; + nai.networkAgentConfig.hasShownBroken = false; } break; } @@ -2744,7 +2744,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // If network becomes valid, the hasShownBroken should be reset for // that network so that the notification will be fired when the private // DNS is broken again. - nai.networkMisc.hasShownBroken = false; + nai.networkAgentConfig.hasShownBroken = false; } } else if (partialConnectivityChanged) { updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); @@ -2803,9 +2803,10 @@ public class ConnectivityService extends IConnectivityManager.Stub loge("EVENT_PROVISIONING_NOTIFICATION from unknown NetworkMonitor"); break; } - if (!nai.networkMisc.provisioningNotificationDisabled) { + if (!nai.networkAgentConfig.provisioningNotificationDisabled) { mNotifier.showNotification(netId, NotificationType.SIGN_IN, nai, null, - (PendingIntent) msg.obj, nai.networkMisc.explicitlySelected); + (PendingIntent) msg.obj, + nai.networkAgentConfig.explicitlySelected); } } break; @@ -3170,8 +3171,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // This should never fail. Specifying an already in use NetID will cause failure. if (networkAgent.isVPN()) { mNetd.networkCreateVpn(networkAgent.network.netId, - (networkAgent.networkMisc == null - || !networkAgent.networkMisc.allowBypass)); + (networkAgent.networkAgentConfig == null + || !networkAgent.networkAgentConfig.allowBypass)); } else { mNetd.networkCreatePhysical(networkAgent.network.netId, getNetworkPermission(networkAgent.networkCapabilities)); @@ -3471,16 +3472,16 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } - if (!nai.networkMisc.explicitlySelected) { + if (!nai.networkAgentConfig.explicitlySelected) { Slog.wtf(TAG, "BUG: setAcceptUnvalidated non non-explicitly selected network"); } - if (accept != nai.networkMisc.acceptUnvalidated) { - nai.networkMisc.acceptUnvalidated = accept; + if (accept != nai.networkAgentConfig.acceptUnvalidated) { + nai.networkAgentConfig.acceptUnvalidated = accept; // If network becomes partial connectivity and user already accepted to use this // network, we should respect the user's option and don't need to popup the // PARTIAL_CONNECTIVITY notification to user again. - nai.networkMisc.acceptPartialConnectivity = accept; + nai.networkAgentConfig.acceptPartialConnectivity = accept; rematchAllNetworksAndRequests(); sendUpdatedScoreToFactories(nai); } @@ -3517,8 +3518,8 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } - if (accept != nai.networkMisc.acceptPartialConnectivity) { - nai.networkMisc.acceptPartialConnectivity = accept; + if (accept != nai.networkAgentConfig.acceptPartialConnectivity) { + nai.networkAgentConfig.acceptPartialConnectivity = accept; } // TODO: Use the current design or save the user choice into IpMemoryStore. @@ -3728,7 +3729,7 @@ public class ConnectivityService extends IConnectivityManager.Stub action = ConnectivityManager.ACTION_PROMPT_PARTIAL_CONNECTIVITY; // Don't bother the user with a high-priority notification if the network was not // explicitly selected by the user. - highPriority = nai.networkMisc.explicitlySelected; + highPriority = nai.networkAgentConfig.explicitlySelected; break; default: Slog.wtf(TAG, "Unknown notification type " + type); @@ -3761,14 +3762,15 @@ public class ConnectivityService extends IConnectivityManager.Stub // automatically connects to a network that has partial Internet access, the user will // always be able to use it, either because they've already chosen "don't ask again" or // because we have prompt them. - if (nai.partialConnectivity && !nai.networkMisc.acceptPartialConnectivity) { + if (nai.partialConnectivity && !nai.networkAgentConfig.acceptPartialConnectivity) { return true; } // If a network has no Internet access, only prompt if the network was explicitly selected // and if the user has not already told us to use the network regardless of whether it // validated or not. - if (nai.networkMisc.explicitlySelected && !nai.networkMisc.acceptUnvalidated) { + if (nai.networkAgentConfig.explicitlySelected + && !nai.networkAgentConfig.acceptUnvalidated) { return true; } @@ -5490,9 +5492,9 @@ public class ConnectivityService extends IConnectivityManager.Stub // tree. public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - int currentScore, NetworkMisc networkMisc) { + int currentScore, NetworkAgentConfig networkAgentConfig) { return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities, - currentScore, networkMisc, NetworkProvider.ID_NONE); + currentScore, networkAgentConfig, NetworkProvider.ID_NONE); } /** @@ -5507,12 +5509,12 @@ public class ConnectivityService extends IConnectivityManager.Stub * later : see {@link #updateCapabilities}. * @param currentScore the initial score of the network. See * {@link NetworkAgentInfo#getCurrentScore}. - * @param networkMisc metadata about the network. This is never updated. + * @param networkAgentConfig metadata about the network. This is never updated. * @param providerId the ID of the provider owning this NetworkAgent. */ public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - int currentScore, NetworkMisc networkMisc, int providerId) { + int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { enforceNetworkFactoryPermission(); LinkProperties lp = new LinkProperties(linkProperties); @@ -5524,8 +5526,8 @@ public class ConnectivityService extends IConnectivityManager.Stub ns.putIntExtension(NetworkScore.LEGACY_SCORE, currentScore); final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc, - ns, mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, - mDnsResolver, mNMS, providerId); + ns, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), this, + mNetd, mDnsResolver, mNMS, providerId); // Make sure the network capabilities reflect what the agent info says. nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); final String extraInfo = networkInfo.getExtraInfo(); @@ -5946,7 +5948,7 @@ public class ConnectivityService extends IConnectivityManager.Stub LinkProperties lp) { if (nc == null || lp == null) return false; return nai.isVPN() - && !nai.networkMisc.allowBypass + && !nai.networkAgentConfig.allowBypass && nc.getEstablishingVpnAppUid() != Process.SYSTEM_UID && lp.getInterfaceName() != null && (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute()); @@ -6637,7 +6639,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // command must be sent after updating LinkProperties to maximize chances of // NetworkMonitor seeing the correct LinkProperties when starting. // TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call. - if (networkAgent.networkMisc.acceptPartialConnectivity) { + if (networkAgent.networkAgentConfig.acceptPartialConnectivity) { networkAgent.networkMonitor().setAcceptPartialConnectivity(); } networkAgent.networkMonitor().notifyNetworkConnected( diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index aea6d8d243..f636d67c3d 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -116,7 +116,8 @@ public class Nat464Xlat extends BaseNetworkObserver { && !lp.hasIpv4Address(); // If the network tells us it doesn't use clat, respect that. - final boolean skip464xlat = (nai.netMisc() != null) && nai.netMisc().skip464xlat; + final boolean skip464xlat = (nai.netAgentConfig() != null) + && nai.netAgentConfig().skip464xlat; return supported && connected && isIpv6OnlyNetwork && !skip464xlat; } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 5e085ca293..c1ab55106a 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -23,9 +23,9 @@ import android.net.INetd; import android.net.INetworkMonitor; import android.net.LinkProperties; import android.net.Network; +import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkInfo; -import android.net.NetworkMisc; import android.net.NetworkMonitorManager; import android.net.NetworkRequest; import android.net.NetworkScore; @@ -127,7 +127,7 @@ public class NetworkAgentInfo implements Comparable { // This should only be modified by ConnectivityService, via setNetworkCapabilities(). // TODO: make this private with a getter. public NetworkCapabilities networkCapabilities; - public final NetworkMisc networkMisc; + public final NetworkAgentConfig networkAgentConfig; // Indicates if netd has been told to create this Network. From this point on the appropriate // routing rules are setup and routes are added so packets can begin flowing over the Network. // This is a sticky bit; once set it is never cleared. @@ -261,7 +261,7 @@ public class NetworkAgentInfo implements Comparable { public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info, LinkProperties lp, NetworkCapabilities nc, @NonNull NetworkScore ns, Context context, - Handler handler, NetworkMisc misc, ConnectivityService connService, INetd netd, + Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd, IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) { this.messenger = messenger; asyncChannel = ac; @@ -274,7 +274,7 @@ public class NetworkAgentInfo implements Comparable { mConnService = connService; mContext = context; mHandler = handler; - networkMisc = misc; + networkAgentConfig = config; this.factorySerialNumber = factorySerialNumber; } @@ -309,8 +309,8 @@ public class NetworkAgentInfo implements Comparable { return mConnService; } - public NetworkMisc netMisc() { - return networkMisc; + public NetworkAgentConfig netAgentConfig() { + return networkAgentConfig; } public Handler handler() { @@ -487,7 +487,8 @@ public class NetworkAgentInfo implements Comparable { // selected and we're trying to see what its score could be. This ensures that we don't tear // down an explicitly selected network before the user gets a chance to prefer it when // a higher-scoring network (e.g., Ethernet) is available. - if (networkMisc.explicitlySelected && (networkMisc.acceptUnvalidated || pretendValidated)) { + if (networkAgentConfig.explicitlySelected + && (networkAgentConfig.acceptUnvalidated || pretendValidated)) { return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE; } @@ -533,7 +534,8 @@ public class NetworkAgentInfo implements Comparable { synchronized (this) { // Network objects are outwardly immutable so there is no point in duplicating. // Duplicating also precludes sharing socket factories and connection pools. - final String subscriberId = (networkMisc != null) ? networkMisc.subscriberId : null; + final String subscriberId = (networkAgentConfig != null) + ? networkAgentConfig.subscriberId : null; return new NetworkState(new NetworkInfo(networkInfo), new LinkProperties(linkProperties), new NetworkCapabilities(networkCapabilities), network, subscriberId, null); @@ -641,13 +643,13 @@ public class NetworkAgentInfo implements Comparable { + "nc{" + networkCapabilities + "} Score{" + getCurrentScore() + "} " + "everValidated{" + everValidated + "} lastValidated{" + lastValidated + "} " + "created{" + created + "} lingering{" + isLingering() + "} " - + "explicitlySelected{" + networkMisc.explicitlySelected + "} " - + "acceptUnvalidated{" + networkMisc.acceptUnvalidated + "} " + + "explicitlySelected{" + networkAgentConfig.explicitlySelected + "} " + + "acceptUnvalidated{" + networkAgentConfig.acceptUnvalidated + "} " + "everCaptivePortalDetected{" + everCaptivePortalDetected + "} " + "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} " + "captivePortalValidationPending{" + captivePortalValidationPending + "} " + "partialConnectivity{" + partialConnectivity + "} " - + "acceptPartialConnectivity{" + networkMisc.acceptPartialConnectivity + "} " + + "acceptPartialConnectivity{" + networkAgentConfig.acceptPartialConnectivity + "} " + "clat{" + clatd + "} " + "}"; } diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index 18474a83b3..0ab5c97d31 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -35,9 +35,9 @@ import android.net.ConnectivityManager; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkAgent; +import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkInfo; -import android.net.NetworkMisc; import android.net.NetworkProvider; import android.net.NetworkSpecifier; import android.net.SocketKeepalive; @@ -114,7 +114,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp) { super(wrapper.mHandlerThread.getLooper(), wrapper.mContext, wrapper.mLogTag, wrapper.mNetworkInfo, wrapper.mNetworkCapabilities, lp, wrapper.mScore, - new NetworkMisc(), NetworkProvider.ID_NONE); + new NetworkAgentConfig(), NetworkProvider.ID_NONE); mWrapper = wrapper; } diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index 82cb1932d2..9e915aec68 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -35,9 +35,9 @@ import android.net.ConnectivityManager; import android.net.IDnsResolver; import android.net.INetd; import android.net.Network; +import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkInfo; -import android.net.NetworkMisc; import android.net.NetworkProvider; import android.net.NetworkScore; import android.os.INetworkManagementService; @@ -75,7 +75,7 @@ public class LingerMonitorTest { @Mock INetd mNetd; @Mock INetworkManagementService mNMS; @Mock Context mCtx; - @Mock NetworkMisc mMisc; + @Mock NetworkAgentConfig mAgentConfig; @Mock NetworkNotificationManager mNotifier; @Mock Resources mResources; @@ -358,7 +358,7 @@ public class LingerMonitorTest { NetworkScore ns = new NetworkScore(); ns.putIntExtension(NetworkScore.LEGACY_SCORE, 50); NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null, - caps, ns, mCtx, null, mMisc, mConnService, mNetd, mDnsResolver, mNMS, + caps, ns, mCtx, null, mAgentConfig, mConnService, mNetd, mDnsResolver, mNMS, NetworkProvider.ID_NONE); nai.everValidated = true; return nai; diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java index b709af1a02..cf70f5d499 100644 --- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java +++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java @@ -33,8 +33,8 @@ import android.net.InterfaceConfiguration; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; +import android.net.NetworkAgentConfig; import android.net.NetworkInfo; -import android.net.NetworkMisc; import android.os.Handler; import android.os.INetworkManagementService; import android.os.test.TestLooper; @@ -63,7 +63,7 @@ public class Nat464XlatTest { static final int NETID = 42; @Mock ConnectivityService mConnectivity; - @Mock NetworkMisc mMisc; + @Mock NetworkAgentConfig mAgentConfig; @Mock IDnsResolver mDnsResolver; @Mock INetd mNetd; @Mock INetworkManagementService mNms; @@ -93,7 +93,7 @@ public class Nat464XlatTest { mNai.networkInfo = new NetworkInfo(null); mNai.networkInfo.setType(ConnectivityManager.TYPE_WIFI); when(mNai.connService()).thenReturn(mConnectivity); - when(mNai.netMisc()).thenReturn(mMisc); + when(mNai.netAgentConfig()).thenReturn(mAgentConfig); when(mNai.handler()).thenReturn(mHandler); when(mNms.getInterfaceConfig(eq(STACKED_IFACE))).thenReturn(mConfig); @@ -104,7 +104,7 @@ public class Nat464XlatTest { String msg = String.format("requiresClat expected %b for type=%d state=%s skip=%b " + "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(), nai.networkInfo.getDetailedState(), - mMisc.skip464xlat, nai.linkProperties.getNat64Prefix(), + mAgentConfig.skip464xlat, nai.linkProperties.getNat64Prefix(), nai.linkProperties.getLinkAddresses()); assertEquals(msg, expected, Nat464Xlat.requiresClat(nai)); } @@ -113,7 +113,7 @@ public class Nat464XlatTest { String msg = String.format("shouldStartClat expected %b for type=%d state=%s skip=%b " + "nat64Prefix=%s addresses=%s", expected, nai.networkInfo.getType(), nai.networkInfo.getDetailedState(), - mMisc.skip464xlat, nai.linkProperties.getNat64Prefix(), + mAgentConfig.skip464xlat, nai.linkProperties.getNat64Prefix(), nai.linkProperties.getLinkAddresses()); assertEquals(msg, expected, Nat464Xlat.shouldStartClat(nai)); } @@ -151,11 +151,11 @@ public class Nat464XlatTest { assertRequiresClat(true, mNai); assertShouldStartClat(true, mNai); - mMisc.skip464xlat = true; + mAgentConfig.skip464xlat = true; assertRequiresClat(false, mNai); assertShouldStartClat(false, mNai); - mMisc.skip464xlat = false; + mAgentConfig.skip464xlat = false; assertRequiresClat(true, mNai); assertShouldStartClat(true, mNai); From 5b2e000f6dedf0bb5e836deba91161aaff6692c6 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 13 Jan 2020 23:36:43 +0900 Subject: [PATCH 020/229] Add a Builder to NetworkAgentConfig, and make it SystemApi. Currently, only support the three elements in the config that are known to be used. Bug: 138306002 Test: builds, boots Test: atest FrameworksTelephonyTests Change-Id: I1d231ec2ddcff97c039bcbc815a39c1d3e26c410 --- core/java/android/net/NetworkAgentConfig.java | 104 +++++++++++++++++- .../connectivity/LingerMonitorTest.java | 4 +- .../server/connectivity/Nat464XlatTest.java | 2 +- 3 files changed, 101 insertions(+), 9 deletions(-) diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java index 3a383a44cd..abc6b67efb 100644 --- a/core/java/android/net/NetworkAgentConfig.java +++ b/core/java/android/net/NetworkAgentConfig.java @@ -18,22 +18,27 @@ package android.net; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; /** - * A grab-bag of information (metadata, policies, properties, etc) about a - * {@link Network}. Since this contains PII, it should not be sent outside the - * system. + * Allows a network transport to provide the system with policy and configuration information about + * a particular network when registering a {@link NetworkAgent}. This information cannot change once + * the agent is registered. * * @hide */ -public class NetworkAgentConfig implements Parcelable { +@SystemApi +public final class NetworkAgentConfig implements Parcelable { /** * If the {@link Network} is a VPN, whether apps are allowed to bypass the * VPN. This is set by a {@link VpnService} and used by * {@link ConnectivityManager} when creating a VPN. + * + * @hide */ public boolean allowBypass; @@ -43,6 +48,8 @@ public class NetworkAgentConfig implements Parcelable { * ap in the wifi settings to trigger a connection is explicit. A 3rd party app asking to * connect to a particular access point is also explicit, though this may change in the future * as we want apps to use the multinetwork apis. + * + * @hide */ public boolean explicitlySelected; @@ -50,12 +57,16 @@ public class NetworkAgentConfig implements Parcelable { * Set if the user desires to use this network even if it is unvalidated. This field has meaning * only if {@link explicitlySelected} is true. If it is, this field must also be set to the * appropriate value based on previous user choice. + * + * @hide */ public boolean acceptUnvalidated; /** * Whether the user explicitly set that this network should be validated even if presence of * only partial internet connectivity. + * + * @hide */ public boolean acceptPartialConnectivity; @@ -65,29 +76,62 @@ public class NetworkAgentConfig implements Parcelable { * procedure, a carrier specific provisioning notification will be placed. * only one notification should be displayed. This field is set based on * which notification should be used for provisioning. + * + * @hide */ public boolean provisioningNotificationDisabled; + /** + * + * @return whether the sign in to network notification is enabled by this configuration. + */ + public boolean isProvisioningNotificationEnabled() { + return !provisioningNotificationDisabled; + } + /** * For mobile networks, this is the subscriber ID (such as IMSI). + * + * @hide */ public String subscriberId; + /** + * @return the subscriber ID, or null if none. + */ + @Nullable + public String getSubscriberId() { + return subscriberId; + } + /** * Set to skip 464xlat. This means the device will treat the network as IPv6-only and * will not attempt to detect a NAT64 via RFC 7050 DNS lookups. + * + * @hide */ public boolean skip464xlat; + /** + * @return whether NAT64 prefix detection is enabled. + */ + public boolean isNat64DetectionEnabled() { + return !skip464xlat; + } + /** * Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network. * Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode. + * + * @hide */ public boolean hasShownBroken; + /** @hide */ public NetworkAgentConfig() { } + /** @hide */ public NetworkAgentConfig(@Nullable NetworkAgentConfig nac) { if (nac != null) { allowBypass = nac.allowBypass; @@ -99,13 +143,63 @@ public class NetworkAgentConfig implements Parcelable { } } + /** + * Builder class to facilitate constructing {@link NetworkAgentConfig} objects. + */ + public static class Builder { + private final NetworkAgentConfig mConfig = new NetworkAgentConfig(); + + /** + * Sets the subscriber ID for this network. + * + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setSubscriberId(@Nullable String subscriberId) { + mConfig.subscriberId = subscriberId; + return this; + } + + /** + * Disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to save power + * and reduce idle traffic on networks that are known to be IPv6-only without a NAT64. + * + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder disableNat64Detection() { + mConfig.skip464xlat = true; + return this; + } + + /** + * Disables the "Sign in to network" notification. Used if the network transport will + * perform its own carrier-specific provisioning procedure. + * + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder disableProvisioningNotification() { + mConfig.provisioningNotificationDisabled = true; + return this; + } + + /** + * Returns the constructed {@link NetworkAgentConfig} object. + */ + @NonNull + public NetworkAgentConfig build() { + return mConfig; + } + } + @Override public int describeContents() { return 0; } @Override - public void writeToParcel(Parcel out, int flags) { + public void writeToParcel(@NonNull Parcel out, int flags) { out.writeInt(allowBypass ? 1 : 0); out.writeInt(explicitlySelected ? 1 : 0); out.writeInt(acceptUnvalidated ? 1 : 0); diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index 9e915aec68..e863266c4b 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -35,7 +35,6 @@ import android.net.ConnectivityManager; import android.net.IDnsResolver; import android.net.INetd; import android.net.Network; -import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkProvider; @@ -75,7 +74,6 @@ public class LingerMonitorTest { @Mock INetd mNetd; @Mock INetworkManagementService mNMS; @Mock Context mCtx; - @Mock NetworkAgentConfig mAgentConfig; @Mock NetworkNotificationManager mNotifier; @Mock Resources mResources; @@ -358,7 +356,7 @@ public class LingerMonitorTest { NetworkScore ns = new NetworkScore(); ns.putIntExtension(NetworkScore.LEGACY_SCORE, 50); NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null, - caps, ns, mCtx, null, mAgentConfig, mConnService, mNetd, mDnsResolver, mNMS, + caps, ns, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS, NetworkProvider.ID_NONE); nai.everValidated = true; return nai; diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java index cf70f5d499..9b248878fe 100644 --- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java +++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java @@ -63,7 +63,6 @@ public class Nat464XlatTest { static final int NETID = 42; @Mock ConnectivityService mConnectivity; - @Mock NetworkAgentConfig mAgentConfig; @Mock IDnsResolver mDnsResolver; @Mock INetd mNetd; @Mock INetworkManagementService mNms; @@ -72,6 +71,7 @@ public class Nat464XlatTest { TestLooper mLooper; Handler mHandler; + NetworkAgentConfig mAgentConfig = new NetworkAgentConfig(); Nat464Xlat makeNat464Xlat() { return new Nat464Xlat(mNai, mNetd, mDnsResolver, mNms) { From fd051db78b3d70be2f34828d500a3ada5f1fb79d Mon Sep 17 00:00:00 2001 From: markchien Date: Tue, 14 Jan 2020 12:54:40 +0800 Subject: [PATCH 021/229] Unhide NetworkRequest API which use legacy type Bug: 144753389 Test: -build, flash, boot -atest TetheringTests Change-Id: I349da06769e9ffcee6bb42f51ab454e0ef774fb3 --- core/java/android/net/ConnectivityManager.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 4bf3e90569..bc318e815b 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3622,14 +3622,26 @@ public class ConnectivityManager { /** * Helper function to request a network with a particular legacy type. * - * This is temporarily public @hide so it can be called by system code that uses the - * NetworkRequest API to request networks but relies on CONNECTIVITY_ACTION broadcasts for - * instead network notifications. + * @deprecated This is temporarily public for tethering to backwards compatibility that uses + * the NetworkRequest API to request networks with legacy type and relies on + * CONNECTIVITY_ACTION broadcasts instead of NetworkCallbacks. New caller should use + * {@link #requestNetwork(NetworkRequest, NetworkCallback, Handler)} instead. * * TODO: update said system code to rely on NetworkCallbacks and make this method private. + + * @param request {@link NetworkRequest} describing this request. + * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note + * the callback must not be shared - it uniquely specifies this request. + * @param timeoutMs The time in milliseconds to attempt looking for a suitable network + * before {@link NetworkCallback#onUnavailable()} is called. The timeout must + * be a positive value (i.e. >0). + * @param legacyType to specify the network type(#TYPE_*). + * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. * * @hide */ + @SystemApi + @Deprecated public void requestNetwork(@NonNull NetworkRequest request, @NonNull NetworkCallback networkCallback, int timeoutMs, int legacyType, @NonNull Handler handler) { From b0a42f72841067b85d6896814e3893f4456c3714 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 13 Dec 2019 19:47:12 +0900 Subject: [PATCH 022/229] Have registerNetworkAgent return a Network. This is more useful. Bug: 135998869 Test: FrameworkNetTests FrameworksWifiTests Change-Id: I74710b396fa3cec6fbae08d3dcab5bc90dc2e669 --- core/java/android/net/ConnectivityManager.java | 8 ++++---- core/java/android/net/IConnectivityManager.aidl | 2 +- core/java/android/net/NetworkAgent.java | 9 +++++---- .../java/com/android/server/ConnectivityService.java | 10 +++++++--- .../java/com/android/server/TestNetworkService.java | 4 ++-- .../util/com/android/server/NetworkAgentWrapper.java | 2 +- .../com/android/server/ConnectivityServiceTest.java | 2 +- 7 files changed, 21 insertions(+), 16 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 4bf3e90569..dda9ff4cb3 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3169,10 +3169,10 @@ public class ConnectivityManager { /** * @hide * Register a NetworkAgent with ConnectivityService. - * @return NetID corresponding to NetworkAgent. + * @return Network corresponding to NetworkAgent. */ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, + public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkAgentConfig config) { return registerNetworkAgent(messenger, ni, lp, nc, score, config, NetworkProvider.ID_NONE); } @@ -3180,10 +3180,10 @@ public class ConnectivityManager { /** * @hide * Register a NetworkAgent with ConnectivityService. - * @return NetID corresponding to NetworkAgent. + * @return Network corresponding to NetworkAgent. */ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, + public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) { try { return mService.registerNetworkAgent(messenger, ni, lp, nc, score, config, providerId); diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 7691beba32..186196bd31 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -152,7 +152,7 @@ interface IConnectivityManager void declareNetworkRequestUnfulfillable(in NetworkRequest request); - int registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp, + Network registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp, in NetworkCapabilities nc, int score, in NetworkAgentConfig config, in int factorySerialNumber); diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index fc72eecd41..d28620433c 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -44,9 +44,10 @@ import java.util.concurrent.atomic.AtomicBoolean; * @hide */ public abstract class NetworkAgent { - // Guaranteed to be valid (not NETID_UNSET), otherwise registerNetworkAgent() would have thrown - // an exception. - public final int netId; + // Guaranteed to be non-null, otherwise registerNetworkAgent() would have thrown + // an exception. Be careful in tests when mocking though. + @NonNull + public final Network network; private final Handler mHandler; private volatile AsyncChannel mAsyncChannel; @@ -246,7 +247,7 @@ public abstract class NetworkAgent { if (VDBG) log("Registering NetworkAgent"); ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( Context.CONNECTIVITY_SERVICE); - netId = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(ni), + network = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(ni), new LinkProperties(lp), new NetworkCapabilities(nc), score, config, providerId); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index f4962e5366..5435cbad87 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5505,7 +5505,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // changes that would conflict throughout the automerger graph. Having this method temporarily // helps with the process of going through with all these dependent changes across the entire // tree. - public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, + /** + * Register a new agent. {@see #registerNetworkAgent} below. + */ + public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkAgentConfig networkAgentConfig) { return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities, @@ -5526,8 +5529,9 @@ public class ConnectivityService extends IConnectivityManager.Stub * {@link NetworkAgentInfo#getCurrentScore}. * @param networkAgentConfig metadata about the network. This is never updated. * @param providerId the ID of the provider owning this NetworkAgent. + * @return the network created for this agent. */ - public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, + public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { enforceNetworkFactoryPermission(); @@ -5560,7 +5564,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // If the network disconnects or sends any other event before that, messages are deferred by // NetworkAgent until nai.asyncChannel.connect(), which will be called when finalizing the // registration. - return nai.network.netId; + return nai.network; } private void handleRegisterNetworkAgent(NetworkAgentInfo nai, INetworkMonitor networkMonitor) { diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index c27b0da780..ed3bab97ca 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -218,7 +218,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { // Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up // resources, even for binder death or unwanted calls. synchronized (mTestNetworkTracker) { - mTestNetworkTracker.remove(netId); + mTestNetworkTracker.remove(network.netId); } } } @@ -337,7 +337,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { callingUid, binder); - mTestNetworkTracker.put(agent.netId, agent); + mTestNetworkTracker.put(agent.network.netId, agent); } } catch (SocketException e) { throw new UncheckedIOException(e); diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index 0ab5c97d31..11d5b250d7 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -222,7 +222,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { @Override public Network getNetwork() { - return new Network(mNetworkAgent.netId); + return mNetworkAgent.network; } public void expectPreventReconnectReceived(long timeoutMs) { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index b2d363e278..1901a1db63 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -575,7 +575,7 @@ public class ConnectivityServiceTest { } }; - assertEquals(na.netId, nmNetworkCaptor.getValue().netId); + assertEquals(na.network.netId, nmNetworkCaptor.getValue().netId); mNmCallbacks = nmCbCaptor.getValue(); mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor); From 2429c7091c814b3c91018683652e1567e0f64f12 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Tue, 17 Dec 2019 00:33:18 +0800 Subject: [PATCH 023/229] Remove framework code that has moved to frameworks/libs/net Add srcs to framework and change import path. Remove the codes which are moved to frameworks/libs/net. Bug: 139268426 Bug: 135998869 Bug: 138306002 Bug: 143925787 Test: atest FrameworksNetTests atest FrameworksTelephonyTests atest ./frameworks/opt/net/wifi/tests/wifitests/runtests.sh Change-Id: Ieb8927f9af7f87a5ae038bd6c7daeb3d70117fef --- core/java/android/net/LinkProperties.java | 76 ++---------------- core/java/android/net/MacAddress.java | 79 ++----------------- core/java/android/net/NetworkUtils.java | 10 --- core/java/android/net/RouteInfo.java | 17 +--- .../android/server/ConnectivityService.java | 2 +- .../java/android/net/LinkPropertiesTest.java | 2 +- .../net/java/android/net/MacAddressTest.java | 12 +-- 7 files changed, 24 insertions(+), 174 deletions(-) diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 2792c56498..be8e561fd0 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -21,6 +21,8 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; +import android.net.util.LinkPropertiesUtils; +import android.net.util.LinkPropertiesUtils.CompareResult; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -81,36 +83,6 @@ public final class LinkProperties implements Parcelable { // Indexed by interface name to allow modification and to prevent duplicates being added. private Hashtable mStackedLinks = new Hashtable<>(); - /** - * @hide - */ - public static class CompareResult { - public final List removed = new ArrayList<>(); - public final List added = new ArrayList<>(); - - public CompareResult() {} - - public CompareResult(Collection oldItems, Collection newItems) { - if (oldItems != null) { - removed.addAll(oldItems); - } - if (newItems != null) { - for (T newItem : newItems) { - if (!removed.remove(newItem)) { - added.add(newItem); - } - } - } - } - - @Override - public String toString() { - return "removed=[" + TextUtils.join(",", removed) - + "] added=[" + TextUtils.join(",", added) - + "]"; - } - } - /** * @hide */ @@ -1295,7 +1267,7 @@ public final class LinkProperties implements Parcelable { */ @UnsupportedAppUsage public boolean isIdenticalInterfaceName(@NonNull LinkProperties target) { - return TextUtils.equals(getInterfaceName(), target.getInterfaceName()); + return LinkPropertiesUtils.isIdenticalInterfaceName(target, this); } /** @@ -1318,10 +1290,7 @@ public final class LinkProperties implements Parcelable { */ @UnsupportedAppUsage public boolean isIdenticalAddresses(@NonNull LinkProperties target) { - Collection targetAddresses = target.getAddresses(); - Collection sourceAddresses = getAddresses(); - return (sourceAddresses.size() == targetAddresses.size()) ? - sourceAddresses.containsAll(targetAddresses) : false; + return LinkPropertiesUtils.isIdenticalAddresses(target, this); } /** @@ -1333,15 +1302,7 @@ public final class LinkProperties implements Parcelable { */ @UnsupportedAppUsage public boolean isIdenticalDnses(@NonNull LinkProperties target) { - Collection targetDnses = target.getDnsServers(); - String targetDomains = target.getDomains(); - if (mDomains == null) { - if (targetDomains != null) return false; - } else { - if (!mDomains.equals(targetDomains)) return false; - } - return (mDnses.size() == targetDnses.size()) ? - mDnses.containsAll(targetDnses) : false; + return LinkPropertiesUtils.isIdenticalDnses(target, this); } /** @@ -1394,9 +1355,7 @@ public final class LinkProperties implements Parcelable { */ @UnsupportedAppUsage public boolean isIdenticalRoutes(@NonNull LinkProperties target) { - Collection targetRoutes = target.getRoutes(); - return (mRoutes.size() == targetRoutes.size()) ? - mRoutes.containsAll(targetRoutes) : false; + return LinkPropertiesUtils.isIdenticalRoutes(target, this); } /** @@ -1408,8 +1367,7 @@ public final class LinkProperties implements Parcelable { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public boolean isIdenticalHttpProxy(@NonNull LinkProperties target) { - return getHttpProxy() == null ? target.getHttpProxy() == null : - getHttpProxy().equals(target.getHttpProxy()); + return LinkPropertiesUtils.isIdenticalHttpProxy(target, this); } /** @@ -1540,26 +1498,6 @@ public final class LinkProperties implements Parcelable { && isIdenticalWakeOnLan(target); } - /** - * Compares the addresses in this LinkProperties with another - * LinkProperties, examining only addresses on the base link. - * - * @param target a LinkProperties with the new list of addresses - * @return the differences between the addresses. - * @hide - */ - public @NonNull CompareResult compareAddresses(@Nullable LinkProperties target) { - /* - * Duplicate the LinkAddresses into removed, we will be removing - * address which are common between mLinkAddresses and target - * leaving the addresses that are different. And address which - * are in target but not in mLinkAddresses are placed in the - * addedAddresses. - */ - return new CompareResult<>(mLinkAddresses, - target != null ? target.getLinkAddresses() : null); - } - /** * Compares the DNS addresses in this LinkProperties with another * LinkProperties, examining only DNS addresses on the base link. diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java index 74c9aac05b..0e10c42e61 100644 --- a/core/java/android/net/MacAddress.java +++ b/core/java/android/net/MacAddress.java @@ -20,11 +20,11 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; +import android.net.util.MacAddressUtils; import android.net.wifi.WifiInfo; import android.os.Parcel; import android.os.Parcelable; -import com.android.internal.util.BitUtils; import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; @@ -33,7 +33,6 @@ import java.net.Inet6Address; import java.net.UnknownHostException; import java.security.SecureRandom; import java.util.Arrays; -import java.util.Random; /** * Representation of a MAC address. @@ -109,20 +108,12 @@ public final class MacAddress implements Parcelable { if (equals(BROADCAST_ADDRESS)) { return TYPE_BROADCAST; } - if (isMulticastAddress()) { + if ((mAddr & MULTICAST_MASK) != 0) { return TYPE_MULTICAST; } return TYPE_UNICAST; } - /** - * @return true if this MacAddress is a multicast address. - * @hide - */ - public boolean isMulticastAddress() { - return (mAddr & MULTICAST_MASK) != 0; - } - /** * @return true if this MacAddress is a locally assigned address. */ @@ -192,7 +183,7 @@ public final class MacAddress implements Parcelable { * @hide */ public static boolean isMacAddress(byte[] addr) { - return addr != null && addr.length == ETHER_ADDR_LEN; + return MacAddressUtils.isMacAddress(addr); } /** @@ -261,26 +252,11 @@ public final class MacAddress implements Parcelable { } private static byte[] byteAddrFromLongAddr(long addr) { - byte[] bytes = new byte[ETHER_ADDR_LEN]; - int index = ETHER_ADDR_LEN; - while (index-- > 0) { - bytes[index] = (byte) addr; - addr = addr >> 8; - } - return bytes; + return MacAddressUtils.byteAddrFromLongAddr(addr); } private static long longAddrFromByteAddr(byte[] addr) { - Preconditions.checkNotNull(addr); - if (!isMacAddress(addr)) { - throw new IllegalArgumentException( - Arrays.toString(addr) + " was not a valid MAC address"); - } - long longAddr = 0; - for (byte b : addr) { - longAddr = (longAddr << 8) + BitUtils.uint8(b); - } - return longAddr; + return MacAddressUtils.longAddrFromByteAddr(addr); } // Internal conversion function equivalent to longAddrFromByteAddr(byteAddrFromStringAddr(addr)) @@ -350,50 +326,7 @@ public final class MacAddress implements Parcelable { * @hide */ public static @NonNull MacAddress createRandomUnicastAddressWithGoogleBase() { - return createRandomUnicastAddress(BASE_GOOGLE_MAC, new SecureRandom()); - } - - /** - * Returns a generated MAC address whose 46 bits, excluding the locally assigned bit and the - * unicast bit, are randomly selected. - * - * The locally assigned bit is always set to 1. The multicast bit is always set to 0. - * - * @return a random locally assigned, unicast MacAddress. - * - * @hide - */ - public static @NonNull MacAddress createRandomUnicastAddress() { - return createRandomUnicastAddress(null, new SecureRandom()); - } - - /** - * Returns a randomly generated MAC address using the given Random object and the same - * OUI values as the given MacAddress. - * - * The locally assigned bit is always set to 1. The multicast bit is always set to 0. - * - * @param base a base MacAddress whose OUI is used for generating the random address. - * If base == null then the OUI will also be randomized. - * @param r a standard Java Random object used for generating the random address. - * @return a random locally assigned MacAddress. - * - * @hide - */ - public static @NonNull MacAddress createRandomUnicastAddress(MacAddress base, Random r) { - long addr; - if (base == null) { - addr = r.nextLong() & VALID_LONG_MASK; - } else { - addr = (base.mAddr & OUI_MASK) | (NIC_MASK & r.nextLong()); - } - addr |= LOCALLY_ASSIGNED_MASK; - addr &= ~MULTICAST_MASK; - MacAddress mac = new MacAddress(addr); - if (mac.equals(DEFAULT_MAC_ADDRESS)) { - return createRandomUnicastAddress(base, r); - } - return mac; + return MacAddressUtils.createRandomUnicastAddress(BASE_GOOGLE_MAC, new SecureRandom()); } // Convenience function for working around the lack of byte literals. diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 08cc4e24b2..779f7bc91e 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -31,7 +31,6 @@ import android.util.Pair; import java.io.FileDescriptor; import java.math.BigInteger; import java.net.Inet4Address; -import java.net.Inet6Address; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; @@ -312,15 +311,6 @@ public class NetworkUtils { return new Pair(address, prefixLength); } - /** - * Check if IP address type is consistent between two InetAddress. - * @return true if both are the same type. False otherwise. - */ - public static boolean addressTypeMatches(InetAddress left, InetAddress right) { - return (((left instanceof Inet4Address) && (right instanceof Inet4Address)) || - ((left instanceof Inet6Address) && (right instanceof Inet6Address))); - } - /** * Convert a 32 char hex string into a Inet6Address. * throws a runtime exception if the string isn't 32 chars, isn't hex or can't be diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index ea6002ca29..e088094576 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; +import android.net.util.NetUtils; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -441,21 +442,7 @@ public final class RouteInfo implements Parcelable { @UnsupportedAppUsage @Nullable public static RouteInfo selectBestRoute(Collection routes, InetAddress dest) { - if ((routes == null) || (dest == null)) return null; - - RouteInfo bestRoute = null; - // pick a longest prefix match under same address type - for (RouteInfo route : routes) { - if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) { - if ((bestRoute != null) && - (bestRoute.mDestination.getPrefixLength() >= - route.mDestination.getPrefixLength())) { - continue; - } - if (route.matches(dest)) bestRoute = route; - } - } - return bestRoute; + return NetUtils.selectBestRoute(routes, dest); } /** diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 5435cbad87..c2e0fbca80 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -79,7 +79,6 @@ import android.net.InetAddresses; import android.net.IpMemoryStore; import android.net.IpPrefix; import android.net.LinkProperties; -import android.net.LinkProperties.CompareResult; import android.net.MatchAllNetworkSpecifier; import android.net.NattSocketKeepalive; import android.net.Network; @@ -114,6 +113,7 @@ import android.net.metrics.IpConnectivityLog; import android.net.metrics.NetworkEvent; import android.net.netlink.InetDiagMessage; import android.net.shared.PrivateDnsConfig; +import android.net.util.LinkPropertiesUtils.CompareResult; import android.net.util.MultinetworkPolicyTracker; import android.net.util.NetdService; import android.os.Binder; diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java index a7328acb73..6005cc375d 100644 --- a/tests/net/common/java/android/net/LinkPropertiesTest.java +++ b/tests/net/common/java/android/net/LinkPropertiesTest.java @@ -27,8 +27,8 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import android.net.LinkProperties.CompareResult; import android.net.LinkProperties.ProvisioningChange; +import android.net.util.LinkPropertiesUtils.CompareResult; import android.system.OsConstants; import android.util.ArraySet; diff --git a/tests/net/java/android/net/MacAddressTest.java b/tests/net/java/android/net/MacAddressTest.java index daf187d015..91c9a2a380 100644 --- a/tests/net/java/android/net/MacAddressTest.java +++ b/tests/net/java/android/net/MacAddressTest.java @@ -22,6 +22,8 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.net.util.MacAddressUtils; + import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -122,11 +124,11 @@ public class MacAddressTest { for (MacAddress mac : multicastAddresses) { String msg = mac.toString() + " expected to be a multicast address"; - assertTrue(msg, mac.isMulticastAddress()); + assertTrue(msg, MacAddressUtils.isMulticastAddress(mac)); } for (MacAddress mac : unicastAddresses) { String msg = mac.toString() + " expected not to be a multicast address"; - assertFalse(msg, mac.isMulticastAddress()); + assertFalse(msg, MacAddressUtils.isMulticastAddress(mac)); } } @@ -156,7 +158,7 @@ public class MacAddressTest { public void testMacAddressConversions() { final int iterations = 10000; for (int i = 0; i < iterations; i++) { - MacAddress mac = MacAddress.createRandomUnicastAddress(); + MacAddress mac = MacAddressUtils.createRandomUnicastAddress(); String stringRepr = mac.toString(); byte[] bytesRepr = mac.toByteArray(); @@ -188,7 +190,7 @@ public class MacAddressTest { final String expectedLocalOui = "26:5f:78"; final MacAddress base = MacAddress.fromString(anotherOui + ":0:0:0"); for (int i = 0; i < iterations; i++) { - MacAddress mac = MacAddress.createRandomUnicastAddress(base, r); + MacAddress mac = MacAddressUtils.createRandomUnicastAddress(base, r); String stringRepr = mac.toString(); assertTrue(stringRepr + " expected to be a locally assigned address", @@ -199,7 +201,7 @@ public class MacAddressTest { } for (int i = 0; i < iterations; i++) { - MacAddress mac = MacAddress.createRandomUnicastAddress(); + MacAddress mac = MacAddressUtils.createRandomUnicastAddress(); String stringRepr = mac.toString(); assertTrue(stringRepr + " expected to be a locally assigned address", From 93de608316ea30bf0f36e8e9bef99a7396a0352b Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 14 Jan 2020 19:48:18 +0900 Subject: [PATCH 024/229] Remove handling of EVENT_UNFULFILLABLE_REQUEST This message is not being sent by any component anymore. Test: built, flashed, WiFi and telephony working Test: atest FrameworksNetTests Bug: 138306002 Change-Id: I5b1ec3136ae8a0a6928e0fb2cda3d5f5e2ca657f --- .../android/server/ConnectivityService.java | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index f4962e5366..286b6a0e5d 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -87,7 +87,6 @@ import android.net.NetworkAgent; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkConfig; -import android.net.NetworkFactory; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkMonitorManager; @@ -2843,26 +2842,11 @@ public class ConnectivityService extends IConnectivityManager.Stub return true; } - // TODO: delete when direct use of registerNetworkFactory is no longer supported. - private boolean maybeHandleNetworkFactoryMessage(Message msg) { - switch (msg.what) { - default: - return false; - case NetworkFactory.EVENT_UNFULFILLABLE_REQUEST: { - handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.sendingUid, - /* callOnUnavailable */ true); - break; - } - } - return true; - } - @Override public void handleMessage(Message msg) { if (!maybeHandleAsyncChannelMessage(msg) && !maybeHandleNetworkMonitorMessage(msg) - && !maybeHandleNetworkAgentInfoMessage(msg) - && !maybeHandleNetworkFactoryMessage(msg)) { + && !maybeHandleNetworkAgentInfoMessage(msg)) { maybeHandleNetworkAgentMessage(msg); } } From 04b18a9e7bf49b04414b1d59ce96e62a573b480d Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 14 Jan 2020 20:33:06 +0900 Subject: [PATCH 025/229] Add NetworkRequest#satisfiedBy to SystemApi The API is useful for NetworkFactories to select requests based on capabilities. This mirrors NetworkCapabilities#satisfiedByNetworkCapabilities Test: m Bug: 138306002 Change-Id: I1d4a928256951397cabde5c352a872fd48d85859 --- core/java/android/net/NetworkRequest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index 9731f3ca18..7fd86f6887 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -454,6 +454,19 @@ public class NetworkRequest implements Parcelable { return networkCapabilities.hasUnwantedCapability(capability); } + /** + * Returns true iff. the capabilities requested in this NetworkRequest are satisfied by the + * provided {@link NetworkCapabilities}. + * + * @param nc Capabilities that should satisfy this NetworkRequest. null capabilities do not + * satisfy any request. + * @hide + */ + @SystemApi + public boolean satisfiedBy(@Nullable NetworkCapabilities nc) { + return networkCapabilities.satisfiedByNetworkCapabilities(nc); + } + /** * @see Builder#addTransportType(int) */ From ce12f80581d72055704c245aa738ea7c00a10807 Mon Sep 17 00:00:00 2001 From: paulhu Date: Mon, 13 Jan 2020 16:18:54 +0800 Subject: [PATCH 026/229] Expose SocketKeepalive#SUCCESS as SystemApi Support wifi mainline module usage. Bug: 135998869 Test: Build and make system-api-stubs-docs-update-current-api atest FrameworksNetTests Change-Id: I94171b2dc4f26442df918547bf8bc40953f63f2e --- core/java/android/net/SocketKeepalive.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java index fb224fbe13..fc9a8f63c1 100644 --- a/core/java/android/net/SocketKeepalive.java +++ b/core/java/android/net/SocketKeepalive.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.os.Binder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -53,7 +54,11 @@ import java.util.concurrent.Executor; public abstract class SocketKeepalive implements AutoCloseable { static final String TAG = "SocketKeepalive"; - /** @hide */ + /** + * No errors. + * @hide + */ + @SystemApi public static final int SUCCESS = 0; /** @hide */ From 980ed12f7f5afe1c568e57e0d4b084d87d744805 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 15 Jan 2020 00:13:37 +0900 Subject: [PATCH 027/229] Make most of NetworkAgent @SystemApi. Bug: 138306002 Bug: 139268426 Test: atest FrameworksNetTests FrameworksWifiTests FrameworksTelephonyTests Test: atest android.net.cts.ConnectivityManagerTest Change-Id: I856f01f02c35c2f6a886d8b98039e5dfbc48148b --- core/java/android/net/NetworkAgent.java | 234 +++++++++++++++++++----- 1 file changed, 184 insertions(+), 50 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index d28620433c..b2cf6f7dd6 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -17,6 +17,8 @@ package android.net; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Build; @@ -43,9 +45,11 @@ import java.util.concurrent.atomic.AtomicBoolean; * * @hide */ +@SystemApi public abstract class NetworkAgent { - // Guaranteed to be non-null, otherwise registerNetworkAgent() would have thrown - // an exception. Be careful in tests when mocking though. + /** + * The {@link Network} corresponding to this object. + */ @NonNull public final Network network; @@ -58,9 +62,14 @@ public abstract class NetworkAgent { private final ArrayListmPreConnectedQueue = new ArrayList(); private volatile long mLastBwRefreshTime = 0; private static final long BW_REFRESH_MIN_WIN_MS = 500; - private boolean mPollLceScheduled = false; - private AtomicBoolean mPollLcePending = new AtomicBoolean(false); - public final int mProviderId; + private boolean mBandwidthUpdateScheduled = false; + private AtomicBoolean mBandwidthUpdatePending = new AtomicBoolean(false); + + /** + * The ID of the {@link NetworkProvider} that created this object, or + * {@link NetworkProvider#ID_NONE} if unknown. + */ + public final int providerId; private static final int BASE = Protocol.BASE_NETWORK_AGENT; @@ -68,6 +77,7 @@ public abstract class NetworkAgent { * Sent by ConnectivityService to the NetworkAgent to inform it of * suspected connectivity problems on its network. The NetworkAgent * should take steps to verify and correct connectivity. + * @hide */ public static final int CMD_SUSPECT_BAD = BASE; @@ -76,6 +86,7 @@ public abstract class NetworkAgent { * ConnectivityService to pass the current NetworkInfo (connection state). * Sent when the NetworkInfo changes, mainly due to change of state. * obj = NetworkInfo + * @hide */ public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 1; @@ -83,6 +94,7 @@ public abstract class NetworkAgent { * Sent by the NetworkAgent to ConnectivityService to pass the current * NetworkCapabilties. * obj = NetworkCapabilities + * @hide */ public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 2; @@ -90,11 +102,14 @@ public abstract class NetworkAgent { * Sent by the NetworkAgent to ConnectivityService to pass the current * NetworkProperties. * obj = NetworkProperties + * @hide */ public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3; - /* centralize place where base network score, and network score scaling, will be + /** + * Centralize the place where base network score, and network score scaling, will be * stored, so as we can consistently compare apple and oranges, or wifi, ethernet and LTE + * @hide */ public static final int WIFI_BASE_SCORE = 60; @@ -102,6 +117,7 @@ public abstract class NetworkAgent { * Sent by the NetworkAgent to ConnectivityService to pass the current * network score. * obj = network score Integer + * @hide */ public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4; @@ -114,12 +130,33 @@ public abstract class NetworkAgent { * obj = Bundle containing map from {@code REDIRECT_URL_KEY} to {@code String} * representing URL that Internet probe was redirect to, if it was redirected, * or mapping to {@code null} otherwise. + * @hide */ public static final int CMD_REPORT_NETWORK_STATUS = BASE + 7; + + /** + * Network validation suceeded. + * Corresponds to {@link NetworkCapabilities.NET_CAPABILITY_VALIDATED}. + */ + public static final int VALIDATION_STATUS_VALID = 1; + + /** + * Network validation was attempted and failed. This may be received more than once as + * subsequent validation attempts are made. + */ + public static final int VALIDATION_STATUS_NOT_VALID = 2; + + // TODO: remove. + /** @hide */ public static final int VALID_NETWORK = 1; + /** @hide */ public static final int INVALID_NETWORK = 2; + /** + * The key for the redirect URL in the Bundle argument of {@code CMD_REPORT_NETWORK_STATUS}. + * @hide + */ public static String REDIRECT_URL_KEY = "redirect URL"; /** @@ -128,6 +165,7 @@ public abstract class NetworkAgent { * CONNECTED so it can be given special treatment at that time. * * obj = boolean indicating whether to use this network even if unvalidated + * @hide */ public static final int EVENT_SET_EXPLICITLY_SELECTED = BASE + 8; @@ -138,12 +176,14 @@ public abstract class NetworkAgent { * responsibility to remember it. * * arg1 = 1 if true, 0 if false + * @hide */ public static final int CMD_SAVE_ACCEPT_UNVALIDATED = BASE + 9; /** * Sent by ConnectivityService to the NetworkAgent to inform the agent to pull * the underlying network connection for updated bandwidth information. + * @hide */ public static final int CMD_REQUEST_BANDWIDTH_UPDATE = BASE + 10; @@ -156,6 +196,7 @@ public abstract class NetworkAgent { * obj = KeepalivePacketData object describing the data to be sent * * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. + * @hide */ public static final int CMD_START_SOCKET_KEEPALIVE = BASE + 11; @@ -165,6 +206,7 @@ public abstract class NetworkAgent { * arg1 = slot number of the keepalive to stop. * * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. + * @hide */ public static final int CMD_STOP_SOCKET_KEEPALIVE = BASE + 12; @@ -178,6 +220,7 @@ public abstract class NetworkAgent { * * arg1 = slot number of the keepalive * arg2 = error code + * @hide */ public static final int EVENT_SOCKET_KEEPALIVE = BASE + 13; @@ -186,6 +229,7 @@ public abstract class NetworkAgent { * that when crossed should trigger a system wakeup and a NetworkCapabilities update. * * obj = int[] describing signal strength thresholds. + * @hide */ public static final int CMD_SET_SIGNAL_STRENGTH_THRESHOLDS = BASE + 14; @@ -193,6 +237,7 @@ public abstract class NetworkAgent { * Sent by ConnectivityService to the NeworkAgent to inform the agent to avoid * automatically reconnecting to this network (e.g. via autojoin). Happens * when user selects "No" option on the "Stay connected?" dialog box. + * @hide */ public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15; @@ -205,6 +250,7 @@ public abstract class NetworkAgent { * This does not happen with UDP, so this message is TCP-specific. * arg1 = slot number of the keepalive to filter for. * obj = the keepalive packet to send repeatedly. + * @hide */ public static final int CMD_ADD_KEEPALIVE_PACKET_FILTER = BASE + 16; @@ -212,6 +258,7 @@ public abstract class NetworkAgent { * Sent by the KeepaliveTracker to NetworkAgent to remove a packet filter. See * {@link #CMD_ADD_KEEPALIVE_PACKET_FILTER}. * arg1 = slot number of the keepalive packet filter to remove. + * @hide */ public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; @@ -219,27 +266,32 @@ public abstract class NetworkAgent { // of dependent changes that would conflict throughout the automerger graph. Having these // temporarily helps with the process of going through with all these dependent changes across // the entire tree. + /** @hide TODO: decide which of these to expose. */ public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) { this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE); } + + /** @hide TODO: decide which of these to expose. */ public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) { this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE); } + /** @hide TODO: decide which of these to expose. */ public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, int providerId) { this(looper, context, logTag, ni, nc, lp, score, null, providerId); } + /** @hide TODO: decide which of these to expose. */ public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, int providerId) { mHandler = new NetworkAgentHandler(looper); LOG_TAG = logTag; mContext = context; - mProviderId = providerId; + this.providerId = providerId; if (ni == null || nc == null || lp == null) { throw new IllegalArgumentException(); } @@ -287,7 +339,7 @@ public abstract class NetworkAgent { case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { if (DBG) log("NetworkAgent channel lost"); // let the client know CS is done with us. - unwanted(); + onNetworkUnwanted(); synchronized (mPreConnectedQueue) { mAsyncChannel = null; } @@ -303,16 +355,16 @@ public abstract class NetworkAgent { log("CMD_REQUEST_BANDWIDTH_UPDATE request received."); } if (currentTimeMs >= (mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS)) { - mPollLceScheduled = false; - if (!mPollLcePending.getAndSet(true)) { - pollLceData(); + mBandwidthUpdateScheduled = false; + if (!mBandwidthUpdatePending.getAndSet(true)) { + onBandwidthUpdateRequested(); } } else { // deliver the request at a later time rather than discard it completely. - if (!mPollLceScheduled) { + if (!mBandwidthUpdateScheduled) { long waitTime = mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS - currentTimeMs + 1; - mPollLceScheduled = sendEmptyMessageDelayed( + mBandwidthUpdateScheduled = sendEmptyMessageDelayed( CMD_REQUEST_BANDWIDTH_UPDATE, waitTime); } } @@ -325,19 +377,20 @@ public abstract class NetworkAgent { + (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") + redirectUrl); } - networkStatus(msg.arg1, redirectUrl); + onValidationStatus(msg.arg1 /* status */, redirectUrl); break; } case CMD_SAVE_ACCEPT_UNVALIDATED: { - saveAcceptUnvalidated(msg.arg1 != 0); + onSaveAcceptUnvalidated(msg.arg1 != 0); break; } case CMD_START_SOCKET_KEEPALIVE: { - startSocketKeepalive(msg); + onStartSocketKeepalive(msg.arg1 /* slot */, msg.arg2 /* interval */, + (KeepalivePacketData) msg.obj /* packet */); break; } case CMD_STOP_SOCKET_KEEPALIVE: { - stopSocketKeepalive(msg); + onStopSocketKeepalive(msg.arg1 /* slot */); break; } @@ -350,19 +403,20 @@ public abstract class NetworkAgent { for (int i = 0; i < intThresholds.length; i++) { intThresholds[i] = thresholds.get(i); } - setSignalStrengthThresholds(intThresholds); + onSignalStrengthThresholdsUpdated(intThresholds); break; } case CMD_PREVENT_AUTOMATIC_RECONNECT: { - preventAutomaticReconnect(); + onAutomaticReconnectDisabled(); break; } case CMD_ADD_KEEPALIVE_PACKET_FILTER: { - addKeepalivePacketFilter(msg); + onAddKeepalivePacketFilter(msg.arg1 /* slot */, + (KeepalivePacketData) msg.obj /* packet */); break; } case CMD_REMOVE_KEEPALIVE_PACKET_FILTER: { - removeKeepalivePacketFilter(msg); + onRemoveKeepalivePacketFilter(msg.arg1 /* slot */); break; } } @@ -397,14 +451,16 @@ public abstract class NetworkAgent { } /** - * Called by the bearer code when it has new LinkProperties data. + * Must be called by the agent when the network's {@link LinkProperties} change. + * @param linkProperties the new LinkProperties. */ - public void sendLinkProperties(LinkProperties linkProperties) { + public void sendLinkProperties(@NonNull LinkProperties linkProperties) { queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties)); } /** - * Called by the bearer code when it has new NetworkInfo data. + * Must be called by the agent when it has a new NetworkInfo object. + * @hide TODO: expose something better. */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public void sendNetworkInfo(NetworkInfo networkInfo) { @@ -412,17 +468,19 @@ public abstract class NetworkAgent { } /** - * Called by the bearer code when it has new NetworkCapabilities data. + * Must be called by the agent when the network's {@link NetworkCapabilities} change. + * @param networkCapabilities the new NetworkCapabilities. */ - public void sendNetworkCapabilities(NetworkCapabilities networkCapabilities) { - mPollLcePending.set(false); + public void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) { + mBandwidthUpdatePending.set(false); mLastBwRefreshTime = System.currentTimeMillis(); queueOrSendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED, new NetworkCapabilities(networkCapabilities)); } /** - * Called by the bearer code when it has a new score for this network. + * Must be called by the agent to update the score of this network. + * @param score the new score. */ public void sendNetworkScore(int score) { if (score < 0) { @@ -434,14 +492,16 @@ public abstract class NetworkAgent { } /** - * Called by the bearer code when it has a new NetworkScore for this network. + * Must be called by the agent when it has a new {@link NetworkScore} for this network. + * @param ns the new score. + * @hide TODO: unhide the NetworkScore class, and rename to sendNetworkScore. */ public void updateScore(@NonNull NetworkScore ns) { queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new NetworkScore(ns)); } /** - * Called by the bearer to indicate this network was manually selected by the user. + * Must be called by the agent to indicate this network was manually selected by the user. * This should be called before the NetworkInfo is marked CONNECTED so that this * Network can be given special treatment at that time. If {@code acceptUnvalidated} is * {@code true}, then the system will switch to this network. If it is {@code false} and the @@ -450,15 +510,16 @@ public abstract class NetworkAgent { * {@link #saveAcceptUnvalidated} to persist the user's choice. Thus, if the transport ever * calls this method with {@code acceptUnvalidated} set to {@code false}, it must also implement * {@link #saveAcceptUnvalidated} to respect the user's choice. + * @hide should move to NetworkAgentConfig. */ public void explicitlySelected(boolean acceptUnvalidated) { explicitlySelected(true /* explicitlySelected */, acceptUnvalidated); } /** - * Called by the bearer to indicate whether the network was manually selected by the user. - * This should be called before the NetworkInfo is marked CONNECTED so that this - * Network can be given special treatment at that time. + * Must be called by the agent to indicate whether the network was manually selected by the + * user. This should be called before the network becomes connected, so it can be given + * special treatment when it does. * * If {@code explicitlySelected} is {@code true}, and {@code acceptUnvalidated} is {@code true}, * then the system will switch to this network. If {@code explicitlySelected} is {@code true} @@ -473,6 +534,7 @@ public abstract class NetworkAgent { * {@code true}, the system will interpret this as the user having accepted partial connectivity * on this network. Thus, the system will switch to the network and consider it validated even * if it only provides partial connectivity, but the network is not otherwise treated specially. + * @hide should move to NetworkAgentConfig. */ public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) { queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED, @@ -486,73 +548,126 @@ public abstract class NetworkAgent { * as well, either canceling NetworkRequests or altering their score such that this * network won't be immediately requested again. */ - abstract protected void unwanted(); + public void onNetworkUnwanted() { + unwanted(); + } + /** @hide TODO delete once subclasses have moved to onNetworkUnwanted. */ + protected void unwanted() { + } /** * Called when ConnectivityService request a bandwidth update. The parent factory * shall try to overwrite this method and produce a bandwidth update if capable. */ + public void onBandwidthUpdateRequested() { + pollLceData(); + } + /** @hide TODO delete once subclasses have moved to onBandwidthUpdateRequested. */ protected void pollLceData() { } /** * Called when the system determines the usefulness of this network. * - * Networks claiming internet connectivity will have their internet - * connectivity verified. + * The system attempts to validate Internet connectivity on networks that provide the + * {@NetworkCapabilities#NET_CAPABILITY_INTERNET} capability. * * Currently there are two possible values: - * {@code VALID_NETWORK} if the system is happy with the connection, - * {@code INVALID_NETWORK} if the system is not happy. - * TODO - add indications of captive portal-ness and related success/failure, - * ie, CAPTIVE_SUCCESS_NETWORK, CAPTIVE_NETWORK for successful login and detection + * {@code VALIDATION_STATUS_VALID} if Internet connectivity was validated, + * {@code VALIDATION_STATUS_NOT_VALID} if Internet connectivity was not validated. * - * This may be called multiple times as the network status changes and may - * generate false negatives if we lose ip connectivity before the link is torn down. + * This may be called multiple times as network status changes, or if there are multiple + * subsequent attempts to validate connectivity that fail. * - * @param status one of {@code VALID_NETWORK} or {@code INVALID_NETWORK}. - * @param redirectUrl If the Internet probe was redirected, this is the destination it was - * redirected to, otherwise {@code null}. + * @param status one of {@code VALIDATION_STATUS_VALID} or {@code VALIDATION_STATUS_NOT_VALID}. + * @param redirectUrl If Internet connectivity is being redirected (e.g., on a captive portal), + * this is the destination the probes are being redirected to, otherwise {@code null}. */ + public void onValidationStatus(int status, @Nullable String redirectUrl) { + networkStatus(status, redirectUrl); + } + /** @hide TODO delete once subclasses have moved to onValidationStatus */ protected void networkStatus(int status, String redirectUrl) { } + /** * Called when the user asks to remember the choice to use this network even if unvalidated. * The transport is responsible for remembering the choice, and the next time the user connects * to the network, should explicitlySelected with {@code acceptUnvalidated} set to {@code true}. * This method will only be called if {@link #explicitlySelected} was called with * {@code acceptUnvalidated} set to {@code false}. + * @param accept whether the user wants to use the network even if unvalidated. */ + public void onSaveAcceptUnvalidated(boolean accept) { + saveAcceptUnvalidated(accept); + } + /** @hide TODO delete once subclasses have moved to onSaveAcceptUnvalidated */ protected void saveAcceptUnvalidated(boolean accept) { } /** * Requests that the network hardware send the specified packet at the specified interval. + * + * @param slot the hardware slot on which to start the keepalive. + * @param intervalSeconds the interval between packets + * @param packet the packet to send. */ + public void onStartSocketKeepalive(int slot, int intervalSeconds, + @NonNull KeepalivePacketData packet) { + Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot, intervalSeconds, + packet); + startSocketKeepalive(msg); + msg.recycle(); + } + /** @hide TODO delete once subclasses have moved to onStartSocketKeepalive */ protected void startSocketKeepalive(Message msg) { onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED); } /** - * Requests that the network hardware send the specified packet at the specified interval. + * Requests that the network hardware stop a previously-started keepalive. + * + * @param slot the hardware slot on which to stop the keepalive. */ + public void onStopSocketKeepalive(int slot) { + Message msg = mHandler.obtainMessage(CMD_STOP_SOCKET_KEEPALIVE, slot, 0, null); + stopSocketKeepalive(msg); + msg.recycle(); + } + /** @hide TODO delete once subclasses have moved to onStopSocketKeepalive */ protected void stopSocketKeepalive(Message msg) { onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED); } /** - * Called by the network when a socket keepalive event occurs. + * Must be called by the agent when a socket keepalive event occurs. + * + * @param slot the hardware slot on which the event occurred. + * @param event the event that occurred. */ + public void sendSocketKeepaliveEvent(int slot, int event) { + queueOrSendMessage(EVENT_SOCKET_KEEPALIVE, slot, event); + } + /** @hide TODO delete once callers have moved to sendSocketKeepaliveEvent */ public void onSocketKeepaliveEvent(int slot, int reason) { - queueOrSendMessage(EVENT_SOCKET_KEEPALIVE, slot, reason); + sendSocketKeepaliveEvent(slot, reason); } /** * Called by ConnectivityService to add specific packet filter to network hardware to block - * ACKs matching the sent keepalive packets. Implementations that support this feature must - * override this method. + * replies (e.g., TCP ACKs) matching the sent keepalive packets. Implementations that support + * this feature must override this method. + * + * @param slot the hardware slot on which the keepalive should be sent. + * @param packet the packet that is being sent. */ + public void onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet) { + Message msg = mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0, packet); + addKeepalivePacketFilter(msg); + msg.recycle(); + } + /** @hide TODO delete once subclasses have moved to onAddKeepalivePacketFilter */ protected void addKeepalivePacketFilter(Message msg) { } @@ -560,14 +675,28 @@ public abstract class NetworkAgent { * Called by ConnectivityService to remove a packet filter installed with * {@link #addKeepalivePacketFilter(Message)}. Implementations that support this feature * must override this method. + * + * @param slot the hardware slot on which the keepalive is being sent. */ + public void onRemoveKeepalivePacketFilter(int slot) { + Message msg = mHandler.obtainMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, slot, 0, null); + removeKeepalivePacketFilter(msg); + msg.recycle(); + } + /** @hide TODO delete once subclasses have moved to onRemoveKeepalivePacketFilter */ protected void removeKeepalivePacketFilter(Message msg) { } /** * Called by ConnectivityService to inform this network transport of signal strength thresholds * that when crossed should trigger a system wakeup and a NetworkCapabilities update. + * + * @param thresholds the array of thresholds that should trigger wakeups. */ + public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { + setSignalStrengthThresholds(thresholds); + } + /** @hide TODO delete once subclasses have moved to onSetSignalStrengthThresholds */ protected void setSignalStrengthThresholds(int[] thresholds) { } @@ -577,9 +706,14 @@ public abstract class NetworkAgent { * responsible for making sure the device does not automatically reconnect to the same network * after the {@code unwanted} call. */ + public void onAutomaticReconnectDisabled() { + preventAutomaticReconnect(); + } + /** @hide TODO delete once subclasses have moved to onAutomaticReconnectDisabled */ protected void preventAutomaticReconnect() { } + /** @hide */ protected void log(String s) { Log.d(LOG_TAG, "NetworkAgent: " + s); } From 6079c4d8eb792b74385bc04989a4ed4ed2926bc4 Mon Sep 17 00:00:00 2001 From: markchien Date: Wed, 15 Jan 2020 20:41:31 +0800 Subject: [PATCH 028/229] NetworkAgent: Fix doc build fail by invalid tag Bug: 138306002 Bug: 139268426 Test: make doc-comment-check-docs Change-Id: I8b8df5096b90ad10545087ab09f68ecae637aa35 --- core/java/android/net/NetworkAgent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index b2cf6f7dd6..aae9fd4725 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -570,7 +570,7 @@ public abstract class NetworkAgent { * Called when the system determines the usefulness of this network. * * The system attempts to validate Internet connectivity on networks that provide the - * {@NetworkCapabilities#NET_CAPABILITY_INTERNET} capability. + * {@link NetworkCapabilities#NET_CAPABILITY_INTERNET} capability. * * Currently there are two possible values: * {@code VALIDATION_STATUS_VALID} if Internet connectivity was validated, From 45d4f10c428edd845992890fe6513f2b5b0c065b Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Tue, 14 Jan 2020 22:46:36 +0900 Subject: [PATCH 029/229] Make NetworkCapabilities authoritative for suspended state ...instead of NetworkInfo Bug: 138306002 Test: FrameworksNetTests FrameworksTelephonyTests Change-Id: I4808fcc0047a926b23ed3d49d979bb7b0371dc69 --- .../android/server/ConnectivityService.java | 60 +++++++++++++------ .../server/connectivity/NetworkAgentInfo.java | 9 --- .../android/server/NetworkAgentWrapper.java | 8 +-- 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index c1e23e42c1..5e495b98c5 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -39,6 +39,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkPolicyManager.RULE_NONE; import static android.net.NetworkPolicyManager.uidRulesToString; @@ -5840,11 +5841,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } else { newNc.addCapability(NET_CAPABILITY_FOREGROUND); } - if (nai.isSuspended()) { - newNc.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); - } else { - newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED); - } if (nai.partialConnectivity) { newNc.addCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY); } else { @@ -5852,6 +5848,11 @@ public class ConnectivityService extends IConnectivityManager.Stub } newNc.setPrivateDnsBroken(nai.networkCapabilities.isPrivateDnsBroken()); + // TODO : remove this once all factories are updated to send NOT_SUSPENDED + if (!newNc.hasTransport(TRANSPORT_CELLULAR)) { + newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED); + } + return newNc; } @@ -5896,6 +5897,17 @@ public class ConnectivityService extends IConnectivityManager.Stub // on this network. We might have been called by rematchNetworkAndRequests when a // network changed foreground state. processListenRequests(nai); + final boolean prevSuspended = !prevNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); + final boolean suspended = !newNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); + if (prevSuspended != suspended) { + // TODO (b/73132094) : remove this call once the few users of onSuspended and + // onResumed have been removed. + notifyNetworkCallbacks(nai, suspended ? ConnectivityManager.CALLBACK_SUSPENDED + : ConnectivityManager.CALLBACK_RESUMED); + // updateNetworkInfo will mix in the suspended info from the capabilities and + // take appropriate action for the network having possibly changed state. + updateNetworkInfo(nai, nai.networkInfo); + } } else { // If the requestable capabilities have changed or the score changed, we can't have been // called by rematchNetworkAndRequests, so it's safe to start a rematch. @@ -5903,6 +5915,9 @@ public class ConnectivityService extends IConnectivityManager.Stub notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED); } + // TODO : static analysis indicates that prevNc can't be null here (getAndSetNetworkCaps + // never returns null), so mark the relevant members and functions in nai as @NonNull and + // remove this test if (prevNc != null) { final boolean oldMetered = prevNc.isMetered(); final boolean newMetered = newNc.isMetered(); @@ -6597,10 +6612,30 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo newInfo) { + @NonNull + private NetworkInfo mixInInfo(@NonNull final NetworkAgentInfo nai, @NonNull NetworkInfo info) { + final NetworkInfo newInfo = new NetworkInfo(info); + // The suspended bit is managed in NetworkCapabilities. + final boolean suspended = + !nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); + if (suspended && info.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) { + // Only override the state with SUSPENDED if the network is currently in CONNECTED + // state. This is because the network could have been suspended before connecting, + // or it could be disconnecting while being suspended, and in both these cases + // the state should not be overridden. Note that the only detailed state that + // maps to State.CONNECTED is DetailedState.CONNECTED, so there is also no need to + // worry about multiple different substates of CONNECTED. + newInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, info.getReason(), + info.getExtraInfo()); + } + return newInfo; + } + + private void updateNetworkInfo(NetworkAgentInfo networkAgent, NetworkInfo info) { + final NetworkInfo newInfo = mixInInfo(networkAgent, info); + final NetworkInfo.State state = newInfo.getState(); NetworkInfo oldInfo = null; - final int oldScore = networkAgent.getCurrentScore(); synchronized (networkAgent) { oldInfo = networkAgent.networkInfo; networkAgent.networkInfo = newInfo; @@ -6682,17 +6717,6 @@ public class ConnectivityService extends IConnectivityManager.Stub } } else if (networkAgent.created && (oldInfo.getState() == NetworkInfo.State.SUSPENDED || state == NetworkInfo.State.SUSPENDED)) { - // going into or coming out of SUSPEND: re-score and notify - if (networkAgent.getCurrentScore() != oldScore) { - rematchAllNetworksAndRequests(); - } - updateCapabilities(networkAgent.getCurrentScore(), networkAgent, - networkAgent.networkCapabilities); - // TODO (b/73132094) : remove this call once the few users of onSuspended and - // onResumed have been removed. - notifyNetworkCallbacks(networkAgent, (state == NetworkInfo.State.SUSPENDED ? - ConnectivityManager.CALLBACK_SUSPENDED : - ConnectivityManager.CALLBACK_RESUMED)); mLegacyTypeTracker.update(networkAgent); } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index c1ab55106a..d66aec5761 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -451,15 +451,6 @@ public class NetworkAgentInfo implements Comparable { && !isLingering(); } - /** - * Returns whether this network is currently suspended. A network is suspended if it is still - * connected but data temporarily fails to transfer. See {@link NetworkInfo.State#SUSPENDED} - * and {@link NetworkCapabilities#NET_CAPABILITY_NOT_SUSPENDED}. - */ - public boolean isSuspended() { - return networkInfo.getState() == NetworkInfo.State.SUSPENDED; - } - // Does this network satisfy request? public boolean satisfies(NetworkRequest request) { return created && diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index 11d5b250d7..1c69209863 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -16,6 +16,7 @@ package com.android.server; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET; @@ -74,6 +75,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { final String typeName = ConnectivityManager.getNetworkTypeName(type); mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock"); mNetworkCapabilities = new NetworkCapabilities(); + mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED); mNetworkCapabilities.addTransportType(transport); switch (transport) { case TRANSPORT_ETHERNET: @@ -206,13 +208,11 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { } public void suspend() { - mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, null, null); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); + removeCapability(NET_CAPABILITY_NOT_SUSPENDED); } public void resume() { - mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); + addCapability(NET_CAPABILITY_NOT_SUSPENDED); } public void disconnect() { From a8cc3cb4c514ccb69097fcb2eca0382549ca0f0d Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 15 Jan 2020 00:49:43 +0900 Subject: [PATCH 030/229] Make NetworkCapabilities authoritative for roaming state ...instead of NetworkInfo Bug: 138306002 Test: FrameworksNetTests FrameworksTelephonyTests Change-Id: Ifdea19fa32089b5c7925f5010169b1dea3d2b304 --- .../java/com/android/server/ConnectivityService.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 5e495b98c5..98b5728017 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5848,9 +5848,10 @@ public class ConnectivityService extends IConnectivityManager.Stub } newNc.setPrivateDnsBroken(nai.networkCapabilities.isPrivateDnsBroken()); - // TODO : remove this once all factories are updated to send NOT_SUSPENDED + // TODO : remove this once all factories are updated to send NOT_SUSPENDED and NOT_ROAMING if (!newNc.hasTransport(TRANSPORT_CELLULAR)) { newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED); + newNc.addCapability(NET_CAPABILITY_NOT_ROAMING); } return newNc; @@ -5899,7 +5900,9 @@ public class ConnectivityService extends IConnectivityManager.Stub processListenRequests(nai); final boolean prevSuspended = !prevNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); final boolean suspended = !newNc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); - if (prevSuspended != suspended) { + final boolean prevRoaming = !prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING); + final boolean roaming = !newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING); + if (prevSuspended != suspended || prevRoaming != roaming) { // TODO (b/73132094) : remove this call once the few users of onSuspended and // onResumed have been removed. notifyNetworkCallbacks(nai, suspended ? ConnectivityManager.CALLBACK_SUSPENDED @@ -6615,7 +6618,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @NonNull private NetworkInfo mixInInfo(@NonNull final NetworkAgentInfo nai, @NonNull NetworkInfo info) { final NetworkInfo newInfo = new NetworkInfo(info); - // The suspended bit is managed in NetworkCapabilities. + // The suspended and roaming bits are managed in NetworkCapabilities. final boolean suspended = !nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_SUSPENDED); if (suspended && info.getDetailedState() == NetworkInfo.DetailedState.CONNECTED) { @@ -6628,6 +6631,7 @@ public class ConnectivityService extends IConnectivityManager.Stub newInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, info.getReason(), info.getExtraInfo()); } + newInfo.setRoaming(!nai.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_ROAMING)); return newInfo; } From fd1758d45e2c0cbeff18538224b0aed9b3dbc646 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 15 Jan 2020 04:01:53 +0900 Subject: [PATCH 031/229] Add a systemapi constructor for NetworkAgent Bug: 138306002 Bug: 139268426 Test: atest FrameworksNetTests FrameworksWifiTests FrameworksTelephonyTests make doc-comment-check-docs Change-Id: I288ea32fac07a9a486e2ea451a2c9b098446a74c --- core/java/android/net/NetworkAgent.java | 44 +++++++++++--- core/java/android/net/NetworkAgentConfig.java | 58 ++++++++++++++++++- 2 files changed, 91 insertions(+), 11 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index aae9fd4725..61a1484cef 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -262,32 +262,60 @@ public abstract class NetworkAgent { */ public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; - // TODO : remove these two constructors. They are a stopgap measure to help sheperding a number - // of dependent changes that would conflict throughout the automerger graph. Having these - // temporarily helps with the process of going through with all these dependent changes across - // the entire tree. - /** @hide TODO: decide which of these to expose. */ + /** @hide TODO: remove and replace usage with the public constructor. */ public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) { this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE); } - /** @hide TODO: decide which of these to expose. */ + /** @hide TODO: remove and replace usage with the public constructor. */ public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) { this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE); } - /** @hide TODO: decide which of these to expose. */ + /** @hide TODO: remove and replace usage with the public constructor. */ public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, int providerId) { this(looper, context, logTag, ni, nc, lp, score, null, providerId); } - /** @hide TODO: decide which of these to expose. */ + /** @hide TODO: remove and replace usage with the public constructor. */ public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, int providerId) { + this(looper, context, logTag, nc, lp, score, config, providerId, ni); + } + + private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) { + // The subtype can be changed with (TODO) setLegacySubtype, but it starts + // with the type and an empty description. + return new NetworkInfo(config.legacyType, config.legacyType, config.legacyTypeName, ""); + } + + /** + * Create a new network agent. + * @param context a {@link Context} to get system services from. + * @param looper the {@link Looper} on which to invoke the callbacks. + * @param logTag the tag for logs + * @param nc the initial {@link NetworkCapabilities} of this network. Update with + * sendNetworkCapabilities. + * @param lp the initial {@link LinkProperties} of this network. Update with sendLinkProperties. + * @param score the initial score of this network. Update with sendNetworkScore. + * @param config an immutable {@link NetworkAgentConfig} for this agent. + * @param provider the {@link NetworkProvider} managing this agent. + */ + public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, + @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { + this(looper, context, logTag, nc, lp, score, config, + provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(), + getLegacyNetworkInfo(config)); + } + + private NetworkAgent(Looper looper, Context context, String logTag, NetworkCapabilities nc, + LinkProperties lp, int score, NetworkAgentConfig config, int providerId, + NetworkInfo ni) { mHandler = new NetworkAgentHandler(looper); LOG_TAG = logTag; mContext = context; diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java index abc6b67efb..1e5af673b8 100644 --- a/core/java/android/net/NetworkAgentConfig.java +++ b/core/java/android/net/NetworkAgentConfig.java @@ -21,12 +21,11 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; -import android.text.TextUtils; /** * Allows a network transport to provide the system with policy and configuration information about - * a particular network when registering a {@link NetworkAgent}. This information cannot change once - * the agent is registered. + * a particular network when registering a {@link NetworkAgent}. + * @note This information cannot change once the agent is registered. * * @hide */ @@ -119,6 +118,19 @@ public final class NetworkAgentConfig implements Parcelable { return !skip464xlat; } + /** + * The legacy type of this network agent, or TYPE_NONE if unset. + * @hide + */ + public int legacyType = ConnectivityManager.TYPE_NONE; + + /** + * @return the legacy type + */ + public int getLegacyType() { + return legacyType; + } + /** * Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network. * Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode. @@ -127,6 +139,21 @@ public final class NetworkAgentConfig implements Parcelable { */ public boolean hasShownBroken; + /** + * The name of the legacy network type. It's a free-form string used in logging. + * @hide + */ + @NonNull + public String legacyTypeName = ""; + + /** + * @return the name of the legacy network type. It's a free-form string used in logging. + */ + @NonNull + public String getLegacyTypeName() { + return legacyTypeName; + } + /** @hide */ public NetworkAgentConfig() { } @@ -140,6 +167,8 @@ public final class NetworkAgentConfig implements Parcelable { subscriberId = nac.subscriberId; provisioningNotificationDisabled = nac.provisioningNotificationDisabled; skip464xlat = nac.skip464xlat; + legacyType = nac.legacyType; + legacyTypeName = nac.legacyTypeName; } } @@ -184,6 +213,29 @@ public final class NetworkAgentConfig implements Parcelable { return this; } + /** + * Sets the legacy type for this network. + * + * @param legacyType the type + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setLegacyType(int legacyType) { + mConfig.legacyType = legacyType; + return this; + } + + /** + * Sets the name of the legacy type of the agent. It's a free-form string used in logging. + * @param legacyTypeName the name + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setLegacyTypeName(@NonNull String legacyTypeName) { + mConfig.legacyTypeName = legacyTypeName; + return this; + } + /** * Returns the constructed {@link NetworkAgentConfig} object. */ From 72106b0b48644e549a7407e87d39ea852e0a6160 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=8C=B6=EF=B8=8FSam=20Sacco=C2=B0=CD=8C=CD=8C=CD=8C?= =?UTF-8?q?=CD=8C=CD=8C=CD=8C=CD=8C=CD=8C=CD=8C=CD=8C=CD=8C=CD=8C=CD=8C?= =?UTF-8?q?=CD=8C=CD=8C=CD=8C=CD=8C=CD=8C=CD=8C=CD=8C=CD=8C=CD=8C=CD=8C?= =?UTF-8?q?=CD=8C=CD=8Cne?= Date: Sat, 18 Jan 2020 20:43:43 +0000 Subject: [PATCH 032/229] Fix invalid use of @note for doc builds. Originally introduced in https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/10087632 Change-Id: I35fc4a814238635fa95981649c27230dda319afa --- core/java/android/net/NetworkAgentConfig.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java index 1e5af673b8..2c5a113a93 100644 --- a/core/java/android/net/NetworkAgentConfig.java +++ b/core/java/android/net/NetworkAgentConfig.java @@ -24,8 +24,7 @@ import android.os.Parcelable; /** * Allows a network transport to provide the system with policy and configuration information about - * a particular network when registering a {@link NetworkAgent}. - * @note This information cannot change once the agent is registered. + * a particular network when registering a {@link NetworkAgent}. This information cannot change once the agent is registered. * * @hide */ From 101719ce8e9705b6a47ace130f9f8fd86a52c63e Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 15 Jan 2020 04:38:56 +0900 Subject: [PATCH 033/229] Add methods to send connected/disconnected state. Also add methods to set the legacy subtype and the APN name. These have to be added together because they have to be used together. Bug: 138306002 Bug: 139268426 Test: atest FrameworksNetTests FrameworksWifiTests FrameworksTelephonyTests Change-Id: Ie90b8d290eab490061d5cb066744b67d597b9469 --- core/java/android/net/NetworkAgent.java | 94 ++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 61a1484cef..7ab981adae 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -33,6 +33,7 @@ import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; import java.util.ArrayList; +import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -53,6 +54,12 @@ public abstract class NetworkAgent { @NonNull public final Network network; + // Whether this NetworkAgent is using the legacy (never unhidden) API. The difference is + // that the legacy API uses NetworkInfo to convey the state, while the current API is + // exposing methods to manage it and generate it internally instead. + // TODO : remove this as soon as all agents have been converted. + private final boolean mIsLegacy; + private final Handler mHandler; private volatile AsyncChannel mAsyncChannel; private final String LOG_TAG; @@ -64,6 +71,10 @@ public abstract class NetworkAgent { private static final long BW_REFRESH_MIN_WIN_MS = 500; private boolean mBandwidthUpdateScheduled = false; private AtomicBoolean mBandwidthUpdatePending = new AtomicBoolean(false); + // Not used by legacy agents. Non-legacy agents use this to convert the NetworkAgent system API + // into the internal API of ConnectivityService. + @NonNull + private NetworkInfo mNetworkInfo; /** * The ID of the {@link NetworkProvider} that created this object, or @@ -284,7 +295,7 @@ public abstract class NetworkAgent { public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, int providerId) { - this(looper, context, logTag, nc, lp, score, config, providerId, ni); + this(looper, context, logTag, nc, lp, score, config, providerId, ni, true /* legacy */); } private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) { @@ -310,15 +321,17 @@ public abstract class NetworkAgent { @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { this(looper, context, logTag, nc, lp, score, config, provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(), - getLegacyNetworkInfo(config)); + getLegacyNetworkInfo(config), false /* legacy */); } private NetworkAgent(Looper looper, Context context, String logTag, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, int providerId, - NetworkInfo ni) { + NetworkInfo ni, boolean legacy) { mHandler = new NetworkAgentHandler(looper); LOG_TAG = logTag; mContext = context; + mIsLegacy = legacy; + mNetworkInfo = new NetworkInfo(ni); this.providerId = providerId; if (ni == null || nc == null || lp == null) { throw new IllegalArgumentException(); @@ -483,15 +496,89 @@ public abstract class NetworkAgent { * @param linkProperties the new LinkProperties. */ public void sendLinkProperties(@NonNull LinkProperties linkProperties) { + Objects.requireNonNull(linkProperties); queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties)); } + /** + * Inform ConnectivityService that this agent has now connected. + */ + public void setConnected() { + if (mIsLegacy) { + throw new UnsupportedOperationException( + "Legacy agents can't call setConnected."); + } + mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); + queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); + } + + /** + * Unregister this network agent. + * + * This signals the network has disconnected and ends its lifecycle. After this is called, + * the network is torn down and this agent can no longer be used. + */ + public void unregister() { + if (mIsLegacy) { + throw new UnsupportedOperationException( + "Legacy agents can't call unregister."); + } + mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null); + queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); + } + + /** + * Change the legacy subtype of this network agent. + * + * This is only for backward compatibility and should not be used by non-legacy network agents, + * or agents that did not use to set a subtype. As such, only TYPE_MOBILE type agents can use + * this and others will be thrown an exception if they try. + * + * @deprecated this is for backward compatibility only. + * @param legacySubtype the legacy subtype. + */ + @Deprecated + public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) { + if (mIsLegacy) { + throw new UnsupportedOperationException("Legacy agents can't call setLegacySubtype."); + } + mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName); + queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); + } + + /** + * Set the ExtraInfo of this network agent. + * + * This sets the ExtraInfo field inside the NetworkInfo returned by legacy public API and the + * broadcasts about the corresponding Network. + * This is only for backward compatibility and should not be used by non-legacy network agents, + * who will be thrown an exception if they try. The extra info should only be : + *
    + *
  • For cellular agents, the APN name.
  • + *
  • For ethernet agents, the interface name.
  • + *
+ * + * @deprecated this is for backward compatibility only. + * @param extraInfo the ExtraInfo. + */ + @Deprecated + public void setLegacyExtraInfo(@Nullable final String extraInfo) { + if (mIsLegacy) { + throw new UnsupportedOperationException("Legacy agents can't call setLegacyExtraInfo."); + } + mNetworkInfo.setExtraInfo(extraInfo); + queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); + } + /** * Must be called by the agent when it has a new NetworkInfo object. * @hide TODO: expose something better. */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public void sendNetworkInfo(NetworkInfo networkInfo) { + if (!mIsLegacy) { + throw new UnsupportedOperationException("Only legacy agents can call sendNetworkInfo."); + } queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo)); } @@ -500,6 +587,7 @@ public abstract class NetworkAgent { * @param networkCapabilities the new NetworkCapabilities. */ public void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) { + Objects.requireNonNull(networkCapabilities); mBandwidthUpdatePending.set(false); mLastBwRefreshTime = System.currentTimeMillis(); queueOrSendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED, From 01b6ba40532fda1b377461d07024a7cf9a567f2d Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 16 Jan 2020 17:13:26 +0900 Subject: [PATCH 034/229] Move NetworkAgent#register to a new method. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling IPC in a constructor is unusual and confusing, and can be considered bad form. There are multiple reasons for this : • Users can't obtain an instance of the class without calling the constructor, but they can't always afford an IPC where they need this, forcing them to know about the implementation detail and sometimes design around it. • On a related but generalized note, constructors should usually be fast for the same range of reasons. • Having a separate method to register the agent simply gives more flexibility to the app. • It's also a lot easier to test. But also we can't fix it without an update to the API, so here it is. Another reason for doing this is consistency with the NetworkProvider API. Bug: 138306002 Bug: 139268426 Test: atest FrameworksNetTests FrameworksWifiTests FrameworksTelephonyTests Change-Id: I1ee5c7b1353d581e487c8a8a159009bebd781643 --- core/java/android/net/NetworkAgent.java | 71 +++++++++++++++---- .../android/server/TestNetworkService.java | 4 +- .../android/server/NetworkAgentWrapper.java | 2 +- .../server/ConnectivityServiceTest.java | 2 +- 4 files changed, 62 insertions(+), 17 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 7ab981adae..7cc78f7389 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -51,8 +51,8 @@ public abstract class NetworkAgent { /** * The {@link Network} corresponding to this object. */ - @NonNull - public final Network network; + @Nullable + private volatile Network mNetwork; // Whether this NetworkAgent is using the legacy (never unhidden) API. The difference is // that the legacy API uses NetworkInfo to convey the state, while the current API is @@ -65,7 +65,6 @@ public abstract class NetworkAgent { private final String LOG_TAG; private static final boolean DBG = true; private static final boolean VDBG = false; - private final Context mContext; private final ArrayListmPreConnectedQueue = new ArrayList(); private volatile long mLastBwRefreshTime = 0; private static final long BW_REFRESH_MIN_WIN_MS = 500; @@ -277,18 +276,21 @@ public abstract class NetworkAgent { public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) { this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE); + // Register done by the constructor called in the previous line } /** @hide TODO: remove and replace usage with the public constructor. */ public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) { this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE); + // Register done by the constructor called in the previous line } /** @hide TODO: remove and replace usage with the public constructor. */ public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, int providerId) { this(looper, context, logTag, ni, nc, lp, score, null, providerId); + // Register done by the constructor called in the previous line } /** @hide TODO: remove and replace usage with the public constructor. */ @@ -296,6 +298,7 @@ public abstract class NetworkAgent { NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, int providerId) { this(looper, context, logTag, nc, lp, score, config, providerId, ni, true /* legacy */); + register(); } private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) { @@ -324,12 +327,32 @@ public abstract class NetworkAgent { getLegacyNetworkInfo(config), false /* legacy */); } - private NetworkAgent(Looper looper, Context context, String logTag, NetworkCapabilities nc, - LinkProperties lp, int score, NetworkAgentConfig config, int providerId, - NetworkInfo ni, boolean legacy) { + private static class InitialConfiguration { + public final Context context; + public final NetworkCapabilities capabilities; + public final LinkProperties properties; + public final int score; + public final NetworkAgentConfig config; + public final NetworkInfo info; + InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities, + @NonNull LinkProperties properties, int score, @NonNull NetworkAgentConfig config, + @NonNull NetworkInfo info) { + this.context = context; + this.capabilities = capabilities; + this.properties = properties; + this.score = score; + this.config = config; + this.info = info; + } + } + private volatile InitialConfiguration mInitialConfiguration; + + private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag, + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, + @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni, + boolean legacy) { mHandler = new NetworkAgentHandler(looper); LOG_TAG = logTag; - mContext = context; mIsLegacy = legacy; mNetworkInfo = new NetworkInfo(ni); this.providerId = providerId; @@ -337,12 +360,8 @@ public abstract class NetworkAgent { throw new IllegalArgumentException(); } - if (VDBG) log("Registering NetworkAgent"); - ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService( - Context.CONNECTIVITY_SERVICE); - network = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(ni), - new LinkProperties(lp), new NetworkCapabilities(nc), score, config, - providerId); + mInitialConfiguration = new InitialConfiguration(context, new NetworkCapabilities(nc), + new LinkProperties(lp), score, config, ni); } private class NetworkAgentHandler extends Handler { @@ -464,6 +483,32 @@ public abstract class NetworkAgent { } } + /** + * Register this network agent with ConnectivityService. + * @return the Network associated with this network agent (which can also be obtained later + * by calling getNetwork() on this agent). + */ + @NonNull + public Network register() { + if (VDBG) log("Registering NetworkAgent"); + final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context + .getSystemService(Context.CONNECTIVITY_SERVICE); + mNetwork = cm.registerNetworkAgent(new Messenger(mHandler), + new NetworkInfo(mInitialConfiguration.info), + mInitialConfiguration.properties, mInitialConfiguration.capabilities, + mInitialConfiguration.score, mInitialConfiguration.config, providerId); + mInitialConfiguration = null; // All this memory can now be GC'd + return mNetwork; + } + + /** + * @return The Network associated with this agent, or null if it's not registered yet. + */ + @Nullable + public Network getNetwork() { + return mNetwork; + } + private void queueOrSendMessage(int what, Object obj) { queueOrSendMessage(what, 0, 0, obj); } diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index ed3bab97ca..35a980286d 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -218,7 +218,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { // Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up // resources, even for binder death or unwanted calls. synchronized (mTestNetworkTracker) { - mTestNetworkTracker.remove(network.netId); + mTestNetworkTracker.remove(getNetwork().netId); } } } @@ -337,7 +337,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { callingUid, binder); - mTestNetworkTracker.put(agent.network.netId, agent); + mTestNetworkTracker.put(agent.getNetwork().netId, agent); } } catch (SocketException e) { throw new UncheckedIOException(e); diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index 1c69209863..a35fb407bc 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -222,7 +222,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { @Override public Network getNetwork() { - return mNetworkAgent.network; + return mNetworkAgent.getNetwork(); } public void expectPreventReconnectReceived(long timeoutMs) { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 1901a1db63..4e29334727 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -575,7 +575,7 @@ public class ConnectivityServiceTest { } }; - assertEquals(na.network.netId, nmNetworkCaptor.getValue().netId); + assertEquals(na.getNetwork().netId, nmNetworkCaptor.getValue().netId); mNmCallbacks = nmCbCaptor.getValue(); mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor); From 5f617f9a07364b6021c7942f30755510db2bc7e9 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 17 Jan 2020 14:38:48 +0900 Subject: [PATCH 035/229] New NetworkAgentConfig API to replace NetworkInfo WiFi stuff. Bug: 139268426 Test: FrameworkWifiTests Change-Id: Id13fcf41e05fd1eb26c86717e2684c724b94e401 --- core/java/android/net/NetworkAgentConfig.java | 113 +++++++++++++++++- .../android/net/NetworkAgentConfigTest.kt | 39 ++++++ 2 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 tests/net/common/java/android/net/NetworkAgentConfigTest.kt diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java index 2c5a113a93..7e2db4a4fa 100644 --- a/core/java/android/net/NetworkAgentConfig.java +++ b/core/java/android/net/NetworkAgentConfig.java @@ -22,6 +22,8 @@ import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import java.util.Objects; + /** * Allows a network transport to provide the system with policy and configuration information about * a particular network when registering a {@link NetworkAgent}. This information cannot change once the agent is registered. @@ -51,23 +53,47 @@ public final class NetworkAgentConfig implements Parcelable { */ public boolean explicitlySelected; + /** + * @return whether this network was explicitly selected by the user. + */ + public boolean isExplicitlySelected() { + return explicitlySelected; + } + /** * Set if the user desires to use this network even if it is unvalidated. This field has meaning * only if {@link explicitlySelected} is true. If it is, this field must also be set to the * appropriate value based on previous user choice. * + * TODO : rename this field to match its accessor * @hide */ public boolean acceptUnvalidated; + /** + * @return whether the system should accept this network even if it doesn't validate. + */ + public boolean isUnvalidatedConnectivityAcceptable() { + return acceptUnvalidated; + } + /** * Whether the user explicitly set that this network should be validated even if presence of * only partial internet connectivity. * + * TODO : rename this field to match its accessor * @hide */ public boolean acceptPartialConnectivity; + /** + * @return whether the system should validate this network even if it only offers partial + * Internet connectivity. + */ + public boolean isPartialConnectivityAcceptable() { + return acceptPartialConnectivity; + } + /** * Set to avoid surfacing the "Sign in to network" notification. * if carrier receivers/apps are registered to handle the carrier-specific provisioning @@ -134,9 +160,11 @@ public final class NetworkAgentConfig implements Parcelable { * Set to true if the PRIVATE_DNS_BROKEN notification has shown for this network. * Reset this bit when private DNS mode is changed from strict mode to opportunistic/off mode. * + * This is not parceled, because it would not make sense. + * * @hide */ - public boolean hasShownBroken; + public transient boolean hasShownBroken; /** * The name of the legacy network type. It's a free-form string used in logging. @@ -163,6 +191,7 @@ public final class NetworkAgentConfig implements Parcelable { allowBypass = nac.allowBypass; explicitlySelected = nac.explicitlySelected; acceptUnvalidated = nac.acceptUnvalidated; + acceptPartialConnectivity = nac.acceptPartialConnectivity; subscriberId = nac.subscriberId; provisioningNotificationDisabled = nac.provisioningNotificationDisabled; skip464xlat = nac.skip464xlat; @@ -177,6 +206,43 @@ public final class NetworkAgentConfig implements Parcelable { public static class Builder { private final NetworkAgentConfig mConfig = new NetworkAgentConfig(); + /** + * Sets whether the network was explicitly selected by the user. + * + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setExplicitlySelected(final boolean explicitlySelected) { + mConfig.explicitlySelected = explicitlySelected; + return this; + } + + /** + * Sets whether the system should validate this network even if it is found not to offer + * Internet connectivity. + * + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setUnvalidatedConnectivityAcceptable( + final boolean unvalidatedConnectivityAcceptable) { + mConfig.acceptUnvalidated = unvalidatedConnectivityAcceptable; + return this; + } + + /** + * Sets whether the system should validate this network even if it is found to only offer + * partial Internet connectivity. + * + * @return this builder, to facilitate chaining. + */ + @NonNull + public Builder setPartialConnectivityAcceptable( + final boolean partialConnectivityAcceptable) { + mConfig.acceptPartialConnectivity = partialConnectivityAcceptable; + return this; + } + /** * Sets the subscriber ID for this network. * @@ -244,6 +310,45 @@ public final class NetworkAgentConfig implements Parcelable { } } + @Override + public boolean equals(final Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + final NetworkAgentConfig that = (NetworkAgentConfig) o; + return allowBypass == that.allowBypass + && explicitlySelected == that.explicitlySelected + && acceptUnvalidated == that.acceptUnvalidated + && acceptPartialConnectivity == that.acceptPartialConnectivity + && provisioningNotificationDisabled == that.provisioningNotificationDisabled + && skip464xlat == that.skip464xlat + && legacyType == that.legacyType + && Objects.equals(subscriberId, that.subscriberId) + && Objects.equals(legacyTypeName, that.legacyTypeName); + } + + @Override + public int hashCode() { + return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated, + acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId, + skip464xlat, legacyType, legacyTypeName); + } + + @Override + public String toString() { + return "NetworkAgentConfig {" + + " allowBypass = " + allowBypass + + ", explicitlySelected = " + explicitlySelected + + ", acceptUnvalidated = " + acceptUnvalidated + + ", acceptPartialConnectivity = " + acceptPartialConnectivity + + ", provisioningNotificationDisabled = " + provisioningNotificationDisabled + + ", subscriberId = '" + subscriberId + '\'' + + ", skip464xlat = " + skip464xlat + + ", legacyType = " + legacyType + + ", hasShownBroken = " + hasShownBroken + + ", legacyTypeName = '" + legacyTypeName + '\'' + + "}"; + } + @Override public int describeContents() { return 0; @@ -254,9 +359,12 @@ public final class NetworkAgentConfig implements Parcelable { out.writeInt(allowBypass ? 1 : 0); out.writeInt(explicitlySelected ? 1 : 0); out.writeInt(acceptUnvalidated ? 1 : 0); + out.writeInt(acceptPartialConnectivity ? 1 : 0); out.writeString(subscriberId); out.writeInt(provisioningNotificationDisabled ? 1 : 0); out.writeInt(skip464xlat ? 1 : 0); + out.writeInt(legacyType); + out.writeString(legacyTypeName); } public static final @NonNull Creator CREATOR = @@ -267,9 +375,12 @@ public final class NetworkAgentConfig implements Parcelable { networkAgentConfig.allowBypass = in.readInt() != 0; networkAgentConfig.explicitlySelected = in.readInt() != 0; networkAgentConfig.acceptUnvalidated = in.readInt() != 0; + networkAgentConfig.acceptPartialConnectivity = in.readInt() != 0; networkAgentConfig.subscriberId = in.readString(); networkAgentConfig.provisioningNotificationDisabled = in.readInt() != 0; networkAgentConfig.skip464xlat = in.readInt() != 0; + networkAgentConfig.legacyType = in.readInt(); + networkAgentConfig.legacyTypeName = in.readString(); return networkAgentConfig; } diff --git a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt new file mode 100644 index 0000000000..d250ad3a2b --- /dev/null +++ b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 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 androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 +import com.android.testutils.assertParcelSane +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +@SmallTest +class NetworkAgentConfigTest { + @Test + fun testParcelNetworkAgentConfig() { + val config = NetworkAgentConfig.Builder().apply { + setExplicitlySelected(true) + setLegacyType(ConnectivityManager.TYPE_ETHERNET) + setSubscriberId("MySubId") + setPartialConnectivityAcceptable(false) + setUnvalidatedConnectivityAcceptable(true) + }.build() + assertParcelSane(config, 9) + } +} From d30bfe01746f60b514fa5bc8b27953d0c8a599e3 Mon Sep 17 00:00:00 2001 From: Sarah Chin Date: Thu, 16 Jan 2020 11:19:52 -0800 Subject: [PATCH 036/229] API changes for IPv6 MTU support Change mtu->mtuV4 and add mtuV6 for DataProfile and DataCallResult Add mtu to RouteInfo and update test Test: atest FrameworksTelephonyTests Bug: 146668814 Change-Id: I43c7e088e46e40f38d8114548e0fc4e39d7f91cb --- core/java/android/net/RouteInfo.java | 61 ++++++++++++++++--- .../java/android/net/RouteInfoTest.java | 12 +++- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index e088094576..2b9e9fe81b 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -105,6 +105,11 @@ public final class RouteInfo implements Parcelable { */ private final int mType; + /** + * The maximum transmission unit size for this route. + */ + private final int mMtu; + // Derived data members. // TODO: remove these. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) @@ -133,6 +138,31 @@ public final class RouteInfo implements Parcelable { @TestApi public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway, @Nullable String iface, @RouteType int type) { + this(destination, gateway, iface, type, 0); + } + + /** + * Constructs a RouteInfo object. + * + * If destination is null, then gateway must be specified and the + * constructed route is either the IPv4 default route 0.0.0.0 + * if the gateway is an instance of {@link Inet4Address}, or the IPv6 default + * route ::/0 if gateway is an instance of + * {@link Inet6Address}. + *

+ * destination and gateway may not both be null. + * + * @param destination the destination prefix + * @param gateway the IP address to route packets through + * @param iface the interface name to send packets on + * @param type the type of this route + * @param mtu the maximum transmission unit size for this route + * + * @hide + */ + @SystemApi + public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway, + @Nullable String iface, @RouteType int type, int mtu) { switch (type) { case RTN_UNICAST: case RTN_UNREACHABLE: @@ -162,7 +192,7 @@ public final class RouteInfo implements Parcelable { } else { // no destination, no gateway. invalid. throw new IllegalArgumentException("Invalid arguments passed in: " + gateway + "," + - destination); + destination); } } // TODO: set mGateway to null if there is no gateway. This is more correct, saves space, and @@ -177,10 +207,10 @@ public final class RouteInfo implements Parcelable { } mHasGateway = (!gateway.isAnyLocalAddress()); - if ((destination.getAddress() instanceof Inet4Address && - (gateway instanceof Inet4Address == false)) || - (destination.getAddress() instanceof Inet6Address && - (gateway instanceof Inet6Address == false))) { + if ((destination.getAddress() instanceof Inet4Address + && !(gateway instanceof Inet4Address)) + || (destination.getAddress() instanceof Inet6Address + && !(gateway instanceof Inet6Address))) { throw new IllegalArgumentException("address family mismatch in RouteInfo constructor"); } mDestination = destination; // IpPrefix objects are immutable. @@ -188,6 +218,7 @@ public final class RouteInfo implements Parcelable { mInterface = iface; // Strings are immutable. mType = type; mIsHost = isHost(); + mMtu = mtu; } /** @@ -373,6 +404,17 @@ public final class RouteInfo implements Parcelable { return mType; } + /** + * Retrieves the MTU size for this route. + * + * @return The MTU size, or 0 if it has not been set. + * @hide + */ + @SystemApi + public int getMtu() { + return mMtu; + } + /** * Indicates if this route is a default route (ie, has no destination specified). * @@ -463,6 +505,7 @@ public final class RouteInfo implements Parcelable { val += " unknown type " + mType; } } + val += " mtu " + mMtu; return val; } @@ -480,7 +523,7 @@ public final class RouteInfo implements Parcelable { return Objects.equals(mDestination, target.getDestination()) && Objects.equals(mGateway, target.getGateway()) && Objects.equals(mInterface, target.getInterface()) && - mType == target.getType(); + mType == target.getType() && mMtu == target.getMtu(); } /** @@ -490,7 +533,7 @@ public final class RouteInfo implements Parcelable { return (mDestination.hashCode() * 41) + (mGateway == null ? 0 :mGateway.hashCode() * 47) + (mInterface == null ? 0 :mInterface.hashCode() * 67) - + (mType * 71); + + (mType * 71) + (mMtu * 89); } /** @@ -509,6 +552,7 @@ public final class RouteInfo implements Parcelable { dest.writeByteArray(gatewayBytes); dest.writeString(mInterface); dest.writeInt(mType); + dest.writeInt(mMtu); } /** @@ -527,8 +571,9 @@ public final class RouteInfo implements Parcelable { String iface = in.readString(); int type = in.readInt(); + int mtu = in.readInt(); - return new RouteInfo(dest, gateway, iface, type); + return new RouteInfo(dest, gateway, iface, type, mtu); } public RouteInfo[] newArray(int size) { diff --git a/tests/net/common/java/android/net/RouteInfoTest.java b/tests/net/common/java/android/net/RouteInfoTest.java index 5ce8436308..fe51b3af4d 100644 --- a/tests/net/common/java/android/net/RouteInfoTest.java +++ b/tests/net/common/java/android/net/RouteInfoTest.java @@ -258,6 +258,16 @@ public class RouteInfoTest extends TestCase { assertParcelingIsLossless(r); r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0"); - assertParcelSane(r, 6); + assertParcelSane(r, 7); + } + + public void testMtu() { + RouteInfo r; + r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0", + RouteInfo.RTN_UNICAST, 1500); + assertEquals(1500, r.getMtu()); + + r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0"); + assertEquals(0, r.getMtu()); } } From 04a2e63ed850f221c2bc1d36416eaab29acda31f Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 22 Jan 2020 22:52:03 +0900 Subject: [PATCH 037/229] Update NetworkInfo public API. Wifi needs to create these objects so it can include them in the broadcasts. Bug: 135998869 Test: FrameworksWifiTests Change-Id: Ic50d9b5c65e8771708620badc3bc242a8ffbb5cc --- core/java/android/net/NetworkInfo.java | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java index d0c5363165..08fe159b27 100644 --- a/core/java/android/net/NetworkInfo.java +++ b/core/java/android/net/NetworkInfo.java @@ -17,9 +17,11 @@ package android.net; import android.annotation.NonNull; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.Annotation.NetworkType; import com.android.internal.annotations.VisibleForTesting; @@ -150,10 +152,19 @@ public class NetworkInfo implements Parcelable { private boolean mIsRoaming; /** - * @hide + * Create a new instance of NetworkInfo. + * + * This may be useful for apps to write unit tests. + * + * @param type the legacy type of the network, as one of the ConnectivityManager.TYPE_* + * constants. + * @param subtype the subtype if applicable, as one of the TelephonyManager.NETWORK_TYPE_* + * constants. + * @param typeName a human-readable string for the network type, or an empty string or null. + * @param subtypeName a human-readable string for the subtype, or an empty string or null. */ - @UnsupportedAppUsage - public NetworkInfo(int type, int subtype, String typeName, String subtypeName) { + public NetworkInfo(int type, @NetworkType int subtype, + @Nullable String typeName, @Nullable String subtypeName) { if (!ConnectivityManager.isNetworkTypeValid(type) && type != ConnectivityManager.TYPE_NONE) { throw new IllegalArgumentException("Invalid network type: " + type); @@ -462,17 +473,19 @@ public class NetworkInfo implements Parcelable { /** * Sets the fine-grained state of the network. + * + * This is only useful for testing. + * * @param detailedState the {@link DetailedState}. * @param reason a {@code String} indicating the reason for the state change, * if one was supplied. May be {@code null}. * @param extraInfo an optional {@code String} providing addditional network state * information passed up from the lower networking layers. * @deprecated Use {@link NetworkCapabilities} instead. - * @hide */ @Deprecated - @UnsupportedAppUsage - public void setDetailedState(DetailedState detailedState, String reason, String extraInfo) { + public void setDetailedState(@NonNull DetailedState detailedState, @Nullable String reason, + @Nullable String extraInfo) { synchronized (this) { this.mDetailedState = detailedState; this.mState = stateMap.get(detailedState); From 5058987bd72e9f251d1544a75d47db3a160a8adb Mon Sep 17 00:00:00 2001 From: markchien Date: Tue, 21 Jan 2020 13:11:06 +0800 Subject: [PATCH 038/229] Make TetheringManager to system API Also deprecated tethering APIs in ConnectivityManager. Will have follow up change to remove @hide tethering function in ConnectivityManager. Bug: 145093446 Bug: 148038547 Test: -build, flash, boot -atest TetheringTests Change-Id: Ia432057bf9056727c4a0ca97d160a49274d33581 --- .../java/android/net/ConnectivityManager.java | 198 ++++++++++++++---- 1 file changed, 162 insertions(+), 36 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 8ba3131a83..753e754602 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -33,6 +33,7 @@ import android.content.Context; import android.content.Intent; import android.net.IpSecManager.UdpEncapsulationSocket; import android.net.SocketKeepalive.Callback; +import android.net.TetheringManager.TetheringEventCallback; import android.os.Binder; import android.os.Build; import android.os.Build.VERSION_CODES; @@ -58,6 +59,7 @@ import android.util.ArrayMap; import android.util.Log; import android.util.SparseIntArray; +import com.android.internal.annotations.GuardedBy; import com.android.internal.util.Preconditions; import com.android.internal.util.Protocol; @@ -75,6 +77,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -484,34 +487,35 @@ public class ConnectivityManager { * enable if any. * @hide */ - public static final String EXTRA_ADD_TETHER_TYPE = TetheringManager.EXTRA_ADD_TETHER_TYPE; + public static final String EXTRA_ADD_TETHER_TYPE = TetheringConstants.EXTRA_ADD_TETHER_TYPE; /** * Extra used for communicating with the TetherService. Includes the type of tethering for * which to cancel provisioning. * @hide */ - public static final String EXTRA_REM_TETHER_TYPE = TetheringManager.EXTRA_REM_TETHER_TYPE; + public static final String EXTRA_REM_TETHER_TYPE = TetheringConstants.EXTRA_REM_TETHER_TYPE; /** * Extra used for communicating with the TetherService. True to schedule a recheck of tether * provisioning. * @hide */ - public static final String EXTRA_SET_ALARM = TetheringManager.EXTRA_SET_ALARM; + public static final String EXTRA_SET_ALARM = TetheringConstants.EXTRA_SET_ALARM; /** * Tells the TetherService to run a provision check now. * @hide */ - public static final String EXTRA_RUN_PROVISION = TetheringManager.EXTRA_RUN_PROVISION; + public static final String EXTRA_RUN_PROVISION = TetheringConstants.EXTRA_RUN_PROVISION; /** * Extra used for communicating with the TetherService. Contains the {@link ResultReceiver} * which will receive provisioning results. Can be left empty. * @hide */ - public static final String EXTRA_PROVISION_CALLBACK = TetheringManager.EXTRA_PROVISION_CALLBACK; + public static final String EXTRA_PROVISION_CALLBACK = + TetheringConstants.EXTRA_PROVISION_CALLBACK; /** * The absence of a connection type. @@ -2368,10 +2372,12 @@ public class ConnectivityManager { * * @return an array of 0 or more Strings of tetherable interface names. * + * @deprecated Use {@link TetheringEventCallback#onTetherableInterfacesChanged(List)} instead. * {@hide} */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage + @Deprecated public String[] getTetherableIfaces() { return getTetheringManager().getTetherableIfaces(); } @@ -2381,10 +2387,12 @@ public class ConnectivityManager { * * @return an array of 0 or more String of currently tethered interface names. * + * @deprecated Use {@link TetheringEventCallback#onTetherableInterfacesChanged(List)} instead. * {@hide} */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage + @Deprecated public String[] getTetheredIfaces() { return getTetheringManager().getTetheredIfaces(); } @@ -2400,10 +2408,12 @@ public class ConnectivityManager { * @return an array of 0 or more String indicating the interface names * which failed to tether. * + * @deprecated Use {@link TetheringEventCallback#onError(String, int)} instead. * {@hide} */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage + @Deprecated public String[] getTetheringErroredIfaces() { return getTetheringManager().getTetheringErroredIfaces(); } @@ -2412,9 +2422,11 @@ public class ConnectivityManager { * Get the set of tethered dhcp ranges. * * @return an array of 0 or more {@code String} of tethered dhcp ranges. + * @deprecated This API just return the default value which is not used in DhcpServer. * {@hide} */ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + @Deprecated public String[] getTetheredDhcpRanges() { return getTetheringManager().getTetheredDhcpRanges(); } @@ -2467,6 +2479,7 @@ public class ConnectivityManager { * {@hide} */ @UnsupportedAppUsage + @Deprecated public int untether(String iface) { return getTetheringManager().untether(iface); } @@ -2487,6 +2500,7 @@ public class ConnectivityManager { * * @return a boolean - {@code true} indicating Tethering is supported. * + * @deprecated Use {@link TetheringEventCallback#onTetheringSupported(boolean)} instead. * {@hide} */ @SystemApi @@ -2573,9 +2587,12 @@ public class ConnectivityManager { * {@link ConnectivityManager.TETHERING_WIFI}, * {@link ConnectivityManager.TETHERING_USB}, or * {@link ConnectivityManager.TETHERING_BLUETOOTH}. + * + * @deprecated Use {@link TetheringManager#stopTethering} instead. * @hide */ @SystemApi + @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int type) { getTetheringManager().stopTethering(type); @@ -2585,9 +2602,11 @@ public class ConnectivityManager { * Callback for use with {@link registerTetheringEventCallback} to find out tethering * upstream status. * - *@hide + * @deprecated Use {@line TetheringManager#OnTetheringEventCallback} instead. + * @hide */ @SystemApi + @Deprecated public abstract static class OnTetheringEventCallback { /** @@ -2600,6 +2619,10 @@ public class ConnectivityManager { public void onUpstreamChanged(@Nullable Network network) {} } + @GuardedBy("mTetheringEventCallbacks") + private final ArrayMap + mTetheringEventCallbacks = new ArrayMap<>(); + /** * Start listening to tethering change events. Any new added callback will receive the last * tethering status right away. If callback is registered when tethering has no upstream or @@ -2608,16 +2631,30 @@ public class ConnectivityManager { * * @param executor the executor on which callback will be invoked. * @param callback the callback to be called when tethering has change events. + * + * @deprecated Use {@line TetheringManager#registerTetheringEventCallback} instead. * @hide */ @SystemApi + @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback( @NonNull @CallbackExecutor Executor executor, @NonNull final OnTetheringEventCallback callback) { Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null."); - getTetheringManager().registerTetheringEventCallback(executor, callback); + final TetheringEventCallback tetherCallback = + new TetheringEventCallback() { + @Override + public void onUpstreamChanged(@Nullable Network network) { + callback.onUpstreamChanged(network); + } + }; + + synchronized (mTetheringEventCallbacks) { + mTetheringEventCallbacks.put(callback, tetherCallback); + getTetheringManager().registerTetheringEventCallback(executor, tetherCallback); + } } /** @@ -2625,13 +2662,21 @@ public class ConnectivityManager { * {@link #registerTetheringEventCallback}. * * @param callback previously registered callback. + * + * @deprecated Use {@link TetheringManager#unregisterTetheringEventCallback} instead. * @hide */ @SystemApi + @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback( @NonNull final OnTetheringEventCallback callback) { - getTetheringManager().unregisterTetheringEventCallback(callback); + Objects.requireNonNull(callback, "The callback must be non-null"); + synchronized (mTetheringEventCallbacks) { + final TetheringEventCallback tetherCallback = + mTetheringEventCallbacks.remove(callback); + getTetheringManager().unregisterTetheringEventCallback(tetherCallback); + } } @@ -2643,10 +2688,12 @@ public class ConnectivityManager { * @return an array of 0 or more regular expression Strings defining * what interfaces are considered tetherable usb interfaces. * + * @deprecated Use {@link TetheringEventCallback#onTetherableInterfaceRegexpsChanged} instead. * {@hide} */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage + @Deprecated public String[] getTetherableUsbRegexs() { return getTetheringManager().getTetherableUsbRegexs(); } @@ -2659,10 +2706,12 @@ public class ConnectivityManager { * @return an array of 0 or more regular expression Strings defining * what interfaces are considered tetherable wifi interfaces. * + * @deprecated Use {@link TetheringEventCallback#onTetherableInterfaceRegexpsChanged} instead. * {@hide} */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage + @Deprecated public String[] getTetherableWifiRegexs() { return getTetheringManager().getTetherableWifiRegexs(); } @@ -2675,10 +2724,13 @@ public class ConnectivityManager { * @return an array of 0 or more regular expression Strings defining * what interfaces are considered tetherable bluetooth interfaces. * + * @deprecated Use {@link TetheringEventCallback#onTetherableInterfaceRegexpsChanged( + *TetheringManager.TetheringInterfaceRegexps)} instead. * {@hide} */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage + @Deprecated public String[] getTetherableBluetoothRegexs() { return getTetheringManager().getTetherableBluetoothRegexs(); } @@ -2705,37 +2757,104 @@ public class ConnectivityManager { return getTetheringManager().setUsbTethering(enable); } - /** {@hide} */ + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_NO_ERROR}. + * {@hide} + */ @SystemApi - public static final int TETHER_ERROR_NO_ERROR = 0; - /** {@hide} */ - public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; - /** {@hide} */ - public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; - /** {@hide} */ - public static final int TETHER_ERROR_UNSUPPORTED = 3; - /** {@hide} */ - public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; - /** {@hide} */ - public static final int TETHER_ERROR_MASTER_ERROR = 5; - /** {@hide} */ - public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; - /** {@hide} */ - public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; - /** {@hide} */ - public static final int TETHER_ERROR_ENABLE_NAT_ERROR = 8; - /** {@hide} */ - public static final int TETHER_ERROR_DISABLE_NAT_ERROR = 9; - /** {@hide} */ - public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; - /** {@hide} */ + @Deprecated + public static final int TETHER_ERROR_NO_ERROR = TetheringManager.TETHER_ERROR_NO_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNKNOWN_IFACE}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_UNKNOWN_IFACE = + TetheringManager.TETHER_ERROR_UNKNOWN_IFACE; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_SERVICE_UNAVAIL}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_SERVICE_UNAVAIL = + TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNSUPPORTED}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_UNSUPPORTED = TetheringManager.TETHER_ERROR_UNSUPPORTED; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNAVAIL_IFACE}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_UNAVAIL_IFACE = + TetheringManager.TETHER_ERROR_UNAVAIL_IFACE; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_MASTER_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_MASTER_ERROR = TetheringManager.TETHER_ERROR_MASTER_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_TETHER_IFACE_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_TETHER_IFACE_ERROR = + TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNTETHER_IFACE_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = + TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_ENABLE_NAT_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_ENABLE_NAT_ERROR = + TetheringManager.TETHER_ERROR_ENABLE_NAT_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_DISABLE_NAT_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_DISABLE_NAT_ERROR = + TetheringManager.TETHER_ERROR_DISABLE_NAT_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_IFACE_CFG_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_IFACE_CFG_ERROR = + TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_PROVISION_FAILED}. + * {@hide} + */ @SystemApi - public static final int TETHER_ERROR_PROVISION_FAILED = 11; - /** {@hide} */ - public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; - /** {@hide} */ + @Deprecated + public static final int TETHER_ERROR_PROVISION_FAILED = + TetheringManager.TETHER_ERROR_PROVISION_FAILED; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_DHCPSERVER_ERROR}. + * {@hide} + */ + @Deprecated + public static final int TETHER_ERROR_DHCPSERVER_ERROR = + TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR; + /** + * @deprecated Use {@link TetheringManager#TETHER_ERROR_ENTITLEMENT_UNKNOWN}. + * {@hide} + */ @SystemApi - public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; + @Deprecated + public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = + TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN; /** * Get a more detailed error code after a Tethering or Untethering @@ -2745,10 +2864,12 @@ public class ConnectivityManager { * @return error The error code of the last error tethering or untethering the named * interface * + * @deprecated Use {@link TetheringEventCallback#onError(String, int)} instead. * {@hide} */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @UnsupportedAppUsage + @Deprecated public int getLastTetherError(String iface) { return getTetheringManager().getLastTetherError(iface); } @@ -2766,9 +2887,12 @@ public class ConnectivityManager { /** * Callback for use with {@link #getLatestTetheringEntitlementResult} to find out whether * entitlement succeeded. + * + * @deprecated Use {@link TetheringManager#OnTetheringEntitlementResultListener} instead. * @hide */ @SystemApi + @Deprecated public interface OnTetheringEntitlementResultListener { /** * Called to notify entitlement result. @@ -2798,9 +2922,11 @@ public class ConnectivityManager { * @param listener an {@link OnTetheringEntitlementResultListener} which will be called to * notify the caller of the result of entitlement check. The listener may be called zero * or one time. + * @deprecated Use {@link TetheringManager#requestLatestTetheringEntitlementResult} instead. * {@hide} */ @SystemApi + @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int type, boolean showEntitlementUi, @NonNull @CallbackExecutor Executor executor, From 109d5dc28b1f7da54e454a76a706858a21fec920 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 23 Jan 2020 09:33:48 +0900 Subject: [PATCH 039/229] Always set NetworkInfo objects to available. For all networks, NetworkInfo.isAvailble has basically always been true for all connected networks. The new NetworkAgent API sets it to false, and this causes application breakage. Always set it to true. Bug: 148126438 Test: builds, boots, searching in maps works again Change-Id: Ia9876b0ce7f02120bd05cab526346cad22cf62b3 --- core/java/android/net/NetworkAgent.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 7cc78f7389..7cc569a42b 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -304,7 +304,10 @@ public abstract class NetworkAgent { private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) { // The subtype can be changed with (TODO) setLegacySubtype, but it starts // with the type and an empty description. - return new NetworkInfo(config.legacyType, config.legacyType, config.legacyTypeName, ""); + final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacyType, + config.legacyTypeName, ""); + ni.setIsAvailable(true); + return ni; } /** From d19ef10d006a7254f7f1a6ec21b8c748a7c8acbf Mon Sep 17 00:00:00 2001 From: markchien Date: Mon, 20 Jan 2020 19:31:56 +0800 Subject: [PATCH 040/229] Allows the caller to specify configuration by TetheringRequest This is initial work to allow caller to pass their prefered configuration to start tethering. Caller may able to specify the downstream interface ipv4 address with dhcp server disabled for static IP configuration, or able to exempt entitlement check if they have permission in follow up CL. Bug: 141256482 Test: -atest TetheringTest -ON/OFF wifi tethering Change-Id: Ic7c3a33195bbd7e72f9b8e73fa148be476b87bf3 --- .../java/android/net/ConnectivityManager.java | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 753e754602..ce8ffab3ca 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -33,7 +33,9 @@ import android.content.Context; import android.content.Intent; import android.net.IpSecManager.UdpEncapsulationSocket; import android.net.SocketKeepalive.Callback; +import android.net.TetheringManager.StartTetheringCallback; import android.net.TetheringManager.TetheringEventCallback; +import android.net.TetheringManager.TetheringRequest; import android.os.Binder; import android.os.Build; import android.os.Build.VERSION_CODES; @@ -2452,10 +2454,12 @@ public class ConnectivityManager { * * @param iface the interface name to tether. * @return error a {@code TETHER_ERROR} value indicating success or failure type + * @deprecated Use {@link TetheringManager#startTethering} instead * * {@hide} */ @UnsupportedAppUsage + @Deprecated public int tether(String iface) { return getTetheringManager().tether(iface); } @@ -2512,9 +2516,12 @@ public class ConnectivityManager { /** * Callback for use with {@link #startTethering} to find out whether tethering succeeded. + * + * @deprecated Use {@link TetheringManager.StartTetheringCallback} instead. * @hide */ @SystemApi + @Deprecated public static abstract class OnStartTetheringCallback { /** * Called when tethering has been successfully started. @@ -2531,9 +2538,12 @@ public class ConnectivityManager { * Convenient overload for * {@link #startTethering(int, boolean, OnStartTetheringCallback, Handler)} which passes a null * handler to run on the current thread's {@link Looper}. + * + * @deprecated Use {@link TetheringManager#startTethering} instead. * @hide */ @SystemApi + @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int type, boolean showProvisioningUi, final OnStartTetheringCallback callback) { @@ -2557,26 +2567,44 @@ public class ConnectivityManager { * @param callback an {@link OnStartTetheringCallback} which will be called to notify the caller * of the result of trying to tether. * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * + * @deprecated Use {@link TetheringManager#startTethering} instead. * @hide */ @SystemApi + @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int type, boolean showProvisioningUi, final OnStartTetheringCallback callback, Handler handler) { Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null."); - ResultReceiver wrappedCallback = new ResultReceiver(handler) { + final Executor executor = new Executor() { @Override - protected void onReceiveResult(int resultCode, Bundle resultData) { - if (resultCode == TETHER_ERROR_NO_ERROR) { - callback.onTetheringStarted(); + public void execute(Runnable command) { + if (handler == null) { + command.run(); } else { - callback.onTetheringFailed(); + handler.post(command); } } }; - getTetheringManager().startTethering(type, wrappedCallback, showProvisioningUi); + final StartTetheringCallback tetheringCallback = new StartTetheringCallback() { + @Override + public void onTetheringStarted() { + callback.onTetheringStarted(); + } + + @Override + public void onTetheringFailed(final int resultCode) { + callback.onTetheringFailed(); + } + }; + + final TetheringRequest request = new TetheringRequest.Builder(type) + .setSilentProvisioning(!showProvisioningUi).build(); + + getTetheringManager().startTethering(request, executor, tetheringCallback); } /** @@ -2749,10 +2777,12 @@ public class ConnectivityManager { * * @param enable a boolean - {@code true} to enable tethering * @return error a {@code TETHER_ERROR} value indicating success or failure type + * @deprecated Use {@link TetheringManager#startTethering} instead * * {@hide} */ @UnsupportedAppUsage + @Deprecated public int setUsbTethering(boolean enable) { return getTetheringManager().setUsbTethering(enable); } From 05d5b3b59f3cb212e066a4a68c768643a073afce Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Fri, 17 Jan 2020 15:28:50 -0800 Subject: [PATCH 041/229] Added expiration time and deprecation time support Added link address deprecation time and expiration time for SSC mode 3 support. Bug: 135717900 Bug: 142949345 Test: LinkAddressTest Change-Id: Ibc030d2a70ded66e00dd3bdae209609b9118de78 --- core/java/android/net/LinkAddress.java | 174 ++++++++++++++++-- .../java/android/net/LinkAddressTest.java | 83 ++++++++- 2 files changed, 245 insertions(+), 12 deletions(-) diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java index bf8b38fc7f..8d9f0d068a 100644 --- a/core/java/android/net/LinkAddress.java +++ b/core/java/android/net/LinkAddress.java @@ -19,6 +19,7 @@ package android.net; import static android.system.OsConstants.IFA_F_DADFAILED; import static android.system.OsConstants.IFA_F_DEPRECATED; import static android.system.OsConstants.IFA_F_OPTIMISTIC; +import static android.system.OsConstants.IFA_F_PERMANENT; import static android.system.OsConstants.IFA_F_TENTATIVE; import static android.system.OsConstants.RT_SCOPE_HOST; import static android.system.OsConstants.RT_SCOPE_LINK; @@ -34,6 +35,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.os.SystemClock; import android.util.Pair; import java.net.Inet4Address; @@ -41,6 +43,7 @@ import java.net.Inet6Address; import java.net.InetAddress; import java.net.InterfaceAddress; import java.net.UnknownHostException; +import java.util.Objects; /** * Identifies an IP address on a network link. @@ -58,6 +61,21 @@ import java.net.UnknownHostException; * */ public class LinkAddress implements Parcelable { + + /** + * Indicates the deprecation or expiration time is unknown + * @hide + */ + @SystemApi + public static final long LIFETIME_UNKNOWN = -1; + + /** + * Indicates this address is permanent. + * @hide + */ + @SystemApi + public static final long LIFETIME_PERMANENT = Long.MAX_VALUE; + /** * IPv4 or IPv6 address. */ @@ -71,7 +89,9 @@ public class LinkAddress implements Parcelable { private int prefixLength; /** - * Address flags. A bitmask of IFA_F_* values. + * Address flags. A bitmask of {@code IFA_F_*} values. Note that {@link #getFlags()} may not + * return these exact values. For example, it may set or clear the {@code IFA_F_DEPRECATED} + * flag depending on the current preferred lifetime. */ private int flags; @@ -80,6 +100,23 @@ public class LinkAddress implements Parcelable { */ private int scope; + /** + * The time, as reported by {@link SystemClock#elapsedRealtime}, when this LinkAddress will be + * or was deprecated. {@link #LIFETIME_UNKNOWN} indicates this information is not available. At + * the time existing connections can still use this address until it expires, but new + * connections should use the new address. {@link #LIFETIME_PERMANENT} indicates this + * {@link LinkAddress} will never be deprecated. + */ + private long deprecationTime; + + /** + * The time, as reported by {@link SystemClock#elapsedRealtime}, when this {@link LinkAddress} + * will expire and be removed from the interface. {@link #LIFETIME_UNKNOWN} indicates this + * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} + * will never expire. + */ + private long expirationTime; + /** * Utility function to determines the scope of a unicast address. Per RFC 4291 section 2.5 and * RFC 6724 section 3.2. @@ -152,7 +189,8 @@ public class LinkAddress implements Parcelable { /** * Utility function for the constructors. */ - private void init(InetAddress address, int prefixLength, int flags, int scope) { + private void init(InetAddress address, int prefixLength, int flags, int scope, + long deprecationTime, long expirationTime) { if (address == null || address.isMulticastAddress() || prefixLength < 0 || @@ -161,15 +199,42 @@ public class LinkAddress implements Parcelable { throw new IllegalArgumentException("Bad LinkAddress params " + address + "/" + prefixLength); } + + // deprecation time and expiration time must be both provided, or neither. + if ((deprecationTime == LIFETIME_UNKNOWN) != (expirationTime == LIFETIME_UNKNOWN)) { + throw new IllegalArgumentException( + "Must not specify only one of deprecation time and expiration time"); + } + + // deprecation time needs to be a positive value. + if (deprecationTime != LIFETIME_UNKNOWN && deprecationTime < 0) { + throw new IllegalArgumentException("invalid deprecation time " + deprecationTime); + } + + // expiration time needs to be a positive value. + if (expirationTime != LIFETIME_UNKNOWN && expirationTime < 0) { + throw new IllegalArgumentException("invalid expiration time " + expirationTime); + } + + // expiration time can't be earlier than deprecation time + if (deprecationTime != LIFETIME_UNKNOWN && expirationTime != LIFETIME_UNKNOWN + && expirationTime < deprecationTime) { + throw new IllegalArgumentException("expiration earlier than deprecation (" + + deprecationTime + ", " + expirationTime + ")"); + } + this.address = address; this.prefixLength = prefixLength; this.flags = flags; this.scope = scope; + this.deprecationTime = deprecationTime; + this.expirationTime = expirationTime; } /** * Constructs a new {@code LinkAddress} from an {@code InetAddress} and prefix length, with * the specified flags and scope. Flags and scope are not checked for validity. + * * @param address The IP address. * @param prefixLength The prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address. @@ -181,7 +246,39 @@ public class LinkAddress implements Parcelable { @TestApi public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength, int flags, int scope) { - init(address, prefixLength, flags, scope); + init(address, prefixLength, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN); + } + + /** + * Constructs a new {@code LinkAddress} from an {@code InetAddress}, prefix length, with + * the specified flags, scope, deprecation time, and expiration time. Flags and scope are not + * checked for validity. The value of the {@code IFA_F_DEPRECATED} and {@code IFA_F_PERMANENT} + * flag will be adjusted based on the passed-in lifetimes. + * + * @param address The IP address. + * @param prefixLength The prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6). + * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address. + * @param scope An integer defining the scope in which the address is unique (e.g., + * {@link OsConstants#RT_SCOPE_LINK} or {@link OsConstants#RT_SCOPE_SITE}). + * @param deprecationTime The time, as reported by {@link SystemClock#elapsedRealtime}, when + * this {@link LinkAddress} will be or was deprecated. + * {@link #LIFETIME_UNKNOWN} indicates this information is not available. + * At the time existing connections can still use this address until it + * expires, but new connections should use the new address. + * {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} will + * never be deprecated. + * @param expirationTime The time, as reported by {@link SystemClock#elapsedRealtime}, when this + * {@link LinkAddress} will expire and be removed from the interface. + * {@link #LIFETIME_UNKNOWN} indicates this information is not available. + * {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} will + * never expire. + * @hide + */ + @SystemApi + @TestApi + public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength, + int flags, int scope, long deprecationTime, long expirationTime) { + init(address, prefixLength, flags, scope, deprecationTime, expirationTime); } /** @@ -237,7 +334,7 @@ public class LinkAddress implements Parcelable { // This may throw an IllegalArgumentException; catching it is the caller's responsibility. // TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24". Pair ipAndMask = NetworkUtils.parseIpAndMask(address); - init(ipAndMask.first, ipAndMask.second, flags, scope); + init(ipAndMask.first, ipAndMask.second, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN); } /** @@ -265,10 +362,12 @@ public class LinkAddress implements Parcelable { return false; } LinkAddress linkAddress = (LinkAddress) obj; - return this.address.equals(linkAddress.address) && - this.prefixLength == linkAddress.prefixLength && - this.flags == linkAddress.flags && - this.scope == linkAddress.scope; + return this.address.equals(linkAddress.address) + && this.prefixLength == linkAddress.prefixLength + && this.flags == linkAddress.flags + && this.scope == linkAddress.scope + && this.deprecationTime == linkAddress.deprecationTime + && this.expirationTime == linkAddress.expirationTime; } /** @@ -276,7 +375,7 @@ public class LinkAddress implements Parcelable { */ @Override public int hashCode() { - return address.hashCode() + 11 * prefixLength + 19 * flags + 43 * scope; + return Objects.hash(address, prefixLength, flags, scope, deprecationTime, expirationTime); } /** @@ -329,6 +428,25 @@ public class LinkAddress implements Parcelable { * Returns the flags of this {@code LinkAddress}. */ public int getFlags() { + int flags = this.flags; + if (deprecationTime != LIFETIME_UNKNOWN) { + if (SystemClock.elapsedRealtime() >= deprecationTime) { + flags |= IFA_F_DEPRECATED; + } else { + // If deprecation time is in the future, or permanent. + flags &= ~IFA_F_DEPRECATED; + } + } + + if (expirationTime == LIFETIME_PERMANENT) { + flags |= IFA_F_PERMANENT; + } else if (expirationTime != LIFETIME_UNKNOWN) { + // If we know this address expired or will expire in the future or, then this address + // should not be permanent. + flags &= ~IFA_F_PERMANENT; + } + + // Do no touch the original flags. Return the adjusted flags here. return flags; } @@ -340,7 +458,35 @@ public class LinkAddress implements Parcelable { } /** - * Returns true if this {@code LinkAddress} is global scope and preferred. + * @return The time that this address will be deprecated. At the time the existing connection + * can still use this address until it expires, but the new connection should use the new + * address. This is the EPOCH time in milliseconds. 0 indicates this information is not + * available. + * + * @hide + */ + @SystemApi + @TestApi + public long getDeprecationTime() { + return deprecationTime; + } + + /** + * @return The time that this address will expire and will be no longer valid. This is the EPOCH + * time in milliseconds. 0 indicates this information is not available. + * + * @hide + */ + @SystemApi + @TestApi + public long getExpirationTime() { + return expirationTime; + } + + /** + * Returns true if this {@code LinkAddress} is global scope and preferred (i.e., not currently + * deprecated). + * * @hide */ @TestApi @@ -352,6 +498,7 @@ public class LinkAddress implements Parcelable { * state has cleared either DAD has succeeded or failed, and both * flags are cleared regardless). */ + int flags = getFlags(); return (scope == RT_SCOPE_UNIVERSE && !isIpv6ULA() && (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED)) == 0L @@ -373,6 +520,8 @@ public class LinkAddress implements Parcelable { dest.writeInt(prefixLength); dest.writeInt(this.flags); dest.writeInt(scope); + dest.writeLong(deprecationTime); + dest.writeLong(expirationTime); } /** @@ -392,7 +541,10 @@ public class LinkAddress implements Parcelable { int prefixLength = in.readInt(); int flags = in.readInt(); int scope = in.readInt(); - return new LinkAddress(address, prefixLength, flags, scope); + long deprecationTime = in.readLong(); + long expirationTime = in.readLong(); + return new LinkAddress(address, prefixLength, flags, scope, deprecationTime, + expirationTime); } public LinkAddress[] newArray(int size) { diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java index b2e573b6c7..096f7bdca0 100644 --- a/tests/net/common/java/android/net/LinkAddressTest.java +++ b/tests/net/common/java/android/net/LinkAddressTest.java @@ -38,6 +38,8 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.os.SystemClock; + import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -316,11 +318,83 @@ public class LinkAddressTest { l = new LinkAddress(V6_ADDRESS, 64, 123, 456); assertParcelingIsLossless(l); + l = new LinkAddress(V6_ADDRESS, 64, 123, 456, + 1L, 3600000L); + assertParcelingIsLossless(l); l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK); - assertParcelSane(l, 4); + assertParcelSane(l, 6); } + @Test + public void testDeprecationTime() { + try { + new LinkAddress(V6_ADDRESS, 64, 0, 456, + LinkAddress.LIFETIME_UNKNOWN, + SystemClock.elapsedRealtime() + 200000); + fail("Only one time provided should cause exception"); + } catch (IllegalArgumentException expected) { } + + try { + new LinkAddress(V6_ADDRESS, 64, 0, 456, + SystemClock.elapsedRealtime() - 100000, + SystemClock.elapsedRealtime() - 200000); + fail("deprecation time later than expiration time should cause exception"); + } catch (IllegalArgumentException expected) { } + + try { + new LinkAddress(V6_ADDRESS, 64, 0, 456, + -2, SystemClock.elapsedRealtime()); + fail("negative deprecation time should cause exception"); + } catch (IllegalArgumentException expected) { } + } + + @Test + public void testExpirationTime() { + try { + new LinkAddress(V6_ADDRESS, 64, 0, 456, + SystemClock.elapsedRealtime() + 200000, + LinkAddress.LIFETIME_UNKNOWN); + fail("Only one time provided should cause exception"); + } catch (IllegalArgumentException expected) { } + + try { + new LinkAddress(V6_ADDRESS, 64, 0, 456, + SystemClock.elapsedRealtime() - 10000, -2); + fail("negative expiration time should cause exception"); + } catch (IllegalArgumentException expected) { } + } + + @Test + public void testGetFlags() { + LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, RT_SCOPE_HOST); + assertEquals(123, l.getFlags()); + + // Test if deprecated bit was added/remove automatically based on the provided deprecation + // time + l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST, + SystemClock.elapsedRealtime() - 100000, LinkAddress.LIFETIME_PERMANENT); + // Check if the flag is added automatically. + assertTrue((l.getFlags() & IFA_F_DEPRECATED) != 0); + + l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST, + SystemClock.elapsedRealtime() + 100000, LinkAddress.LIFETIME_PERMANENT); + // Check if the flag is removed automatically. + assertTrue((l.getFlags() & IFA_F_DEPRECATED) == 0); + + l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST, + LinkAddress.LIFETIME_PERMANENT, LinkAddress.LIFETIME_PERMANENT); + // Check if the permanent flag is added. + assertTrue((l.getFlags() & IFA_F_PERMANENT) != 0); + + l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_HOST, + SystemClock.elapsedRealtime() - 100000, + SystemClock.elapsedRealtime() + 100000); + // Check if the permanent flag is removed + assertTrue((l.getFlags() & IFA_F_PERMANENT) == 0); + } + + private void assertGlobalPreferred(LinkAddress l, String msg) { assertTrue(msg, l.isGlobalPreferred()); } @@ -389,5 +463,12 @@ public class LinkAddressTest { (IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC), RT_SCOPE_UNIVERSE); assertGlobalPreferred(l, "v6,global,tempaddr+optimistic"); + + l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, + RT_SCOPE_UNIVERSE, SystemClock.elapsedRealtime() + 100000, + SystemClock.elapsedRealtime() + 200000); + // Although the deprecated bit is set, but the deprecation time is in the future, test + // if the flag is removed automatically. + assertGlobalPreferred(l, "v6,global,tempaddr+deprecated in the future"); } } From 5cfe856af1a8bc96bb9e49603ed7ad7ac3eaeaa5 Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Thu, 23 Jan 2020 18:03:46 -0800 Subject: [PATCH 042/229] Fix javadoc build break s/line/link/ Bug: 148248781 Test: compilation Change-Id: I9df208a9b063b71b2f6cc3099005d1ab38044cd2 --- core/java/android/net/ConnectivityManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 753e754602..3d6cae205b 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2602,7 +2602,7 @@ public class ConnectivityManager { * Callback for use with {@link registerTetheringEventCallback} to find out tethering * upstream status. * - * @deprecated Use {@line TetheringManager#OnTetheringEventCallback} instead. + * @deprecated Use {@link TetheringManager#OnTetheringEventCallback} instead. * @hide */ @SystemApi @@ -2632,7 +2632,7 @@ public class ConnectivityManager { * @param executor the executor on which callback will be invoked. * @param callback the callback to be called when tethering has change events. * - * @deprecated Use {@line TetheringManager#registerTetheringEventCallback} instead. + * @deprecated Use {@link TetheringManager#registerTetheringEventCallback} instead. * @hide */ @SystemApi From d40e5498d0c559503bfdf0815e17e583357f3941 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Thu, 23 Jan 2020 22:09:29 -0800 Subject: [PATCH 043/229] Disabled the tests Will re-enable after fixing the negative time issue Test: LinkAddressTest Bug: 148257086 Change-Id: Ia6ce0608a2ce95be980e4f9ea62315076c4453be --- tests/net/common/java/android/net/LinkAddressTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java index 096f7bdca0..e566e44c81 100644 --- a/tests/net/common/java/android/net/LinkAddressTest.java +++ b/tests/net/common/java/android/net/LinkAddressTest.java @@ -326,6 +326,7 @@ public class LinkAddressTest { assertParcelSane(l, 6); } + /* @Test public void testDeprecationTime() { try { @@ -392,7 +393,7 @@ public class LinkAddressTest { SystemClock.elapsedRealtime() + 100000); // Check if the permanent flag is removed assertTrue((l.getFlags() & IFA_F_PERMANENT) == 0); - } + }*/ private void assertGlobalPreferred(LinkAddress l, String msg) { From b67261b01c787392bb24a6fe3f067937e33a0d6a Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Sun, 26 Jan 2020 15:52:11 -0800 Subject: [PATCH 044/229] Fixed the documentation and unit tests Fixed the documentation and re-eanble the broken unit tests. Test: LinkAddressTest Bug: 142949345 Change-Id: I0ac8c022f70cdf9305c183996c2464a8e04ba5ae --- core/java/android/net/LinkAddress.java | 35 +++++++++++-------- .../java/android/net/LinkAddressTest.java | 24 +++++-------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java index 8d9f0d068a..a9d7f17017 100644 --- a/core/java/android/net/LinkAddress.java +++ b/core/java/android/net/LinkAddress.java @@ -102,9 +102,9 @@ public class LinkAddress implements Parcelable { /** * The time, as reported by {@link SystemClock#elapsedRealtime}, when this LinkAddress will be - * or was deprecated. {@link #LIFETIME_UNKNOWN} indicates this information is not available. At - * the time existing connections can still use this address until it expires, but new - * connections should use the new address. {@link #LIFETIME_PERMANENT} indicates this + * or was deprecated. At the time existing connections can still use this address until it + * expires, but new connections should use the new address. {@link #LIFETIME_UNKNOWN} indicates + * this information is not available. {@link #LIFETIME_PERMANENT} indicates this * {@link LinkAddress} will never be deprecated. */ private long deprecationTime; @@ -261,10 +261,10 @@ public class LinkAddress implements Parcelable { * @param scope An integer defining the scope in which the address is unique (e.g., * {@link OsConstants#RT_SCOPE_LINK} or {@link OsConstants#RT_SCOPE_SITE}). * @param deprecationTime The time, as reported by {@link SystemClock#elapsedRealtime}, when - * this {@link LinkAddress} will be or was deprecated. - * {@link #LIFETIME_UNKNOWN} indicates this information is not available. - * At the time existing connections can still use this address until it - * expires, but new connections should use the new address. + * this {@link LinkAddress} will be or was deprecated. At the time + * existing connections can still use this address until it expires, but + * new connections should use the new address. {@link #LIFETIME_UNKNOWN} + * indicates this information is not available. * {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} will * never be deprecated. * @param expirationTime The time, as reported by {@link SystemClock#elapsedRealtime}, when this @@ -441,7 +441,7 @@ public class LinkAddress implements Parcelable { if (expirationTime == LIFETIME_PERMANENT) { flags |= IFA_F_PERMANENT; } else if (expirationTime != LIFETIME_UNKNOWN) { - // If we know this address expired or will expire in the future or, then this address + // If we know this address expired or will expire in the future, then this address // should not be permanent. flags &= ~IFA_F_PERMANENT; } @@ -458,10 +458,13 @@ public class LinkAddress implements Parcelable { } /** - * @return The time that this address will be deprecated. At the time the existing connection - * can still use this address until it expires, but the new connection should use the new - * address. This is the EPOCH time in milliseconds. 0 indicates this information is not - * available. + * Get the deprecation time, as reported by {@link SystemClock#elapsedRealtime}, when this + * {@link LinkAddress} will be or was deprecated. At the time existing connections can still use + * this address until it expires, but new connections should use the new address. + * + * @return The deprecation time in milliseconds. {@link #LIFETIME_UNKNOWN} indicates this + * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} + * will never be deprecated. * * @hide */ @@ -472,8 +475,12 @@ public class LinkAddress implements Parcelable { } /** - * @return The time that this address will expire and will be no longer valid. This is the EPOCH - * time in milliseconds. 0 indicates this information is not available. + * Get the expiration time, as reported by {@link SystemClock#elapsedRealtime}, when this + * {@link LinkAddress} will expire and be removed from the interface. + * + * @return The expiration time in milliseconds. {@link #LIFETIME_UNKNOWN} indicates this + * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} + * will never expire. * * @hide */ diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java index e566e44c81..06c6301d66 100644 --- a/tests/net/common/java/android/net/LinkAddressTest.java +++ b/tests/net/common/java/android/net/LinkAddressTest.java @@ -326,26 +326,23 @@ public class LinkAddressTest { assertParcelSane(l, 6); } - /* @Test public void testDeprecationTime() { try { new LinkAddress(V6_ADDRESS, 64, 0, 456, - LinkAddress.LIFETIME_UNKNOWN, - SystemClock.elapsedRealtime() + 200000); + LinkAddress.LIFETIME_UNKNOWN, 100000L); fail("Only one time provided should cause exception"); } catch (IllegalArgumentException expected) { } try { new LinkAddress(V6_ADDRESS, 64, 0, 456, - SystemClock.elapsedRealtime() - 100000, - SystemClock.elapsedRealtime() - 200000); + 200000L, 100000L); fail("deprecation time later than expiration time should cause exception"); } catch (IllegalArgumentException expected) { } try { new LinkAddress(V6_ADDRESS, 64, 0, 456, - -2, SystemClock.elapsedRealtime()); + -2, 100000L); fail("negative deprecation time should cause exception"); } catch (IllegalArgumentException expected) { } } @@ -354,14 +351,13 @@ public class LinkAddressTest { public void testExpirationTime() { try { new LinkAddress(V6_ADDRESS, 64, 0, 456, - SystemClock.elapsedRealtime() + 200000, - LinkAddress.LIFETIME_UNKNOWN); + 200000L, LinkAddress.LIFETIME_UNKNOWN); fail("Only one time provided should cause exception"); } catch (IllegalArgumentException expected) { } try { new LinkAddress(V6_ADDRESS, 64, 0, 456, - SystemClock.elapsedRealtime() - 10000, -2); + 100000L, -2); fail("negative expiration time should cause exception"); } catch (IllegalArgumentException expected) { } } @@ -374,12 +370,12 @@ public class LinkAddressTest { // Test if deprecated bit was added/remove automatically based on the provided deprecation // time l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST, - SystemClock.elapsedRealtime() - 100000, LinkAddress.LIFETIME_PERMANENT); + 1L, LinkAddress.LIFETIME_PERMANENT); // Check if the flag is added automatically. assertTrue((l.getFlags() & IFA_F_DEPRECATED) != 0); l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST, - SystemClock.elapsedRealtime() + 100000, LinkAddress.LIFETIME_PERMANENT); + SystemClock.elapsedRealtime() + 100000L, LinkAddress.LIFETIME_PERMANENT); // Check if the flag is removed automatically. assertTrue((l.getFlags() & IFA_F_DEPRECATED) == 0); @@ -389,12 +385,10 @@ public class LinkAddressTest { assertTrue((l.getFlags() & IFA_F_PERMANENT) != 0); l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_HOST, - SystemClock.elapsedRealtime() - 100000, - SystemClock.elapsedRealtime() + 100000); + 1000L, SystemClock.elapsedRealtime() + 100000L); // Check if the permanent flag is removed assertTrue((l.getFlags() & IFA_F_PERMANENT) == 0); - }*/ - + } private void assertGlobalPreferred(LinkAddress l, String msg) { assertTrue(msg, l.isGlobalPreferred()); From c19c94fe9bb863090acf49e82e80a2f2f31097fd Mon Sep 17 00:00:00 2001 From: David Su Date: Mon, 27 Jan 2020 13:27:50 -0800 Subject: [PATCH 045/229] Networking: Rename removeDoubleQuotes to sanitizeSsid Bug: 145745815 Test: compiles Change-Id: Iaa6f0d65cab556c24b0a9010427de8e6a02836c1 --- .../connectivity/NetworkNotificationManager.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 2c415570d5..25c761ab80 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -188,14 +188,14 @@ public class NetworkNotificationManager { int icon = getIcon(transportType, notifyType); if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.PRIVATE_DNS_BROKEN) { if (transportType == TRANSPORT_CELLULAR) { title = r.getString(R.string.mobile_no_internet); } else if (transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); } else { title = r.getString(R.string.other_networks_no_internet); } @@ -203,19 +203,19 @@ public class NetworkNotificationManager { } else if (notifyType == NotificationType.PARTIAL_CONNECTIVITY && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.network_partial_connectivity, - WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); details = r.getString(R.string.network_partial_connectivity_detailed); } else if (notifyType == NotificationType.LOST_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.SIGN_IN) { switch (transportType) { case TRANSPORT_WIFI: title = r.getString(R.string.wifi_available_sign_in, 0); details = r.getString(R.string.network_available_sign_in_detailed, - WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); break; case TRANSPORT_CELLULAR: title = r.getString(R.string.network_available_sign_in, 0); @@ -236,7 +236,7 @@ public class NetworkNotificationManager { break; } } else if (notifyType == NotificationType.LOGGED_IN) { - title = WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()); + title = WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID()); details = r.getString(R.string.captive_portal_logged_in_detailed); } else if (notifyType == NotificationType.NETWORK_SWITCH) { String fromTransport = getTransportName(transportType); From ead2e7bbb172883ef027c782120d4479c263d8c5 Mon Sep 17 00:00:00 2001 From: Paul Trautrim Date: Thu, 23 Jan 2020 14:55:57 +0900 Subject: [PATCH 046/229] Add implementation of getInterfaceHash() Bug: 136065010 Test: m Change-Id: I314f19aeca82cc8653eab71c9526ea7a208e6b50 --- .../core/java/com/android/server/ConnectivityService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index dd33566322..d933e9d8e9 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2962,6 +2962,11 @@ public class ConnectivityService extends IConnectivityManager.Stub public int getInterfaceVersion() { return this.VERSION; } + + @Override + public String getInterfaceHash() { + return this.HASH; + } } private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) { From 511f7e3792fcec295a41bf85f4722faeb8cbd166 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Tue, 14 Jan 2020 17:03:42 +0900 Subject: [PATCH 047/229] Add public fields to NetworkScore and make it @SystemApi Bug: 113554781 Bug: 146583853 Test: FrameworksNetTests Change-Id: I19d965c0146196cb67b3417eb1790ccd90ce3233 --- .../java/android/net/ConnectivityManager.java | 8 +- .../android/net/IConnectivityManager.aidl | 3 +- core/java/android/net/NetworkAgent.java | 50 +- core/java/android/net/NetworkScore.java | 470 +++++++++++++++--- .../android/server/ConnectivityService.java | 22 +- .../server/connectivity/NetworkAgentInfo.java | 2 +- .../android/server/NetworkAgentWrapper.java | 7 +- .../connectivity/LingerMonitorTest.java | 3 +- 8 files changed, 446 insertions(+), 119 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index ce9693d88a..fa12c08f22 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3322,15 +3322,19 @@ public class ConnectivityManager { // of dependent changes that would conflict throughout the automerger graph. Having this // temporarily helps with the process of going through with all these dependent changes across // the entire tree. + // STOPSHIP (b/148055573) : remove this before R is released. /** * @hide * Register a NetworkAgent with ConnectivityService. * @return Network corresponding to NetworkAgent. + * @deprecated use the version that takes a NetworkScore and a provider ID. */ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + @Deprecated public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkAgentConfig config) { - return registerNetworkAgent(messenger, ni, lp, nc, score, config, NetworkProvider.ID_NONE); + final NetworkScore ns = new NetworkScore.Builder().setLegacyScore(score).build(); + return registerNetworkAgent(messenger, ni, lp, nc, ns, config, NetworkProvider.ID_NONE); } /** @@ -3340,7 +3344,7 @@ public class ConnectivityManager { */ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, - NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) { + NetworkCapabilities nc, NetworkScore score, NetworkAgentConfig config, int providerId) { try { return mService.registerNetworkAgent(messenger, ni, lp, nc, score, config, providerId); } catch (RemoteException e) { diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 186196bd31..c58ffd5606 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -25,6 +25,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; +import android.net.NetworkScore; import android.net.NetworkState; import android.net.ISocketKeepaliveCallback; import android.net.ProxyInfo; @@ -153,7 +154,7 @@ interface IConnectivityManager void declareNetworkRequestUnfulfillable(in NetworkRequest request); Network registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp, - in NetworkCapabilities nc, int score, in NetworkAgentConfig config, + in NetworkCapabilities nc, in NetworkScore score, in NetworkAgentConfig config, in int factorySerialNumber); NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 7cc569a42b..ddf8dbbcb9 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -116,13 +116,6 @@ public abstract class NetworkAgent { */ public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3; - /** - * Centralize the place where base network score, and network score scaling, will be - * stored, so as we can consistently compare apple and oranges, or wifi, ethernet and LTE - * @hide - */ - public static final int WIFI_BASE_SCORE = 60; - /** * Sent by the NetworkAgent to ConnectivityService to pass the current * network score. @@ -272,7 +265,13 @@ public abstract class NetworkAgent { */ public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; + // STOPSHIP (b/148055573) : remove this before R is released. + private static NetworkScore makeNetworkScore(int score) { + return new NetworkScore.Builder().setLegacyScore(score).build(); + } + /** @hide TODO: remove and replace usage with the public constructor. */ + // STOPSHIP (b/148055573) : remove this before R is released. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) { this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE); @@ -280,6 +279,7 @@ public abstract class NetworkAgent { } /** @hide TODO: remove and replace usage with the public constructor. */ + // STOPSHIP (b/148055573) : remove this before R is released. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) { this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE); @@ -287,6 +287,7 @@ public abstract class NetworkAgent { } /** @hide TODO: remove and replace usage with the public constructor. */ + // STOPSHIP (b/148055573) : remove this before R is released. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, int providerId) { this(looper, context, logTag, ni, nc, lp, score, null, providerId); @@ -294,10 +295,12 @@ public abstract class NetworkAgent { } /** @hide TODO: remove and replace usage with the public constructor. */ + // STOPSHIP (b/148055573) : remove this before R is released. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, int providerId) { - this(looper, context, logTag, nc, lp, score, config, providerId, ni, true /* legacy */); + this(looper, context, logTag, nc, lp, makeNetworkScore(score), config, providerId, ni, + true /* legacy */); register(); } @@ -323,8 +326,9 @@ public abstract class NetworkAgent { * @param provider the {@link NetworkProvider} managing this agent. */ public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, - @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, + @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, + @Nullable NetworkProvider provider) { this(looper, context, logTag, nc, lp, score, config, provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(), getLegacyNetworkInfo(config), false /* legacy */); @@ -334,12 +338,12 @@ public abstract class NetworkAgent { public final Context context; public final NetworkCapabilities capabilities; public final LinkProperties properties; - public final int score; + public final NetworkScore score; public final NetworkAgentConfig config; public final NetworkInfo info; InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities, - @NonNull LinkProperties properties, int score, @NonNull NetworkAgentConfig config, - @NonNull NetworkInfo info) { + @NonNull LinkProperties properties, @NonNull NetworkScore score, + @NonNull NetworkAgentConfig config, @NonNull NetworkInfo info) { this.context = context; this.capabilities = capabilities; this.properties = properties; @@ -351,7 +355,7 @@ public abstract class NetworkAgent { private volatile InitialConfiguration mInitialConfiguration; private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, NetworkScore score, @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni, boolean legacy) { mHandler = new NetworkAgentHandler(looper); @@ -646,22 +650,8 @@ public abstract class NetworkAgent { * Must be called by the agent to update the score of this network. * @param score the new score. */ - public void sendNetworkScore(int score) { - if (score < 0) { - throw new IllegalArgumentException("Score must be >= 0"); - } - final NetworkScore ns = new NetworkScore(); - ns.putIntExtension(NetworkScore.LEGACY_SCORE, score); - updateScore(ns); - } - - /** - * Must be called by the agent when it has a new {@link NetworkScore} for this network. - * @param ns the new score. - * @hide TODO: unhide the NetworkScore class, and rename to sendNetworkScore. - */ - public void updateScore(@NonNull NetworkScore ns) { - queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new NetworkScore(ns)); + public void sendNetworkScore(@NonNull final NetworkScore score) { + queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, score); } /** diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java index 13f2994110..ae17378cfc 100644 --- a/core/java/android/net/NetworkScore.java +++ b/core/java/android/net/NetworkScore.java @@ -15,12 +15,18 @@ */ package android.net; +import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** @@ -28,57 +34,392 @@ import java.util.Objects; * * A NetworkScore object represents the characteristics of a network that affects how good the * network is considered for a particular use. + * + * This class is not thread-safe. * @hide */ +@TestApi +@SystemApi public final class NetworkScore implements Parcelable { + /** An object containing scoring-relevant metrics for a network. */ + public static class Metrics { + /** Value meaning the latency is unknown. */ + public static final int LATENCY_UNKNOWN = -1; - // The key of bundle which is used to get the legacy network score of NetworkAgentInfo. - // TODO: Remove this when the transition to NetworkScore is over. - public static final String LEGACY_SCORE = "LEGACY_SCORE"; + /** Value meaning the bandwidth is unknown. */ + public static final int BANDWIDTH_UNKNOWN = -1; + + /** + * Round-trip delay in milliseconds to the relevant destination for this Metrics object. + * + * LATENCY_UNKNOWN if unknown. + */ + @IntRange(from = LATENCY_UNKNOWN) + public final int latencyMs; + + /** + * Downlink in kB/s with the relevant destination for this Metrics object. + * + * BANDWIDTH_UNKNOWN if unknown. If directional bandwidth is unknown, up and downlink + * bandwidth can have the same value. + */ + @IntRange(from = BANDWIDTH_UNKNOWN) + public final int downlinkBandwidthKBps; + + /** + * Uplink in kB/s with the relevant destination for this Metrics object. + * + * BANDWIDTH_UNKNOWN if unknown. If directional bandwidth is unknown, up and downlink + * bandwidth can have the same value. + */ + @IntRange(from = BANDWIDTH_UNKNOWN) + public final int uplinkBandwidthKBps; + + /** Constructor */ + public Metrics(@IntRange(from = LATENCY_UNKNOWN) final int latency, + @IntRange(from = BANDWIDTH_UNKNOWN) final int downlinkBandwidth, + @IntRange(from = BANDWIDTH_UNKNOWN) final int uplinkBandwidth) { + latencyMs = latency; + downlinkBandwidthKBps = downlinkBandwidth; + uplinkBandwidthKBps = uplinkBandwidth; + } + + /** toString */ + public String toString() { + return "latency = " + latencyMs + " downlinkBandwidth = " + downlinkBandwidthKBps + + "uplinkBandwidth = " + uplinkBandwidthKBps; + } + + @NonNull + public static final Metrics EMPTY = + new Metrics(LATENCY_UNKNOWN, BANDWIDTH_UNKNOWN, BANDWIDTH_UNKNOWN); + } + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = "POLICY_", value = { + POLICY_LOCKDOWN_VPN, + POLICY_VPN, + POLICY_IGNORE_ON_WIFI, + POLICY_DEFAULT_SUBSCRIPTION + }) + public @interface Policy { + } + + /** + * This network is a VPN with lockdown enabled. + * + * If a network with this bit is present in the list of candidates and not connected, + * no network can satisfy the request. + */ + public static final int POLICY_LOCKDOWN_VPN = 1 << 0; + + /** + * This network is a VPN. + * + * If a network with this bit is present and the request UID is included in the UID ranges + * of this network, it outscores all other networks without this bit. + */ + public static final int POLICY_VPN = 1 << 1; + + /** + * This network should not be used if a previously validated WiFi network is available. + * + * If a network with this bit is present and a previously validated WiFi is present too, the + * network with this bit is outscored by it. This stays true if the WiFi network + * becomes unvalidated : this network will not be considered. + */ + public static final int POLICY_IGNORE_ON_WIFI = 1 << 2; + + /** + * This network is the default subscription for this transport. + * + * If a network with this bit is present, other networks of the same transport without this + * bit are outscored by it. A device with two active subscriptions and a setting + * to decide the default one would have this policy bit on the network for the default + * subscription so that when both are active at the same time, the device chooses the + * network associated with the default subscription rather than the one with the best link + * quality (which will happen if policy doesn't dictate otherwise). + */ + public static final int POLICY_DEFAULT_SUBSCRIPTION = 1 << 3; + + /** + * Policy bits for this network. Filled in by the NetworkAgent. + */ + private final int mPolicy; + + /** + * Predicted metrics to the gateway (it contains latency and bandwidth to the gateway). + * This is filled by the NetworkAgent with the theoretical values of the link if available, + * although they may fill it with predictions from historical data if available. + * Note that while this member cannot be null, any and all of its members can be unknown. + */ @NonNull - private final Bundle mExtensions; + private final Metrics mLinkLayerMetrics; - public NetworkScore() { - mExtensions = new Bundle(); - } + /** + * Predicted metrics to representative servers. + * This is filled by connectivity with (if available) a best-effort estimate of the performance + * information to servers the user connects to in similar circumstances, and predicted from + * actual measurements if possible. + * Note that while this member cannot be null, any and all of its members can be unknown. + */ + @NonNull + private final Metrics mEndToEndMetrics; - public NetworkScore(@NonNull NetworkScore source) { - mExtensions = new Bundle(source.mExtensions); + /** Value meaning the signal strength is unknown. */ + public static final int UNKNOWN_SIGNAL_STRENGTH = -1; + + /** The smallest meaningful signal strength. */ + public static final int MIN_SIGNAL_STRENGTH = 0; + + /** The largest meaningful signal strength. */ + public static final int MAX_SIGNAL_STRENGTH = 1000; + + /** + * User-visible measure of the strength of the signal normalized 1~1000. + * This represents a measure of the signal strength for this network. + * If unknown, this has value UNKNOWN_SIGNAL_STRENGTH. + */ + // A good way to populate this value is to fill it with the number of bars displayed in + // the system UI, scaled 0 to 1000. This is what the user sees and it makes sense to them. + // Cellular for example could quantize the ASU value (see SignalStrength#getAsuValue) into + // this, while WiFi could scale the RSSI (see WifiManager#calculateSignalLevel). + @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH) + private final int mSignalStrength; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, prefix = "RANGE_", value = { + RANGE_UNKNOWN, RANGE_CLOSE, RANGE_SHORT, RANGE_MEDIUM, RANGE_LONG + }) + public @interface Range { } /** - * Put the value of parcelable inside the bundle by key. + * The range of this network is not known. + * This can be used by VPN the range of which depends on the range of the underlying network. */ - public void putExtension(@Nullable String key, @Nullable Parcelable value) { - mExtensions.putParcelable(key, value); + public static final int RANGE_UNKNOWN = 0; + + /** + * This network typically only operates at close range, like an NFC beacon. + */ + public static final int RANGE_CLOSE = 1; + + /** + * This network typically operates at a range of a few meters to a few dozen meters, like WiFi. + */ + public static final int RANGE_SHORT = 2; + + /** + * This network typically operates at a range of a few dozen to a few hundred meters, like CBRS. + */ + public static final int RANGE_MEDIUM = 3; + + /** + * This network typically offers continuous connectivity up to many kilometers away, like LTE. + */ + public static final int RANGE_LONG = 4; + + /** + * The typical range of this networking technology. + * + * This is one of the RANGE_* constants and is filled by the NetworkAgent. + * This may be useful when evaluating how desirable a network is, because for two networks that + * have equivalent performance and cost, the one that won't lose IP continuity when the user + * moves is probably preferable. + * Agents should fill this with the largest typical range this technology provides. See the + * descriptions of the individual constants for guidance. + * + * If unknown, this is set to RANGE_UNKNOWN. + */ + @Range private final int mRange; + + /** + * A prediction of whether this network is likely to be unusable in a few seconds. + * + * NetworkAgents set this to true to mean they are aware that usability is limited due to + * low signal strength, congestion, or other reasons, and indicates that the system should + * only use this network as a last resort. An example would be a WiFi network when the device + * is about to move outside of range. + * + * This is filled by the NetworkAgent. Agents that don't know whether this network is likely + * to be unusable soon should set this to false. + */ + private final boolean mExiting; + + /** + * The legacy score, as a migration strategy from Q to R. + * STOPSHIP : remove this before R ships. + */ + private final int mLegacyScore; + + /** + * Create a new NetworkScore object. + */ + private NetworkScore(@Policy final int policy, @Nullable final Metrics l2Perf, + @Nullable final Metrics e2ePerf, + @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH) + final int signalStrength, + @Range final int range, final boolean exiting, final int legacyScore) { + mPolicy = policy; + mLinkLayerMetrics = null != l2Perf ? l2Perf : Metrics.EMPTY; + mEndToEndMetrics = null != e2ePerf ? e2ePerf : Metrics.EMPTY; + mSignalStrength = signalStrength; + mRange = range; + mExiting = exiting; + mLegacyScore = legacyScore; } /** - * Put the value of int inside the bundle by key. + * Utility function to return a copy of this with a different exiting value. */ - public void putIntExtension(@Nullable String key, int value) { - mExtensions.putInt(key, value); + @NonNull public NetworkScore withExiting(final boolean exiting) { + return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToEndMetrics, + mSignalStrength, mRange, exiting, mLegacyScore); } /** - * Get the value of non primitive type by key. + * Utility function to return a copy of this with a different signal strength. */ - public T getExtension(@Nullable String key) { - return mExtensions.getParcelable(key); + @NonNull public NetworkScore withSignalStrength( + @IntRange(from = UNKNOWN_SIGNAL_STRENGTH) final int signalStrength) { + return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToEndMetrics, + signalStrength, mRange, mExiting, mLegacyScore); } /** - * Get the value of int by key. + * Returns whether this network has a particular policy flag. + * @param policy the policy, as one of the POLICY_* constants. */ - public int getIntExtension(@Nullable String key) { - return mExtensions.getInt(key); + public boolean hasPolicy(@Policy final int policy) { + return 0 != (mPolicy & policy); } /** - * Remove the entry by given key. + * Returns the Metrics representing the performance of the link layer. + * + * This contains the theoretical performance of the link, if available. + * Note that while this function cannot return null, any and/or all of the members of the + * returned object can be null if unknown. */ - public void removeExtension(@Nullable String key) { - mExtensions.remove(key); + @NonNull public Metrics getLinkLayerMetrics() { + return mLinkLayerMetrics; + } + + /** + * Returns the Metrics representing the end-to-end performance of the network. + * + * This contains the end-to-end performance of the link, if available. + * Note that while this function cannot return null, any and/or all of the members of the + * returned object can be null if unknown. + */ + @NonNull public Metrics getEndToEndMetrics() { + return mEndToEndMetrics; + } + + /** + * Returns the signal strength of this network normalized 0~1000, or UNKNOWN_SIGNAL_STRENGTH. + */ + @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH) + public int getSignalStrength() { + return mSignalStrength; + } + + /** + * Returns the typical range of this network technology as one of the RANGE_* constants. + */ + @Range public int getRange() { + return mRange; + } + + /** Returns a prediction of whether this network is likely to be unusable in a few seconds. */ + public boolean isExiting() { + return mExiting; + } + + /** + * Get the legacy score. + * @hide + */ + public int getLegacyScore() { + return mLegacyScore; + } + + /** Builder for NetworkScore. */ + public static class Builder { + private int mPolicy = 0; + @NonNull + private Metrics mLinkLayerMetrics = new Metrics(Metrics.LATENCY_UNKNOWN, + Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN); + @NonNull + private Metrics mEndToMetrics = new Metrics(Metrics.LATENCY_UNKNOWN, + Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN); + private int mSignalStrength = UNKNOWN_SIGNAL_STRENGTH; + private int mRange = RANGE_UNKNOWN; + private boolean mExiting = false; + private int mLegacyScore = 0; + @NonNull private Bundle mExtensions = new Bundle(); + + /** Create a new builder. */ + public Builder() { } + + /** Add a policy flag. */ + @NonNull public Builder addPolicy(@Policy final int policy) { + mPolicy |= policy; + return this; + } + + /** Clear a policy flag */ + @NonNull public Builder clearPolicy(@Policy final int policy) { + mPolicy &= ~policy; + return this; + } + + /** Set the link layer metrics. */ + @NonNull public Builder setLinkLayerMetrics(@NonNull final Metrics linkLayerMetrics) { + mLinkLayerMetrics = linkLayerMetrics; + return this; + } + + /** Set the end-to-end metrics. */ + @NonNull public Builder setEndToEndMetrics(@NonNull final Metrics endToEndMetrics) { + mEndToMetrics = endToEndMetrics; + return this; + } + + /** Set the signal strength. */ + @NonNull public Builder setSignalStrength( + @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH) + final int signalStrength) { + mSignalStrength = signalStrength; + return this; + } + + /** Set the range. */ + @NonNull public Builder setRange(@Range final int range) { + mRange = range; + return this; + } + + /** Set whether this network is exiting. */ + @NonNull public Builder setExiting(final boolean exiting) { + mExiting = exiting; + return this; + } + + /** Add a parcelable extension. */ + @NonNull public Builder setLegacyScore(final int legacyScore) { + mLegacyScore = legacyScore; + return this; + } + + /** Build the NetworkScore object represented by this builder. */ + @NonNull public NetworkScore build() { + return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToMetrics, + mSignalStrength, mRange, mExiting, mLegacyScore); + } } @Override @@ -88,9 +429,17 @@ public final class NetworkScore implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - synchronized (this) { - dest.writeBundle(mExtensions); - } + dest.writeInt(mPolicy); + dest.writeInt(mLinkLayerMetrics.latencyMs); + dest.writeInt(mLinkLayerMetrics.downlinkBandwidthKBps); + dest.writeInt(mLinkLayerMetrics.uplinkBandwidthKBps); + dest.writeInt(mEndToEndMetrics.latencyMs); + dest.writeInt(mEndToEndMetrics.downlinkBandwidthKBps); + dest.writeInt(mEndToEndMetrics.uplinkBandwidthKBps); + dest.writeInt(mSignalStrength); + dest.writeInt(mRange); + dest.writeBoolean(mExiting); + dest.writeInt(mLegacyScore); } public static final @NonNull Creator CREATOR = new Creator() { @@ -106,57 +455,52 @@ public final class NetworkScore implements Parcelable { }; private NetworkScore(@NonNull Parcel in) { - mExtensions = in.readBundle(); + mPolicy = in.readInt(); + mLinkLayerMetrics = new Metrics(in.readInt(), in.readInt(), in.readInt()); + mEndToEndMetrics = new Metrics(in.readInt(), in.readInt(), in.readInt()); + mSignalStrength = in.readInt(); + mRange = in.readInt(); + mExiting = in.readBoolean(); + mLegacyScore = in.readInt(); } - // TODO: Modify this method once new fields are added into this class. @Override public boolean equals(@Nullable Object obj) { if (!(obj instanceof NetworkScore)) { return false; } final NetworkScore other = (NetworkScore) obj; - return bundlesEqual(mExtensions, other.mExtensions); + return mPolicy == other.mPolicy + && mLinkLayerMetrics.latencyMs == other.mLinkLayerMetrics.latencyMs + && mLinkLayerMetrics.uplinkBandwidthKBps + == other.mLinkLayerMetrics.uplinkBandwidthKBps + && mEndToEndMetrics.latencyMs == other.mEndToEndMetrics.latencyMs + && mEndToEndMetrics.uplinkBandwidthKBps + == other.mEndToEndMetrics.uplinkBandwidthKBps + && mSignalStrength == other.mSignalStrength + && mRange == other.mRange + && mExiting == other.mExiting + && mLegacyScore == other.mLegacyScore; } @Override public int hashCode() { - int result = 29; - for (String key : mExtensions.keySet()) { - final Object value = mExtensions.get(key); - // The key may be null, so call Objects.hash() is safer. - result += 31 * value.hashCode() + 37 * Objects.hash(key); - } - return result; - } - - // mExtensions won't be null since the constructor will create it. - private boolean bundlesEqual(@NonNull Bundle bundle1, @NonNull Bundle bundle2) { - if (bundle1 == bundle2) { - return true; - } - - // This is unlikely but it's fine to add this clause here. - if (null == bundle1 || null == bundle2) { - return false; - } - - if (bundle1.size() != bundle2.size()) { - return false; - } - - for (String key : bundle1.keySet()) { - final Object value1 = bundle1.get(key); - final Object value2 = bundle2.get(key); - if (!Objects.equals(value1, value2)) { - return false; - } - } - return true; + return Objects.hash(mPolicy, + mLinkLayerMetrics.latencyMs, mLinkLayerMetrics.uplinkBandwidthKBps, + mEndToEndMetrics.latencyMs, mEndToEndMetrics.uplinkBandwidthKBps, + mSignalStrength, mRange, mExiting, mLegacyScore); } /** Convert to a string */ public String toString() { - return "NetworkScore[" + mExtensions.toString() + "]"; + return "NetworkScore [" + + "Policy = " + mPolicy + + " LinkLayerMetrics = " + mLinkLayerMetrics + + " EndToEndMetrics = " + mEndToEndMetrics + + " SignalStrength = " + mSignalStrength + + " Range = " + mRange + + " Exiting = " + mExiting + + " LegacyScore = " + mLegacyScore + + "]"; } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 1c9f5dc9c2..ba4708f1cd 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5510,20 +5510,6 @@ public class ConnectivityService extends IConnectivityManager.Stub return nri.request.requestId == mDefaultRequest.requestId; } - // TODO : remove this method. It's a stopgap measure to help sheperding a number of dependent - // changes that would conflict throughout the automerger graph. Having this method temporarily - // helps with the process of going through with all these dependent changes across the entire - // tree. - /** - * Register a new agent. {@see #registerNetworkAgent} below. - */ - public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, - LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - int currentScore, NetworkAgentConfig networkAgentConfig) { - return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities, - currentScore, networkAgentConfig, NetworkProvider.ID_NONE); - } - /** * Register a new agent with ConnectivityService to handle a network. * @@ -5542,7 +5528,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { + NetworkScore currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { enforceNetworkFactoryPermission(); LinkProperties lp = new LinkProperties(linkProperties); @@ -5550,12 +5536,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network // satisfies mDefaultRequest. final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); - final NetworkScore ns = new NetworkScore(); - ns.putIntExtension(NetworkScore.LEGACY_SCORE, currentScore); final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc, - ns, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), this, - mNetd, mDnsResolver, mNMS, providerId); + currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), + this, mNetd, mDnsResolver, mNMS, providerId); // Make sure the network capabilities reflect what the agent info says. nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); final String extraInfo = networkInfo.getExtraInfo(); diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index d66aec5761..3cfe916049 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -483,7 +483,7 @@ public class NetworkAgentInfo implements Comparable { return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE; } - int score = mNetworkScore.getIntExtension(NetworkScore.LEGACY_SCORE); + int score = mNetworkScore.getLegacyScore(); if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) { score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY; } diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index a35fb407bc..7ae9e95a52 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -40,6 +40,7 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkProvider; +import android.net.NetworkScore; import android.net.NetworkSpecifier; import android.net.SocketKeepalive; import android.net.UidRange; @@ -155,9 +156,13 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { } } + private NetworkScore makeNetworkScore(final int legacyScore) { + return new NetworkScore.Builder().setLegacyScore(legacyScore).build(); + } + public void adjustScore(int change) { mScore += change; - mNetworkAgent.sendNetworkScore(mScore); + mNetworkAgent.sendNetworkScore(makeNetworkScore(mScore)); } public int getScore() { diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index e863266c4b..25e9057fd1 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -353,8 +353,7 @@ public class LingerMonitorTest { NetworkCapabilities caps = new NetworkCapabilities(); caps.addCapability(0); caps.addTransportType(transport); - NetworkScore ns = new NetworkScore(); - ns.putIntExtension(NetworkScore.LEGACY_SCORE, 50); + NetworkScore ns = new NetworkScore.Builder().setLegacyScore(50).build(); NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null, caps, ns, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS, NetworkProvider.ID_NONE); From 5cb7ef9f089b7097a3250720940165d5b81663dc Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 6 Nov 2019 00:20:15 -0800 Subject: [PATCH 048/229] Add separate user consent for Platform VPNs This change adds a new VPN user consent flow (using the same text) for granting the lesser OP_ACTIVATE_PLATFORM_VPN. A new PlatformVpnConfirmDialog is created as a subclass to preserve all logic, but ensure the right appop is granted for the relevant dialog. Intent extras were considered, but are inherently unsafe, since the caller may add any extras that they would want. Bug: 144246835 Test: FrameworksNetTests passing Change-Id: Ia6f36207d43c3748f938430c2780dcf29e5623f3 --- .../android/net/IConnectivityManager.aidl | 2 +- .../android/server/ConnectivityService.java | 27 ++++++---- .../net/java/android/net/VpnManagerTest.java | 11 +++- .../android/server/connectivity/VpnTest.java | 50 ++++++++++++++++++- 4 files changed, 75 insertions(+), 15 deletions(-) diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 6baa383240..1089a197ff 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -117,7 +117,7 @@ interface IConnectivityManager boolean prepareVpn(String oldPackage, String newPackage, int userId); - void setVpnPackageAuthorization(String packageName, int userId, boolean authorized); + void setVpnPackageAuthorization(String packageName, int userId, int vpnType); ParcelFileDescriptor establishVpn(in VpnConfig config); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 8c8a4e22d4..a1a953f865 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -109,6 +109,7 @@ import android.net.SocketKeepalive; import android.net.TetheringManager; import android.net.UidRange; import android.net.Uri; +import android.net.VpnManager; import android.net.VpnService; import android.net.metrics.IpConnectivityLog; import android.net.metrics.NetworkEvent; @@ -4317,7 +4318,7 @@ public class ConnectivityService extends IConnectivityManager.Stub throwIfLockdownEnabled(); Vpn vpn = mVpns.get(userId); if (vpn != null) { - return vpn.prepare(oldPackage, newPackage, false); + return vpn.prepare(oldPackage, newPackage, VpnManager.TYPE_VPN_SERVICE); } else { return false; } @@ -4325,26 +4326,29 @@ public class ConnectivityService extends IConnectivityManager.Stub } /** - * Set whether the VPN package has the ability to launch VPNs without user intervention. - * This method is used by system-privileged apps. - * VPN permissions are checked in the {@link Vpn} class. If the caller is not {@code userId}, - * {@link android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. + * Set whether the VPN package has the ability to launch VPNs without user intervention. This + * method is used by system-privileged apps. VPN permissions are checked in the {@link Vpn} + * class. If the caller is not {@code userId}, {@link + * android.Manifest.permission.INTERACT_ACROSS_USERS_FULL} permission is required. * * @param packageName The package for which authorization state should change. * @param userId User for whom {@code packageName} is installed. * @param authorized {@code true} if this app should be able to start a VPN connection without - * explicit user approval, {@code false} if not. - * + * explicit user approval, {@code false} if not. + * @param vpnType The {@link VpnManager.VpnType} constant representing what class of VPN + * permissions should be granted. When unauthorizing an app, {@link + * VpnManager.TYPE_VPN_NONE} should be used. * @hide */ @Override - public void setVpnPackageAuthorization(String packageName, int userId, boolean authorized) { + public void setVpnPackageAuthorization( + String packageName, int userId, @VpnManager.VpnType int vpnType) { enforceCrossUserPermission(userId); synchronized (mVpns) { Vpn vpn = mVpns.get(userId); if (vpn != null) { - vpn.setPackageAuthorization(packageName, authorized); + vpn.setPackageAuthorization(packageName, vpnType); } } } @@ -7217,7 +7221,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final String alwaysOnPackage = getAlwaysOnVpnPackage(userId); if (alwaysOnPackage != null) { setAlwaysOnVpnPackage(userId, null, false, null); - setVpnPackageAuthorization(alwaysOnPackage, userId, false); + setVpnPackageAuthorization(alwaysOnPackage, userId, VpnManager.TYPE_VPN_NONE); } // Turn Always-on VPN off @@ -7240,7 +7244,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } else { // Prevent this app (packagename = vpnConfig.user) from initiating // VPN connections in the future without user intervention. - setVpnPackageAuthorization(vpnConfig.user, userId, false); + setVpnPackageAuthorization( + vpnConfig.user, userId, VpnManager.TYPE_VPN_NONE); prepareVpn(null, VpnConfig.LEGACY_VPN, userId); } diff --git a/tests/net/java/android/net/VpnManagerTest.java b/tests/net/java/android/net/VpnManagerTest.java index 97551c94e2..95a794235a 100644 --- a/tests/net/java/android/net/VpnManagerTest.java +++ b/tests/net/java/android/net/VpnManagerTest.java @@ -16,6 +16,7 @@ package android.net; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.mockito.Matchers.any; @@ -24,6 +25,8 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.ComponentName; +import android.content.Intent; import android.test.mock.MockContext; import androidx.test.filters.SmallTest; @@ -78,7 +81,13 @@ public class VpnManagerTest { when(mMockCs.provisionVpnProfile(any(VpnProfile.class), eq(PKG_NAME))).thenReturn(false); // Expect intent to be returned, as consent has not already been granted. - assertNotNull(mVpnManager.provisionVpnProfile(profile)); + final Intent intent = mVpnManager.provisionVpnProfile(profile); + assertNotNull(intent); + + final ComponentName expectedComponentName = + ComponentName.unflattenFromString( + "com.android.vpndialogs/com.android.vpndialogs.PlatformVpnConfirmDialog"); + assertEquals(expectedComponentName, intent.getComponent()); verify(mMockCs).provisionVpnProfile(eq(profile.toVpnProfile()), eq(PKG_NAME)); } diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 084ec73302..155c61f3f8 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -63,6 +63,7 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo.DetailedState; import android.net.UidRange; +import android.net.VpnManager; import android.net.VpnService; import android.os.Build.VERSION_CODES; import android.os.Bundle; @@ -471,12 +472,12 @@ public class VpnTest { order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser)); // When a new VPN package is set the rules should change to cover that package. - vpn.prepare(null, PKGS[0], false /* isPlatformVpn */); + vpn.prepare(null, PKGS[0], VpnManager.TYPE_VPN_SERVICE); order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(entireUser)); order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(exceptPkg0)); // When that VPN package is unset, everything should be undone again in reverse. - vpn.prepare(null, VpnConfig.LEGACY_VPN, false /* isPlatformVpn */); + vpn.prepare(null, VpnConfig.LEGACY_VPN, VpnManager.TYPE_VPN_SERVICE); order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(exceptPkg0)); order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser)); } @@ -817,6 +818,51 @@ public class VpnTest { eq(TEST_VPN_PKG)); } + @Test + public void testSetPackageAuthorizationVpnService() throws Exception { + final Vpn vpn = createVpnAndSetupUidChecks(); + + assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_SERVICE)); + verify(mAppOps) + .setMode( + eq(AppOpsManager.OP_ACTIVATE_VPN), + eq(Process.myUid()), + eq(TEST_VPN_PKG), + eq(AppOpsManager.MODE_ALLOWED)); + } + + @Test + public void testSetPackageAuthorizationPlatformVpn() throws Exception { + final Vpn vpn = createVpnAndSetupUidChecks(); + + assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_PLATFORM)); + verify(mAppOps) + .setMode( + eq(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN), + eq(Process.myUid()), + eq(TEST_VPN_PKG), + eq(AppOpsManager.MODE_ALLOWED)); + } + + @Test + public void testSetPackageAuthorizationRevokeAuthorization() throws Exception { + final Vpn vpn = createVpnAndSetupUidChecks(); + + assertTrue(vpn.setPackageAuthorization(TEST_VPN_PKG, VpnManager.TYPE_VPN_NONE)); + verify(mAppOps) + .setMode( + eq(AppOpsManager.OP_ACTIVATE_VPN), + eq(Process.myUid()), + eq(TEST_VPN_PKG), + eq(AppOpsManager.MODE_IGNORED)); + verify(mAppOps) + .setMode( + eq(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN), + eq(Process.myUid()), + eq(TEST_VPN_PKG), + eq(AppOpsManager.MODE_IGNORED)); + } + /** * Mock some methods of vpn object. */ From c8e5bf6effd175c0e95e8fea5d31147a4d787cb0 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Sun, 5 Jan 2020 14:06:39 -0800 Subject: [PATCH 049/229] Implement INetworkMonitorCallbacks#notifyNetworkTestedWithExtras. INetworkMonitorCallbacks defines notifyNetworkTestedWithExtras() for notifying ConnectivityService of networks being tested along with a PersistableBundle of extras. A new event is introduced for NetworkStateTrackerHandler to notify the ConnectivityDiagnosticsHandler before continuing with the normal processing for "network tested" notifications. The event is also used in the ConnectivityDiagnosticsHandler. Bug: 143187964 Bug: 147391402 Test: compiles. Test: atest CtsNetTestCases FrameworksNetTests Change-Id: Iab29da790c0f5faae68227770bc3a84bbc94f124 (cherry picked from commit c5326407d592490783259a48a8ca653c4ff13122) --- .../net/ConnectivityDiagnosticsManager.java | 3 +- .../android/net/IConnectivityManager.aidl | 2 +- .../java/android/net/NetworkCapabilities.java | 4 +- .../android/server/ConnectivityService.java | 354 +++++++++++++----- .../ConnectivityDiagnosticsManagerTest.java | 15 +- .../server/ConnectivityServiceTest.java | 179 ++++++++- 6 files changed, 455 insertions(+), 102 deletions(-) diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java index 140363c482..b128ea7f3e 100644 --- a/core/java/android/net/ConnectivityDiagnosticsManager.java +++ b/core/java/android/net/ConnectivityDiagnosticsManager.java @@ -676,7 +676,8 @@ public class ConnectivityDiagnosticsManager { } try { - mService.registerConnectivityDiagnosticsCallback(binder, request); + mService.registerConnectivityDiagnosticsCallback( + binder, request, mContext.getOpPackageName()); } catch (RemoteException exception) { exception.rethrowFromSystemServer(); } diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 1089a197ff..0fae607ca6 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -222,7 +222,7 @@ interface IConnectivityManager boolean isCallerCurrentAlwaysOnVpnLockdownApp(); void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback, - in NetworkRequest request); + in NetworkRequest request, String callingPackageName); void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback); IBinder startOrGetTestNetworkService(); diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 4f4e27b446..cf5f2259af 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -858,8 +858,8 @@ public final class NetworkCapabilities implements Parcelable { * *

In general, user-supplied networks (such as WiFi networks) do not have an administrator. * - *

An app is granted owner privileges over Networks that it supplies. Owner privileges - * implicitly include administrator privileges. + *

An app is granted owner privileges over Networks that it supplies. The owner UID MUST + * always be included in administratorUids. * * @param administratorUids the UIDs to be set as administrators of this Network. * @hide diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2968a81683..9702c50279 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -48,8 +48,11 @@ import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; import static android.system.OsConstants.IPPROTO_UDP; +import static java.util.Map.Entry; + import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.AppOpsManager; import android.app.BroadcastOptions; import android.app.NotificationManager; import android.app.PendingIntent; @@ -62,6 +65,7 @@ import android.content.res.Configuration; import android.database.ContentObserver; import android.net.CaptivePortal; import android.net.ConnectionInfo; +import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import android.net.ConnectivityManager; import android.net.ICaptivePortal; import android.net.IConnectivityDiagnosticsCallback; @@ -130,6 +134,7 @@ import android.os.Message; import android.os.Messenger; import android.os.ParcelFileDescriptor; import android.os.Parcelable; +import android.os.PersistableBundle; import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; @@ -170,6 +175,7 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.AsyncChannel; import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.LocationPermissionChecker; import com.android.internal.util.MessageUtils; import com.android.internal.util.XmlUtils; import com.android.server.am.BatteryStatsService; @@ -492,9 +498,9 @@ public class ConnectivityService extends IConnectivityManager.Stub /** * Event for NetworkMonitor/NetworkAgentInfo to inform ConnectivityService that the network has * been tested. - * obj = String representing URL that Internet probe was redirect to, if it was redirected. - * arg1 = One of the NETWORK_TESTED_RESULT_* constants. - * arg2 = NetID. + * obj = {@link NetworkTestedResults} representing information sent from NetworkMonitor. + * data = PersistableBundle of extras passed from NetworkMonitor. If {@link + * NetworkMonitorCallbacks#notifyNetworkTested} is called, this will be null. */ private static final int EVENT_NETWORK_TESTED = 41; @@ -596,6 +602,9 @@ public class ConnectivityService extends IConnectivityManager.Stub private Set mWolSupportedInterfaces; private TelephonyManager mTelephonyManager; + private final AppOpsManager mAppOpsManager; + + private final LocationPermissionChecker mLocationPermissionChecker; private KeepaliveTracker mKeepaliveTracker; private NetworkNotificationManager mNotifier; @@ -992,6 +1001,8 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetd = netd; mKeyStore = KeyStore.getInstance(); mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); + mLocationPermissionChecker = new LocationPermissionChecker(mContext); // To ensure uid rules are synchronized with Network Policy, register for // NetworkPolicyManagerService events must happen prior to NetworkPolicyManagerService @@ -2101,6 +2112,12 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } + private boolean checkNetworkStackPermission(int pid, int uid) { + return checkAnyPermissionOf(pid, uid, + android.Manifest.permission.NETWORK_STACK, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); + } + private boolean checkNetworkSignalStrengthWakeupPermission(int pid, int uid) { return checkAnyPermissionOf(pid, uid, android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP, @@ -2747,88 +2764,21 @@ public class ConnectivityService extends IConnectivityManager.Stub break; } case EVENT_NETWORK_TESTED: { - final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); + final NetworkTestedResults results = (NetworkTestedResults) msg.obj; + + final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(results.mNetId); if (nai == null) break; - final boolean wasPartial = nai.partialConnectivity; - nai.partialConnectivity = ((msg.arg1 & NETWORK_VALIDATION_RESULT_PARTIAL) != 0); - final boolean partialConnectivityChanged = - (wasPartial != nai.partialConnectivity); + handleNetworkTested(nai, results.mTestResult, + (results.mRedirectUrl == null) ? "" : results.mRedirectUrl); - final boolean valid = ((msg.arg1 & NETWORK_VALIDATION_RESULT_VALID) != 0); - final boolean wasValidated = nai.lastValidated; - final boolean wasDefault = isDefaultNetwork(nai); - // Only show a connected notification if the network is pending validation - // after the captive portal app was open, and it has now validated. - if (nai.captivePortalValidationPending && valid) { - // User is now logged in, network validated. - nai.captivePortalValidationPending = false; - showNetworkNotification(nai, NotificationType.LOGGED_IN); - } - - final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : ""; - - if (DBG) { - final String logMsg = !TextUtils.isEmpty(redirectUrl) - ? " with redirect to " + redirectUrl - : ""; - log(nai.name() + " validation " + (valid ? "passed" : "failed") + logMsg); - } - if (valid != nai.lastValidated) { - if (wasDefault) { - mDeps.getMetricsLogger() - .defaultNetworkMetrics().logDefaultNetworkValidity( - SystemClock.elapsedRealtime(), valid); - } - final int oldScore = nai.getCurrentScore(); - nai.lastValidated = valid; - nai.everValidated |= valid; - updateCapabilities(oldScore, nai, nai.networkCapabilities); - // If score has changed, rebroadcast to NetworkProviders. b/17726566 - if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai); - if (valid) { - handleFreshlyValidatedNetwork(nai); - // Clear NO_INTERNET, PRIVATE_DNS_BROKEN, PARTIAL_CONNECTIVITY and - // LOST_INTERNET notifications if network becomes valid. - mNotifier.clearNotification(nai.network.netId, - NotificationType.NO_INTERNET); - mNotifier.clearNotification(nai.network.netId, - NotificationType.LOST_INTERNET); - mNotifier.clearNotification(nai.network.netId, - NotificationType.PARTIAL_CONNECTIVITY); - mNotifier.clearNotification(nai.network.netId, - NotificationType.PRIVATE_DNS_BROKEN); - // If network becomes valid, the hasShownBroken should be reset for - // that network so that the notification will be fired when the private - // DNS is broken again. - nai.networkAgentConfig.hasShownBroken = false; - } - } else if (partialConnectivityChanged) { - updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); - } - updateInetCondition(nai); - // Let the NetworkAgent know the state of its network - Bundle redirectUrlBundle = new Bundle(); - redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, redirectUrl); - // TODO: Evaluate to update partial connectivity to status to NetworkAgent. - nai.asyncChannel.sendMessage( - NetworkAgent.CMD_REPORT_NETWORK_STATUS, - (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK), - 0, redirectUrlBundle); - - // If NetworkMonitor detects partial connectivity before - // EVENT_PROMPT_UNVALIDATED arrives, show the partial connectivity notification - // immediately. Re-notify partial connectivity silently if no internet - // notification already there. - if (!wasPartial && nai.partialConnectivity) { - // Remove delayed message if there is a pending message. - mHandler.removeMessages(EVENT_PROMPT_UNVALIDATED, nai.network); - handlePromptUnvalidated(nai.network); - } - - if (wasValidated && !nai.lastValidated) { - handleNetworkUnvalidated(nai); - } + // Invoke ConnectivityReport generation for this Network test event. + final Message m = + mConnectivityDiagnosticsHandler.obtainMessage( + ConnectivityDiagnosticsHandler.EVENT_NETWORK_TESTED, + new ConnectivityReportEvent(results.mTimestampMillis, nai)); + m.setData(msg.getData()); + mConnectivityDiagnosticsHandler.sendMessage(m); break; } case EVENT_PROVISIONING_NOTIFICATION: { @@ -2879,6 +2829,87 @@ public class ConnectivityService extends IConnectivityManager.Stub return true; } + private void handleNetworkTested( + @NonNull NetworkAgentInfo nai, int testResult, @NonNull String redirectUrl) { + final boolean wasPartial = nai.partialConnectivity; + nai.partialConnectivity = ((testResult & NETWORK_VALIDATION_RESULT_PARTIAL) != 0); + final boolean partialConnectivityChanged = + (wasPartial != nai.partialConnectivity); + + final boolean valid = ((testResult & NETWORK_VALIDATION_RESULT_VALID) != 0); + final boolean wasValidated = nai.lastValidated; + final boolean wasDefault = isDefaultNetwork(nai); + // Only show a connected notification if the network is pending validation + // after the captive portal app was open, and it has now validated. + if (nai.captivePortalValidationPending && valid) { + // User is now logged in, network validated. + nai.captivePortalValidationPending = false; + showNetworkNotification(nai, NotificationType.LOGGED_IN); + } + + if (DBG) { + final String logMsg = !TextUtils.isEmpty(redirectUrl) + ? " with redirect to " + redirectUrl + : ""; + log(nai.name() + " validation " + (valid ? "passed" : "failed") + logMsg); + } + if (valid != nai.lastValidated) { + if (wasDefault) { + mDeps.getMetricsLogger() + .defaultNetworkMetrics().logDefaultNetworkValidity( + SystemClock.elapsedRealtime(), valid); + } + final int oldScore = nai.getCurrentScore(); + nai.lastValidated = valid; + nai.everValidated |= valid; + updateCapabilities(oldScore, nai, nai.networkCapabilities); + // If score has changed, rebroadcast to NetworkProviders. b/17726566 + if (oldScore != nai.getCurrentScore()) sendUpdatedScoreToFactories(nai); + if (valid) { + handleFreshlyValidatedNetwork(nai); + // Clear NO_INTERNET, PRIVATE_DNS_BROKEN, PARTIAL_CONNECTIVITY and + // LOST_INTERNET notifications if network becomes valid. + mNotifier.clearNotification(nai.network.netId, + NotificationType.NO_INTERNET); + mNotifier.clearNotification(nai.network.netId, + NotificationType.LOST_INTERNET); + mNotifier.clearNotification(nai.network.netId, + NotificationType.PARTIAL_CONNECTIVITY); + mNotifier.clearNotification(nai.network.netId, + NotificationType.PRIVATE_DNS_BROKEN); + // If network becomes valid, the hasShownBroken should be reset for + // that network so that the notification will be fired when the private + // DNS is broken again. + nai.networkAgentConfig.hasShownBroken = false; + } + } else if (partialConnectivityChanged) { + updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); + } + updateInetCondition(nai); + // Let the NetworkAgent know the state of its network + Bundle redirectUrlBundle = new Bundle(); + redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, redirectUrl); + // TODO: Evaluate to update partial connectivity to status to NetworkAgent. + nai.asyncChannel.sendMessage( + NetworkAgent.CMD_REPORT_NETWORK_STATUS, + (valid ? NetworkAgent.VALID_NETWORK : NetworkAgent.INVALID_NETWORK), + 0, redirectUrlBundle); + + // If NetworkMonitor detects partial connectivity before + // EVENT_PROMPT_UNVALIDATED arrives, show the partial connectivity notification + // immediately. Re-notify partial connectivity silently if no internet + // notification already there. + if (!wasPartial && nai.partialConnectivity) { + // Remove delayed message if there is a pending message. + mHandler.removeMessages(EVENT_PROMPT_UNVALIDATED, nai.network); + handlePromptUnvalidated(nai.network); + } + + if (wasValidated && !nai.lastValidated) { + handleNetworkUnvalidated(nai); + } + } + private int getCaptivePortalMode() { return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.CAPTIVE_PORTAL_MODE, @@ -2927,8 +2958,23 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void notifyNetworkTested(int testResult, @Nullable String redirectUrl) { - mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(EVENT_NETWORK_TESTED, - testResult, mNetId, redirectUrl)); + notifyNetworkTestedWithExtras(testResult, redirectUrl, SystemClock.elapsedRealtime(), + PersistableBundle.EMPTY); + } + + @Override + public void notifyNetworkTestedWithExtras( + int testResult, + @Nullable String redirectUrl, + long timestampMillis, + @NonNull PersistableBundle extras) { + final Message msg = + mTrackerHandler.obtainMessage( + EVENT_NETWORK_TESTED, + new NetworkTestedResults( + mNetId, testResult, timestampMillis, redirectUrl)); + msg.setData(new Bundle(extras)); + mTrackerHandler.sendMessage(msg); } @Override @@ -7359,7 +7405,11 @@ public class ConnectivityService extends IConnectivityManager.Stub @GuardedBy("mVpns") private Vpn getVpnIfOwner() { - final int uid = Binder.getCallingUid(); + return getVpnIfOwner(Binder.getCallingUid()); + } + + @GuardedBy("mVpns") + private Vpn getVpnIfOwner(int uid) { final int user = UserHandle.getUserId(uid); final Vpn vpn = mVpns.get(user); @@ -7471,6 +7521,17 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private static final int EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK = 2; + /** + * Event for {@link NetworkStateTrackerHandler} to trigger ConnectivityReport callbacks + * after processing {@link #EVENT_NETWORK_TESTED} events. + * obj = {@link ConnectivityReportEvent} representing ConnectivityReport info reported from + * NetworkMonitor. + * data = PersistableBundle of extras passed from NetworkMonitor. + * + *

See {@link ConnectivityService#EVENT_NETWORK_TESTED}. + */ + private static final int EVENT_NETWORK_TESTED = ConnectivityService.EVENT_NETWORK_TESTED; + private ConnectivityDiagnosticsHandler(Looper looper) { super(looper); } @@ -7488,6 +7549,19 @@ public class ConnectivityService extends IConnectivityManager.Stub (IConnectivityDiagnosticsCallback) msg.obj, msg.arg1); break; } + case EVENT_NETWORK_TESTED: { + final ConnectivityReportEvent reportEvent = + (ConnectivityReportEvent) msg.obj; + + // This is safe because {@link + // NetworkMonitorCallbacks#notifyNetworkTestedWithExtras} receives a + // PersistableBundle and converts it to the Bundle in the incoming Message. If + // {@link NetworkMonitorCallbacks#notifyNetworkTested} is called, msg.data will + // not be set. This is also safe, as msg.getData() will return an empty Bundle. + final PersistableBundle extras = new PersistableBundle(msg.getData()); + handleNetworkTestedWithExtras(reportEvent, extras); + break; + } } } } @@ -7497,12 +7571,16 @@ public class ConnectivityService extends IConnectivityManager.Stub class ConnectivityDiagnosticsCallbackInfo implements Binder.DeathRecipient { @NonNull private final IConnectivityDiagnosticsCallback mCb; @NonNull private final NetworkRequestInfo mRequestInfo; + @NonNull private final String mCallingPackageName; @VisibleForTesting ConnectivityDiagnosticsCallbackInfo( - @NonNull IConnectivityDiagnosticsCallback cb, @NonNull NetworkRequestInfo nri) { + @NonNull IConnectivityDiagnosticsCallback cb, + @NonNull NetworkRequestInfo nri, + @NonNull String callingPackageName) { mCb = cb; mRequestInfo = nri; + mCallingPackageName = callingPackageName; } @Override @@ -7512,6 +7590,39 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + /** + * Class used for sending information from {@link + * NetworkMonitorCallbacks#notifyNetworkTestedWithExtras} to the handler for processing it. + */ + private static class NetworkTestedResults { + private final int mNetId; + private final int mTestResult; + private final long mTimestampMillis; + @Nullable private final String mRedirectUrl; + + private NetworkTestedResults( + int netId, int testResult, long timestampMillis, @Nullable String redirectUrl) { + mNetId = netId; + mTestResult = testResult; + mTimestampMillis = timestampMillis; + mRedirectUrl = redirectUrl; + } + } + + /** + * Class used for sending information from {@link NetworkStateTrackerHandler} to {@link + * ConnectivityDiagnosticsHandler}. + */ + private static class ConnectivityReportEvent { + private final long mTimestampMillis; + @NonNull private final NetworkAgentInfo mNai; + + private ConnectivityReportEvent(long timestampMillis, @NonNull NetworkAgentInfo nai) { + mTimestampMillis = timestampMillis; + mNai = nai; + } + } + private void handleRegisterConnectivityDiagnosticsCallback( @NonNull ConnectivityDiagnosticsCallbackInfo cbInfo) { ensureRunningOnConnectivityServiceThread(); @@ -7559,13 +7670,80 @@ public class ConnectivityService extends IConnectivityManager.Stub cb.asBinder().unlinkToDeath(mConnectivityDiagnosticsCallbacks.remove(cb), 0); } + private void handleNetworkTestedWithExtras( + @NonNull ConnectivityReportEvent reportEvent, @NonNull PersistableBundle extras) { + final NetworkAgentInfo nai = reportEvent.mNai; + final ConnectivityReport report = + new ConnectivityReport( + reportEvent.mNai.network, + reportEvent.mTimestampMillis, + nai.linkProperties, + nai.networkCapabilities, + extras); + final List results = + getMatchingPermissionedCallbacks(nai); + for (final IConnectivityDiagnosticsCallback cb : results) { + try { + cb.onConnectivityReport(report); + } catch (RemoteException ex) { + loge("Error invoking onConnectivityReport", ex); + } + } + } + + private List getMatchingPermissionedCallbacks( + @NonNull NetworkAgentInfo nai) { + final List results = new ArrayList<>(); + for (Entry entry : + mConnectivityDiagnosticsCallbacks.entrySet()) { + final ConnectivityDiagnosticsCallbackInfo cbInfo = entry.getValue(); + final NetworkRequestInfo nri = cbInfo.mRequestInfo; + if (nai.satisfies(nri.request)) { + if (checkConnectivityDiagnosticsPermissions( + nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) { + results.add(entry.getKey()); + } + } + } + return results; + } + + @VisibleForTesting + boolean checkConnectivityDiagnosticsPermissions( + int callbackPid, int callbackUid, NetworkAgentInfo nai, String callbackPackageName) { + if (checkNetworkStackPermission(callbackPid, callbackUid)) { + return true; + } + + if (!mLocationPermissionChecker.checkLocationPermission( + callbackPackageName, null /* featureId */, callbackUid, null /* message */)) { + return false; + } + + synchronized (mVpns) { + if (getVpnIfOwner(callbackUid) != null) { + return true; + } + } + + // Administrator UIDs also contains the Owner UID + if (nai.networkCapabilities.getAdministratorUids().contains(callbackUid)) { + return true; + } + + return false; + } + @Override public void registerConnectivityDiagnosticsCallback( - @NonNull IConnectivityDiagnosticsCallback callback, @NonNull NetworkRequest request) { + @NonNull IConnectivityDiagnosticsCallback callback, + @NonNull NetworkRequest request, + @NonNull String callingPackageName) { if (request.legacyType != TYPE_NONE) { throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated." + " Please use NetworkCapabilities instead."); } + mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName); // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid // and administrator uids to be safe. @@ -7583,7 +7761,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // callback's binder death. final NetworkRequestInfo nri = new NetworkRequestInfo(requestWithId); final ConnectivityDiagnosticsCallbackInfo cbInfo = - new ConnectivityDiagnosticsCallbackInfo(callback, nri); + new ConnectivityDiagnosticsCallbackInfo(callback, nri, callingPackageName); mConnectivityDiagnosticsHandler.sendMessage( mConnectivityDiagnosticsHandler.obtainMessage( diff --git a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java index 2d5df4f47e..0628691c33 100644 --- a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java +++ b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java @@ -38,6 +38,8 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import android.content.Context; import android.os.PersistableBundle; +import androidx.test.InstrumentationRegistry; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -58,21 +60,26 @@ public class ConnectivityDiagnosticsManagerTest { private static final Executor INLINE_EXECUTOR = x -> x.run(); - @Mock private Context mContext; @Mock private IConnectivityManager mService; @Mock private ConnectivityDiagnosticsCallback mCb; + private Context mContext; private ConnectivityDiagnosticsBinder mBinder; private ConnectivityDiagnosticsManager mManager; + private String mPackageName; + @Before public void setUp() { - mContext = mock(Context.class); + mContext = InstrumentationRegistry.getContext(); + mService = mock(IConnectivityManager.class); mCb = mock(ConnectivityDiagnosticsCallback.class); mBinder = new ConnectivityDiagnosticsBinder(mCb, INLINE_EXECUTOR); mManager = new ConnectivityDiagnosticsManager(mContext, mService); + + mPackageName = mContext.getOpPackageName(); } @After @@ -271,7 +278,7 @@ public class ConnectivityDiagnosticsManagerTest { mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); verify(mService).registerConnectivityDiagnosticsCallback( - any(ConnectivityDiagnosticsBinder.class), eq(request)); + any(ConnectivityDiagnosticsBinder.class), eq(request), eq(mPackageName)); assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); } @@ -302,7 +309,7 @@ public class ConnectivityDiagnosticsManagerTest { // verify that re-registering is successful mManager.registerConnectivityDiagnosticsCallback(request, INLINE_EXECUTOR, mCb); verify(mService, times(2)).registerConnectivityDiagnosticsCallback( - any(ConnectivityDiagnosticsBinder.class), eq(request)); + any(ConnectivityDiagnosticsBinder.class), eq(request), eq(mPackageName)); assertTrue(ConnectivityDiagnosticsManager.sCallbacks.containsKey(mCb)); } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 028c1dad82..bd460272c8 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -23,6 +23,7 @@ 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; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL; @@ -119,6 +120,7 @@ import static org.mockito.Mockito.when; import android.Manifest; import android.annotation.NonNull; import android.app.AlarmManager; +import android.app.AppOpsManager; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; @@ -132,6 +134,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.content.res.Resources; +import android.location.LocationManager; import android.net.CaptivePortalData; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; @@ -177,6 +180,7 @@ import android.net.shared.PrivateDnsConfig; import android.net.util.MultinetworkPolicyTracker; import android.os.BadParcelableException; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.ConditionVariable; import android.os.Handler; @@ -187,6 +191,7 @@ import android.os.Looper; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; +import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; @@ -218,6 +223,7 @@ import com.android.server.connectivity.DefaultNetworkMetrics; import com.android.server.connectivity.IpConnectivityMetrics; import com.android.server.connectivity.MockableSystemProperties; import com.android.server.connectivity.Nat464Xlat; +import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkNotificationManager.NotificationType; import com.android.server.connectivity.ProxyTracker; import com.android.server.connectivity.Vpn; @@ -292,6 +298,8 @@ public class ConnectivityServiceTest { private static final int UNREASONABLY_LONG_ALARM_WAIT_MS = 1000; + private static final long TIMESTAMP = 1234L; + private static final String CLAT_PREFIX = "v4-"; private static final String MOBILE_IFNAME = "test_rmnet_data0"; private static final String WIFI_IFNAME = "test_wlan0"; @@ -327,6 +335,8 @@ public class ConnectivityServiceTest { @Mock AlarmManager mAlarmManager; @Mock IConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback; @Mock IBinder mIBinder; + @Mock LocationManager mLocationManager; + @Mock AppOpsManager mAppOpsManager; private ArgumentCaptor mResolverParamsParcelCaptor = ArgumentCaptor.forClass(ResolverParamsParcel.class); @@ -412,6 +422,8 @@ public class ConnectivityServiceTest { if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack; if (Context.USER_SERVICE.equals(name)) return mUserManager; if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager; + if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager; + if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager; return super.getSystemService(name); } @@ -564,6 +576,7 @@ public class ConnectivityServiceTest { private int mProbesCompleted; private int mProbesSucceeded; private String mNmValidationRedirectUrl = null; + private PersistableBundle mValidationExtras = PersistableBundle.EMPTY; private boolean mNmProvNotificationRequested = false; private final ConditionVariable mNetworkStatusReceived = new ConditionVariable(); @@ -631,8 +644,8 @@ public class ConnectivityServiceTest { } mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded); - mNmCallbacks.notifyNetworkTested( - mNmValidationResult, mNmValidationRedirectUrl); + mNmCallbacks.notifyNetworkTestedWithExtras( + mNmValidationResult, mNmValidationRedirectUrl, TIMESTAMP, mValidationExtras); if (mNmValidationRedirectUrl != null) { mNmCallbacks.showProvisioningNotification( @@ -970,6 +983,8 @@ public class ConnectivityServiceTest { // not inherit from NetworkAgent. private TestNetworkAgentWrapper mMockNetworkAgent; + private VpnInfo mVpnInfo; + public MockVpn(int userId) { super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService, userId); @@ -1041,6 +1056,17 @@ public class ConnectivityServiceTest { mConnected = false; mConfig = null; } + + @Override + public synchronized VpnInfo getVpnInfo() { + if (mVpnInfo != null) return mVpnInfo; + + return super.getVpnInfo(); + } + + private void setVpnInfo(VpnInfo vpnInfo) { + mVpnInfo = vpnInfo; + } } private void mockVpn(int uid) { @@ -6402,7 +6428,7 @@ public class ConnectivityServiceTest { new NetworkCapabilities(), TYPE_ETHERNET, 0, NetworkRequest.Type.NONE); try { mService.registerConnectivityDiagnosticsCallback( - mConnectivityDiagnosticsCallback, request); + mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); fail("registerConnectivityDiagnosticsCallback should throw on invalid NetworkRequest"); } catch (IllegalArgumentException expected) { } @@ -6416,7 +6442,7 @@ public class ConnectivityServiceTest { when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); mService.registerConnectivityDiagnosticsCallback( - mConnectivityDiagnosticsCallback, wifiRequest); + mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName()); verify(mIBinder, timeout(TIMEOUT_MS)) .linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt()); @@ -6440,7 +6466,7 @@ public class ConnectivityServiceTest { when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); mService.registerConnectivityDiagnosticsCallback( - mConnectivityDiagnosticsCallback, wifiRequest); + mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName()); verify(mIBinder, timeout(TIMEOUT_MS)) .linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt()); @@ -6451,7 +6477,7 @@ public class ConnectivityServiceTest { // Register the same callback again mService.registerConnectivityDiagnosticsCallback( - mConnectivityDiagnosticsCallback, wifiRequest); + mConnectivityDiagnosticsCallback, wifiRequest, mContext.getPackageName()); // Block until all other events are done processing. HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); @@ -6460,4 +6486,145 @@ public class ConnectivityServiceTest { mService.mConnectivityDiagnosticsCallbacks.containsKey( mConnectivityDiagnosticsCallback)); } + + @Test + public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception { + final NetworkAgentInfo naiWithoutUid = + new NetworkAgentInfo( + null, null, null, null, null, new NetworkCapabilities(), null, + mServiceContext, null, null, mService, null, null, null, 0); + + mServiceContext.setPermission( + android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); + assertTrue( + "NetworkStack permission not applied", + mService.checkConnectivityDiagnosticsPermissions( + Process.myPid(), Process.myUid(), naiWithoutUid, + mContext.getOpPackageName())); + } + + @Test + public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception { + final NetworkAgentInfo naiWithoutUid = + new NetworkAgentInfo( + null, null, null, null, null, new NetworkCapabilities(), null, + mServiceContext, null, null, mService, null, null, null, 0); + + mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); + + assertFalse( + "ACCESS_FINE_LOCATION permission necessary for Connectivity Diagnostics", + mService.checkConnectivityDiagnosticsPermissions( + Process.myPid(), Process.myUid(), naiWithoutUid, + mContext.getOpPackageName())); + } + + @Test + public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception { + final NetworkAgentInfo naiWithoutUid = + new NetworkAgentInfo( + null, null, null, null, null, new NetworkCapabilities(), null, + mServiceContext, null, null, mService, null, null, null, 0); + + setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); + mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); + + // setUp() calls mockVpn() which adds a VPN with the Test Runner's uid. Configure it to be + // active + final VpnInfo info = new VpnInfo(); + info.ownerUid = Process.myUid(); + info.vpnIface = "interface"; + mMockVpn.setVpnInfo(info); + assertTrue( + "Active VPN permission not applied", + mService.checkConnectivityDiagnosticsPermissions( + Process.myPid(), Process.myUid(), naiWithoutUid, + mContext.getOpPackageName())); + } + + @Test + public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception { + final NetworkCapabilities nc = new NetworkCapabilities(); + nc.setAdministratorUids(Arrays.asList(Process.myUid())); + final NetworkAgentInfo naiWithUid = + new NetworkAgentInfo( + null, null, null, null, null, nc, null, mServiceContext, null, null, + mService, null, null, null, 0); + + setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); + mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); + + // Disconnect mock vpn so the uid check on NetworkAgentInfo is tested + mMockVpn.disconnect(); + assertTrue( + "NetworkCapabilities administrator uid permission not applied", + mService.checkConnectivityDiagnosticsPermissions( + Process.myPid(), Process.myUid(), naiWithUid, mContext.getOpPackageName())); + } + + @Test + public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception { + final NetworkCapabilities nc = new NetworkCapabilities(); + nc.setOwnerUid(Process.myUid()); + nc.setAdministratorUids(Arrays.asList(Process.myUid())); + final NetworkAgentInfo naiWithUid = + new NetworkAgentInfo( + null, null, null, null, null, nc, null, mServiceContext, null, null, + mService, null, null, null, 0); + + setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, + Manifest.permission.ACCESS_FINE_LOCATION); + mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); + + // Use wrong pid and uid + assertFalse( + "Permissions allowed when they shouldn't be granted", + mService.checkConnectivityDiagnosticsPermissions( + Process.myPid() + 1, Process.myUid() + 1, naiWithUid, + mContext.getOpPackageName())); + } + + private void setupLocationPermissions( + int targetSdk, boolean locationToggle, String op, String perm) throws Exception { + final ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.targetSdkVersion = targetSdk; + when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) + .thenReturn(applicationInfo); + + when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle); + + when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName()))) + .thenReturn(AppOpsManager.MODE_ALLOWED); + + mServiceContext.setPermission(perm, PERMISSION_GRANTED); + } + + @Test + public void testConnectivityDiagnosticsCallbackOnConnectivityReport() throws Exception { + final NetworkRequest request = new NetworkRequest.Builder().build(); + when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); + + mServiceContext.setPermission( + android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); + + mService.registerConnectivityDiagnosticsCallback( + mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); + + // Block until all other events are done processing. + HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); + + // Connect the cell agent verify that it notifies TestNetworkCallback that it is available + final TestNetworkCallback callback = new TestNetworkCallback(); + mCm.registerDefaultNetworkCallback(callback); + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + callback.assertNoCallback(); + + // Wait for onConnectivityReport to fire + verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)) + .onConnectivityReport(any(ConnectivityReport.class)); + } } From a1bb47a7682c1fb8342118af3acd467f8870f970 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Mon, 6 Jan 2020 16:55:35 -0800 Subject: [PATCH 050/229] Implement INetworkMonitorCallbacks#notifyDataStallSuspected. INetworkMonitorCallbacks defines notifyDataStallSuspected() for notifying ConnectivityService of networks encountering a potential data stall. A new event is introduced for ConnectivityDiagnosticsHandler to process the notification and invoke the relevant ConnectivityDiagnosticsCallbacks. Bug: 143187964 Test: compiles Test: atest CtsNetTestCases FrameworksNetTests Change-Id: I70320bdda9855dced31e08e6a0b25329fb5cb535 (cherry picked from commit 6c51dc9de39d7963a6bc6d03eacadf2ba2131e20) --- .../android/server/ConnectivityService.java | 53 +++++++++++++++++++ .../server/ConnectivityServiceTest.java | 41 ++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index d0cd7ffee1..d1a5082ffd 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -66,6 +66,7 @@ import android.database.ContentObserver; import android.net.CaptivePortal; import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; +import android.net.ConnectivityDiagnosticsManager.DataStallReport; import android.net.ConnectivityManager; import android.net.ICaptivePortal; import android.net.IConnectivityDiagnosticsCallback; @@ -3015,6 +3016,21 @@ public class ConnectivityService extends IConnectivityManager.Stub EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE, mNetId)); } + @Override + public void notifyDataStallSuspected( + long timestampMillis, int detectionMethod, PersistableBundle extras) { + final Message msg = + mConnectivityDiagnosticsHandler.obtainMessage( + ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, + detectionMethod, mNetId, timestampMillis); + msg.setData(new Bundle(extras)); + + // NetworkStateTrackerHandler currently doesn't take any actions based on data + // stalls so send the message directly to ConnectivityDiagnosticsHandler and avoid + // the cost of going through two handlers. + mConnectivityDiagnosticsHandler.sendMessage(msg); + } + @Override public int getInterfaceVersion() { return this.VERSION; @@ -7546,6 +7562,16 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private static final int EVENT_NETWORK_TESTED = ConnectivityService.EVENT_NETWORK_TESTED; + /** + * Event for NetworkMonitor to inform ConnectivityService that a potential data stall has + * been detected on the network. + * obj = Long the timestamp (in millis) for when the suspected data stall was detected. + * arg1 = {@link DataStallReport#DetectionMethod} indicating the detection method. + * arg2 = NetID. + * data = PersistableBundle of extras passed from NetworkMonitor. + */ + private static final int EVENT_DATA_STALL_SUSPECTED = 4; + private ConnectivityDiagnosticsHandler(Looper looper) { super(looper); } @@ -7576,6 +7602,17 @@ public class ConnectivityService extends IConnectivityManager.Stub handleNetworkTestedWithExtras(reportEvent, extras); break; } + case EVENT_DATA_STALL_SUSPECTED: { + final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); + if (nai == null) break; + + // This is safe because NetworkMonitorCallbacks#notifyDataStallSuspected + // receives a PersistableBundle and converts it to the Bundle in the incoming + // Message. + final PersistableBundle extras = new PersistableBundle(msg.getData()); + handleDataStallSuspected(nai, (long) msg.obj, msg.arg1, extras); + break; + } } } } @@ -7705,6 +7742,22 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private void handleDataStallSuspected( + @NonNull NetworkAgentInfo nai, long timestampMillis, int detectionMethod, + @NonNull PersistableBundle extras) { + final DataStallReport report = + new DataStallReport(nai.network, timestampMillis, detectionMethod, extras); + final List results = + getMatchingPermissionedCallbacks(nai); + for (final IConnectivityDiagnosticsCallback cb : results) { + try { + cb.onDataStallSuspected(report); + } catch (RemoteException ex) { + loge("Error invoking onDataStallSuspected", ex); + } + } + } + private List getMatchingPermissionedCallbacks( @NonNull NetworkAgentInfo nai) { final List results = new ArrayList<>(); diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 50c312cacc..5e80ede318 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -24,6 +24,7 @@ import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport; +import static android.net.ConnectivityDiagnosticsManager.DataStallReport; import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL; @@ -570,6 +571,9 @@ public class ConnectivityServiceTest { | NETWORK_VALIDATION_RESULT_PARTIAL; private static final int VALIDATION_RESULT_INVALID = 0; + private static final long DATA_STALL_TIMESTAMP = 10L; + private static final int DATA_STALL_DETECTION_METHOD = 1; + private INetworkMonitor mNetworkMonitor; private INetworkMonitorCallbacks mNmCallbacks; private int mNmValidationResult = VALIDATION_RESULT_BASE; @@ -577,6 +581,7 @@ public class ConnectivityServiceTest { private int mProbesSucceeded; private String mNmValidationRedirectUrl = null; private PersistableBundle mValidationExtras = PersistableBundle.EMPTY; + private PersistableBundle mDataStallExtras = PersistableBundle.EMPTY; private boolean mNmProvNotificationRequested = false; private final ConditionVariable mNetworkStatusReceived = new ConditionVariable(); @@ -804,6 +809,11 @@ public class ConnectivityServiceTest { public void expectPreventReconnectReceived() { expectPreventReconnectReceived(TIMEOUT_MS); } + + void notifyDataStallSuspected() throws Exception { + mNmCallbacks.notifyDataStallSuspected( + DATA_STALL_TIMESTAMP, DATA_STALL_DETECTION_METHOD, mDataStallExtras); + } } /** @@ -6625,4 +6635,35 @@ public class ConnectivityServiceTest { verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)) .onConnectivityReport(any(ConnectivityReport.class)); } + + @Test + public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception { + final NetworkRequest request = new NetworkRequest.Builder().build(); + when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); + + mServiceContext.setPermission( + android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); + + mService.registerConnectivityDiagnosticsCallback( + mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); + + // Block until all other events are done processing. + HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); + + // Connect the cell agent verify that it notifies TestNetworkCallback that it is available + final TestNetworkCallback callback = new TestNetworkCallback(); + mCm.registerDefaultNetworkCallback(callback); + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.connect(true); + callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + callback.assertNoCallback(); + + // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the + // cellular network agent + mCellNetworkAgent.notifyDataStallSuspected(); + + // Wait for onDataStallSuspected to fire + verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)) + .onDataStallSuspected(any(DataStallReport.class)); + } } From 3eb07d4e7fa6ea19d3d42425144780bdb24fc90f Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Tue, 7 Jan 2020 11:18:54 -0800 Subject: [PATCH 051/229] Fire ConnectivityDiagnostics callbacks on Connectivity reported. When ConnectivityService#reportNetworkTested is called, the platform needs to fire ConnectivityDiagnostics callbacks for registered callbacks that are permissioned for the network being reported on. This adds a new event to ConnectivityDiagnosticsHandler for invoking these callbacks. Bug: 143187964 Test: compiles Test: atest CtsNetTestCases ConnectivityServiceTest Change-Id: Icc6bcf7a2411133d8ecd7477bc351dad9333f24f (cherry picked from commit 3d57b0f4ff5b56780c79df6062dfaf2b9fa5ae3c) --- .../android/server/ConnectivityService.java | 45 +++++++++++++++++ .../server/ConnectivityServiceTest.java | 48 +++++++++++-------- 2 files changed, 72 insertions(+), 21 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index d1a5082ffd..ec3dbe9f85 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -4205,6 +4205,19 @@ public class ConnectivityService extends IConnectivityManager.Stub final int connectivityInfo = encodeBool(hasConnectivity); mHandler.sendMessage( mHandler.obtainMessage(EVENT_REVALIDATE_NETWORK, uid, connectivityInfo, network)); + + final NetworkAgentInfo nai; + if (network == null) { + nai = getDefaultNetwork(); + } else { + nai = getNetworkAgentInfoForNetwork(network); + } + if (nai != null) { + mConnectivityDiagnosticsHandler.sendMessage( + mConnectivityDiagnosticsHandler.obtainMessage( + ConnectivityDiagnosticsHandler.EVENT_NETWORK_CONNECTIVITY_REPORTED, + connectivityInfo, 0, nai)); + } } private void handleReportNetworkConnectivity( @@ -7535,6 +7548,8 @@ public class ConnectivityService extends IConnectivityManager.Stub */ @VisibleForTesting class ConnectivityDiagnosticsHandler extends Handler { + private final String mTag = ConnectivityDiagnosticsHandler.class.getSimpleName(); + /** * Used to handle ConnectivityDiagnosticsCallback registration events from {@link * android.net.ConnectivityDiagnosticsManager}. @@ -7572,6 +7587,16 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private static final int EVENT_DATA_STALL_SUSPECTED = 4; + /** + * Event for ConnectivityDiagnosticsHandler to handle network connectivity being reported to + * the platform. This event will invoke {@link + * IConnectivityDiagnosticsCallback#onNetworkConnectivityReported} for permissioned + * callbacks. + * obj = Network that was reported on + * arg1 = boolint for the quality reported + */ + private static final int EVENT_NETWORK_CONNECTIVITY_REPORTED = 5; + private ConnectivityDiagnosticsHandler(Looper looper) { super(looper); } @@ -7613,6 +7638,13 @@ public class ConnectivityService extends IConnectivityManager.Stub handleDataStallSuspected(nai, (long) msg.obj, msg.arg1, extras); break; } + case EVENT_NETWORK_CONNECTIVITY_REPORTED: { + handleNetworkConnectivityReported((NetworkAgentInfo) msg.obj, toBool(msg.arg1)); + break; + } + default: { + Log.e(mTag, "Unrecognized event in ConnectivityDiagnostics: " + msg.what); + } } } } @@ -7758,6 +7790,19 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private void handleNetworkConnectivityReported( + @NonNull NetworkAgentInfo nai, boolean connectivity) { + final List results = + getMatchingPermissionedCallbacks(nai); + for (final IConnectivityDiagnosticsCallback cb : results) { + try { + cb.onNetworkConnectivityReported(nai.network, connectivity); + } catch (RemoteException ex) { + loge("Error invoking onNetworkConnectivityReported", ex); + } + } + } + private List getMatchingPermissionedCallbacks( @NonNull NetworkAgentInfo nai) { final List results = new ArrayList<>(); diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 5e80ede318..b4f32e75fd 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6609,8 +6609,7 @@ public class ConnectivityServiceTest { mServiceContext.setPermission(perm, PERMISSION_GRANTED); } - @Test - public void testConnectivityDiagnosticsCallbackOnConnectivityReport() throws Exception { + private void setUpConnectivityDiagnosticsCallback() throws Exception { final NetworkRequest request = new NetworkRequest.Builder().build(); when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); @@ -6630,6 +6629,11 @@ public class ConnectivityServiceTest { mCellNetworkAgent.connect(true); callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); callback.assertNoCallback(); + } + + @Test + public void testConnectivityDiagnosticsCallbackOnConnectivityReport() throws Exception { + setUpConnectivityDiagnosticsCallback(); // Wait for onConnectivityReport to fire verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)) @@ -6638,25 +6642,7 @@ public class ConnectivityServiceTest { @Test public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() throws Exception { - final NetworkRequest request = new NetworkRequest.Builder().build(); - when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); - - mServiceContext.setPermission( - android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); - - mService.registerConnectivityDiagnosticsCallback( - mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); - - // Block until all other events are done processing. - HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - - // Connect the cell agent verify that it notifies TestNetworkCallback that it is available - final TestNetworkCallback callback = new TestNetworkCallback(); - mCm.registerDefaultNetworkCallback(callback); - mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); - mCellNetworkAgent.connect(true); - callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); - callback.assertNoCallback(); + setUpConnectivityDiagnosticsCallback(); // Trigger notifyDataStallSuspected() on the INetworkMonitorCallbacks instance in the // cellular network agent @@ -6666,4 +6652,24 @@ public class ConnectivityServiceTest { verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)) .onDataStallSuspected(any(DataStallReport.class)); } + + @Test + public void testConnectivityDiagnosticsCallbackOnConnectivityReported() throws Exception { + setUpConnectivityDiagnosticsCallback(); + + final Network n = mCellNetworkAgent.getNetwork(); + final boolean hasConnectivity = true; + mService.reportNetworkConnectivity(n, hasConnectivity); + + // Wait for onNetworkConnectivityReported to fire + verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)) + .onNetworkConnectivityReported(eq(n), eq(hasConnectivity)); + + final boolean noConnectivity = false; + mService.reportNetworkConnectivity(n, noConnectivity); + + // Wait for onNetworkConnectivityReported to fire + verify(mConnectivityDiagnosticsCallback, timeout(TIMEOUT_MS)) + .onNetworkConnectivityReported(eq(n), eq(noConnectivity)); + } } From a098ec41718d7bdcd86ecb2de5fecf9c773e6e16 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Thu, 16 Jan 2020 12:17:17 -0800 Subject: [PATCH 052/229] NetworkRequest: Embed requestor uid & packageName Add the requestorUid & requestorPackageName fields to NetworkCapabilities. This is populated by CS when a new network request is received. These 2 requestor fields are also optionally used for network matching. All of the regular app initiated requests will have the requestor uid and package name set by connectivity service. Network agents can optionally set the requestorUid and requestorPackageName to restrict the network created only to the app that requested the network. This will help removing the necessity for the various specifiers to embed the uid & package name info in the specifier for network matching. Note: NetworkSpecifier.assertValidFromUid() is deprecated & removed in favor of setting the uid/package name on the agent to restrict the network to a certain app (useful for wifi peer to peer API & wifi aware). Bug: 144102365 Test: Verified that wifi network request related CTS verifier tests pass. Test: Device boots up and connects to wifi networks Change-Id: I207c446108afdac7ee2c25e6bbcbc37c4e3f6529 --- .../java/android/net/ConnectivityManager.java | 14 +- .../android/net/IConnectivityManager.aidl | 9 +- .../java/android/net/NetworkCapabilities.java | 161 +++++++++++++++++- core/java/android/net/NetworkRequest.java | 26 +++ .../android/server/ConnectivityService.java | 54 +++--- .../android/net/NetworkCapabilitiesTest.java | 16 +- .../android/net/ConnectivityManagerTest.java | 12 +- .../server/ConnectivityServiceTest.java | 31 +--- 8 files changed, 257 insertions(+), 66 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index fa12c08f22..f644f148a5 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3750,6 +3750,7 @@ public class ConnectivityManager { checkCallbackNotNull(callback); Preconditions.checkArgument(action == REQUEST || need != null, "null NetworkCapabilities"); final NetworkRequest request; + final String callingPackageName = mContext.getOpPackageName(); try { synchronized(sCallbacks) { if (callback.networkRequest != null @@ -3761,10 +3762,11 @@ public class ConnectivityManager { Messenger messenger = new Messenger(handler); Binder binder = new Binder(); if (action == LISTEN) { - request = mService.listenForNetwork(need, messenger, binder); + request = mService.listenForNetwork( + need, messenger, binder, callingPackageName); } else { request = mService.requestNetwork( - need, messenger, timeoutMs, binder, legacyType); + need, messenger, timeoutMs, binder, legacyType, callingPackageName); } if (request != null) { sCallbacks.put(request, callback); @@ -4037,8 +4039,10 @@ public class ConnectivityManager { @NonNull PendingIntent operation) { printStackTrace(); checkPendingIntentNotNull(operation); + final String callingPackageName = mContext.getOpPackageName(); try { - mService.pendingRequestForNetwork(request.networkCapabilities, operation); + mService.pendingRequestForNetwork( + request.networkCapabilities, operation, callingPackageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { @@ -4150,8 +4154,10 @@ public class ConnectivityManager { @NonNull PendingIntent operation) { printStackTrace(); checkPendingIntentNotNull(operation); + final String callingPackageName = mContext.getOpPackageName(); try { - mService.pendingListenForNetwork(request.networkCapabilities, operation); + mService.pendingListenForNetwork( + request.networkCapabilities, operation, callingPackageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } catch (ServiceSpecificException e) { diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 0fae607ca6..1c7628f6ad 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -167,18 +167,19 @@ interface IConnectivityManager in int factorySerialNumber); NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, - in Messenger messenger, int timeoutSec, in IBinder binder, int legacy); + in Messenger messenger, int timeoutSec, in IBinder binder, int legacy, + String callingPackageName); NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities, - in PendingIntent operation); + in PendingIntent operation, String callingPackageName); void releasePendingNetworkRequest(in PendingIntent operation); NetworkRequest listenForNetwork(in NetworkCapabilities networkCapabilities, - in Messenger messenger, in IBinder binder); + in Messenger messenger, in IBinder binder, String callingPackageName); void pendingListenForNetwork(in NetworkCapabilities networkCapabilities, - in PendingIntent operation); + in PendingIntent operation, String callingPackageName); void releaseNetworkRequest(in NetworkRequest networkRequest); diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index cf5f2259af..f8b51dd990 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -27,6 +27,7 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.os.Process; +import android.text.TextUtils; import android.util.ArraySet; import android.util.proto.ProtoOutputStream; @@ -63,6 +64,16 @@ public final class NetworkCapabilities implements Parcelable { // Set to true when private DNS is broken. private boolean mPrivateDnsBroken; + /** + * Uid of the app making the request. + */ + private int mRequestorUid; + + /** + * Package name of the app making the request. + */ + private String mRequestorPackageName; + public NetworkCapabilities() { clearAll(); mNetworkCapabilities = DEFAULT_CAPABILITIES; @@ -89,6 +100,8 @@ public final class NetworkCapabilities implements Parcelable { mOwnerUid = Process.INVALID_UID; mSSID = null; mPrivateDnsBroken = false; + mRequestorUid = Process.INVALID_UID; + mRequestorPackageName = null; } /** @@ -109,6 +122,8 @@ public final class NetworkCapabilities implements Parcelable { mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; mSSID = nc.mSSID; mPrivateDnsBroken = nc.mPrivateDnsBroken; + mRequestorUid = nc.mRequestorUid; + mRequestorPackageName = nc.mRequestorPackageName; } /** @@ -810,7 +825,7 @@ public final class NetworkCapabilities implements Parcelable { } /** - * UID of the app that owns this network, or INVALID_UID if none/unknown. + * UID of the app that owns this network, or Process#INVALID_UID if none/unknown. * *

This field keeps track of the UID of the app that created this network and is in charge of * its lifecycle. This could be the UID of apps such as the Wifi network suggestor, the running @@ -821,8 +836,9 @@ public final class NetworkCapabilities implements Parcelable { /** * Set the UID of the owner app. */ - public void setOwnerUid(final int uid) { + public @NonNull NetworkCapabilities setOwnerUid(final int uid) { mOwnerUid = uid; + return this; } /** @@ -865,9 +881,11 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @SystemApi - public void setAdministratorUids(@NonNull final List administratorUids) { + public @NonNull NetworkCapabilities setAdministratorUids( + @NonNull final List administratorUids) { mAdministratorUids.clear(); mAdministratorUids.addAll(administratorUids); + return this; } /** @@ -1385,6 +1403,7 @@ public final class NetworkCapabilities implements Parcelable { combineSignalStrength(nc); combineUids(nc); combineSSIDs(nc); + combineRequestor(nc); } /** @@ -1404,7 +1423,8 @@ public final class NetworkCapabilities implements Parcelable { && satisfiedBySpecifier(nc) && (onlyImmutable || satisfiedBySignalStrength(nc)) && (onlyImmutable || satisfiedByUids(nc)) - && (onlyImmutable || satisfiedBySSID(nc))); + && (onlyImmutable || satisfiedBySSID(nc))) + && (onlyImmutable || satisfiedByRequestor(nc)); } /** @@ -1488,7 +1508,7 @@ public final class NetworkCapabilities implements Parcelable { public boolean equals(@Nullable Object obj) { if (obj == null || (obj instanceof NetworkCapabilities == false)) return false; NetworkCapabilities that = (NetworkCapabilities) obj; - return (equalsNetCapabilities(that) + return equalsNetCapabilities(that) && equalsTransportTypes(that) && equalsLinkBandwidths(that) && equalsSignalStrength(that) @@ -1496,7 +1516,8 @@ public final class NetworkCapabilities implements Parcelable { && equalsTransportInfo(that) && equalsUids(that) && equalsSSID(that) - && equalsPrivateDnsBroken(that)); + && equalsPrivateDnsBroken(that) + && equalsRequestor(that); } @Override @@ -1514,7 +1535,9 @@ public final class NetworkCapabilities implements Parcelable { + Objects.hashCode(mUids) * 31 + Objects.hashCode(mSSID) * 37 + Objects.hashCode(mTransportInfo) * 41 - + Objects.hashCode(mPrivateDnsBroken) * 43; + + Objects.hashCode(mPrivateDnsBroken) * 43 + + Objects.hashCode(mRequestorUid) * 47 + + Objects.hashCode(mRequestorPackageName) * 53; } @Override @@ -1537,6 +1560,8 @@ public final class NetworkCapabilities implements Parcelable { dest.writeBoolean(mPrivateDnsBroken); dest.writeList(mAdministratorUids); dest.writeInt(mOwnerUid); + dest.writeInt(mRequestorUid); + dest.writeString(mRequestorPackageName); } public static final @android.annotation.NonNull Creator CREATOR = @@ -1559,6 +1584,8 @@ public final class NetworkCapabilities implements Parcelable { netCap.mPrivateDnsBroken = in.readBoolean(); netCap.setAdministratorUids(in.readArrayList(null)); netCap.mOwnerUid = in.readInt(); + netCap.mRequestorUid = in.readInt(); + netCap.mRequestorPackageName = in.readString(); return netCap; } @Override @@ -1624,6 +1651,9 @@ public final class NetworkCapabilities implements Parcelable { sb.append(" Private DNS is broken"); } + sb.append(" RequestorUid: ").append(mRequestorUid); + sb.append(" RequestorPackageName: ").append(mRequestorPackageName); + sb.append("]"); return sb.toString(); } @@ -1632,6 +1662,7 @@ public final class NetworkCapabilities implements Parcelable { private interface NameOf { String nameOf(int value); } + /** * @hide */ @@ -1799,4 +1830,120 @@ public final class NetworkCapabilities implements Parcelable { private boolean equalsPrivateDnsBroken(NetworkCapabilities nc) { return mPrivateDnsBroken == nc.mPrivateDnsBroken; } + + /** + * Set the uid of the app making the request. + * + * Note: This works only for {@link NetworkAgent} instances. Any capabilities passed in + * via the public {@link ConnectivityManager} API's will have this field overwritten. + * + * @param uid UID of the app. + * @hide + */ + @SystemApi + public @NonNull NetworkCapabilities setRequestorUid(int uid) { + mRequestorUid = uid; + return this; + } + + /** + * @return the uid of the app making the request. + * + * Note: This could return {@link Process#INVALID_UID} if the {@link NetworkRequest} + * object was not obtained from {@link ConnectivityManager}. + * @hide + */ + public int getRequestorUid() { + return mRequestorUid; + } + + /** + * Set the package name of the app making the request. + * + * Note: This works only for {@link NetworkAgent} instances. Any capabilities passed in + * via the public {@link ConnectivityManager} API's will have this field overwritten. + * + * @param packageName package name of the app. + * @hide + */ + @SystemApi + public @NonNull NetworkCapabilities setRequestorPackageName(@NonNull String packageName) { + mRequestorPackageName = packageName; + return this; + } + + /** + * @return the package name of the app making the request. + * + * Note: This could return {@code null} if the {@link NetworkRequest} object was not obtained + * from {@link ConnectivityManager}. + * @hide + */ + @Nullable + public String getRequestorPackageName() { + return mRequestorPackageName; + } + + /** + * Set the uid and package name of the app making the request. + * + * Note: This is intended to be only invoked from within connectivitiy service. + * + * @param uid UID of the app. + * @param packageName package name of the app. + * @hide + */ + public @NonNull NetworkCapabilities setRequestorUidAndPackageName( + int uid, @NonNull String packageName) { + return setRequestorUid(uid).setRequestorPackageName(packageName); + } + + /** + * Test whether the passed NetworkCapabilities satisfies the requestor restrictions of this + * capabilities. + * + * This method is called on the NetworkCapabilities embedded in a request with the + * capabilities of an available network. If the available network, sets a specific + * requestor (by uid and optionally package name), then this will only match a request from the + * same app. If either of the capabilities have an unset uid or package name, then it matches + * everything. + *

+ * nc is assumed nonnull. Else, NPE. + */ + private boolean satisfiedByRequestor(NetworkCapabilities nc) { + // No uid set, matches everything. + if (mRequestorUid == Process.INVALID_UID || nc.mRequestorUid == Process.INVALID_UID) { + return true; + } + // uids don't match. + if (mRequestorUid != nc.mRequestorUid) return false; + // No package names set, matches everything + if (null == nc.mRequestorPackageName || null == mRequestorPackageName) return true; + // check for package name match. + return TextUtils.equals(mRequestorPackageName, nc.mRequestorPackageName); + } + + /** + * Combine requestor info of the capabilities. + *

+ * This is only legal if either the requestor info of this object is reset, or both info are + * equal. + * nc is assumed nonnull. + */ + private void combineRequestor(@NonNull NetworkCapabilities nc) { + if (mRequestorUid != Process.INVALID_UID && mRequestorUid != nc.mOwnerUid) { + throw new IllegalStateException("Can't combine two uids"); + } + if (mRequestorPackageName != null + && !mRequestorPackageName.equals(nc.mRequestorPackageName)) { + throw new IllegalStateException("Can't combine two package names"); + } + setRequestorUid(nc.mRequestorUid); + setRequestorPackageName(nc.mRequestorPackageName); + } + + private boolean equalsRequestor(NetworkCapabilities nc) { + return mRequestorUid == nc.mRequestorUid + && TextUtils.equals(mRequestorPackageName, nc.mRequestorPackageName); + } } diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index 301d203406..964f13f39e 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -380,6 +380,7 @@ public class NetworkRequest implements Parcelable { dest.writeInt(requestId); dest.writeString(type.name()); } + public static final @android.annotation.NonNull Creator CREATOR = new Creator() { public NetworkRequest createFromParcel(Parcel in) { @@ -494,6 +495,31 @@ public class NetworkRequest implements Parcelable { return networkCapabilities.getNetworkSpecifier(); } + /** + * @return the uid of the app making the request. + * + * Note: This could return {@link Process#INVALID_UID} if the {@link NetworkRequest} object was + * not obtained from {@link ConnectivityManager}. + * @hide + */ + @SystemApi + public int getRequestorUid() { + return networkCapabilities.getRequestorUid(); + } + + /** + * @return the package name of the app making the request. + * + * Note: This could return {@code null} if the {@link NetworkRequest} object was not obtained + * from {@link ConnectivityManager}. + * @hide + */ + @SystemApi + @Nullable + public String getRequestorPackageName() { + return networkCapabilities.getRequestorPackageName(); + } + public String toString() { return "NetworkRequest [ " + type + " id=" + requestId + (legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") + diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index d0cd7ffee1..a0e6832ee1 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -601,7 +601,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private Set mWolSupportedInterfaces; - private TelephonyManager mTelephonyManager; + private final TelephonyManager mTelephonyManager; private final AppOpsManager mAppOpsManager; private final LocationPermissionChecker mLocationPermissionChecker; @@ -960,6 +960,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mDeps = Objects.requireNonNull(deps, "missing Dependencies"); mSystemProperties = mDeps.getSystemProperties(); mNetIdManager = mDeps.makeNetIdManager(); + mContext = Objects.requireNonNull(context, "missing Context"); mMetricsLog = logger; mDefaultRequest = createDefaultInternetRequestForTransport(-1, NetworkRequest.Type.REQUEST); @@ -988,7 +989,6 @@ public class ConnectivityService extends IConnectivityManager.Stub mLingerDelayMs = mSystemProperties.getInt(LINGER_DELAY_PROPERTY, DEFAULT_LINGER_DELAY_MS); - mContext = Objects.requireNonNull(context, "missing Context"); mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService"); mStatsService = Objects.requireNonNull(statsService, "missing INetworkStatsService"); mPolicyManager = Objects.requireNonNull(policyManager, "missing INetworkPolicyManager"); @@ -1168,6 +1168,7 @@ public class ConnectivityService extends IConnectivityManager.Stub int transportType, NetworkRequest.Type type) { final NetworkCapabilities netCap = new NetworkCapabilities(); netCap.addCapability(NET_CAPABILITY_INTERNET); + netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName()); if (transportType > -1) { netCap.addTransportType(transportType); } @@ -1698,10 +1699,12 @@ public class ConnectivityService extends IConnectivityManager.Stub return newLp; } - private void restrictRequestUidsForCaller(NetworkCapabilities nc) { + private void restrictRequestUidsForCallerAndSetRequestorInfo(NetworkCapabilities nc, + int callerUid, String callerPackageName) { if (!checkSettingsPermission()) { - nc.setSingleUid(Binder.getCallingUid()); + nc.setSingleUid(callerUid); } + nc.setRequestorUidAndPackageName(callerUid, callerPackageName); nc.setAdministratorUids(Collections.EMPTY_LIST); // Clear owner UID; this can never come from an app. @@ -5275,7 +5278,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // This checks that the passed capabilities either do not request a // specific SSID/SignalStrength, or the calling app has permission to do so. private void ensureSufficientPermissionsForRequest(NetworkCapabilities nc, - int callerPid, int callerUid) { + int callerPid, int callerUid, String callerPackageName) { if (null != nc.getSSID() && !checkSettingsPermission(callerPid, callerUid)) { throw new SecurityException("Insufficient permissions to request a specific SSID"); } @@ -5285,6 +5288,7 @@ public class ConnectivityService extends IConnectivityManager.Stub throw new SecurityException( "Insufficient permissions to request a specific signal strength"); } + mAppOpsManager.checkPackage(callerUid, callerPackageName); } private ArrayList getSignalStrengthThresholds(NetworkAgentInfo nai) { @@ -5331,7 +5335,6 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(ns); - ns.assertValidFromUid(Binder.getCallingUid()); } private void ensureValid(NetworkCapabilities nc) { @@ -5343,7 +5346,9 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities, - Messenger messenger, int timeoutMs, IBinder binder, int legacyType) { + Messenger messenger, int timeoutMs, IBinder binder, int legacyType, + @NonNull String callingPackageName) { + final int callingUid = Binder.getCallingUid(); final NetworkRequest.Type type = (networkCapabilities == null) ? NetworkRequest.Type.TRACK_DEFAULT : NetworkRequest.Type.REQUEST; @@ -5351,7 +5356,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // the default network request. This allows callers to keep track of // the system default network. if (type == NetworkRequest.Type.TRACK_DEFAULT) { - networkCapabilities = createDefaultNetworkCapabilitiesForUid(Binder.getCallingUid()); + networkCapabilities = createDefaultNetworkCapabilitiesForUid(callingUid); enforceAccessPermission(); } else { networkCapabilities = new NetworkCapabilities(networkCapabilities); @@ -5363,13 +5368,14 @@ public class ConnectivityService extends IConnectivityManager.Stub } ensureRequestableCapabilities(networkCapabilities); ensureSufficientPermissionsForRequest(networkCapabilities, - Binder.getCallingPid(), Binder.getCallingUid()); + 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. // 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. - restrictRequestUidsForCaller(networkCapabilities); + restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities, + callingUid, callingPackageName); if (timeoutMs < 0) { throw new IllegalArgumentException("Bad timeout specified"); @@ -5444,16 +5450,18 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities, - PendingIntent operation) { + PendingIntent operation, @NonNull String callingPackageName) { Objects.requireNonNull(operation, "PendingIntent cannot be null."); + final int callingUid = Binder.getCallingUid(); networkCapabilities = new NetworkCapabilities(networkCapabilities); enforceNetworkRequestPermissions(networkCapabilities); enforceMeteredApnPolicy(networkCapabilities); ensureRequestableCapabilities(networkCapabilities); ensureSufficientPermissionsForRequest(networkCapabilities, - Binder.getCallingPid(), Binder.getCallingUid()); + Binder.getCallingPid(), callingUid, callingPackageName); ensureValidNetworkSpecifier(networkCapabilities); - restrictRequestUidsForCaller(networkCapabilities); + restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities, + callingUid, callingPackageName); NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.REQUEST); @@ -5501,15 +5509,16 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities, - Messenger messenger, IBinder binder) { + Messenger messenger, IBinder binder, @NonNull String callingPackageName) { + final int callingUid = Binder.getCallingUid(); if (!hasWifiNetworkListenPermission(networkCapabilities)) { enforceAccessPermission(); } NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); ensureSufficientPermissionsForRequest(networkCapabilities, - Binder.getCallingPid(), Binder.getCallingUid()); - restrictRequestUidsForCaller(nc); + Binder.getCallingPid(), callingUid, callingPackageName); + restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName); // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get // onLost and onAvailable callbacks when networks move in and out of the background. @@ -5529,17 +5538,17 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void pendingListenForNetwork(NetworkCapabilities networkCapabilities, - PendingIntent operation) { + PendingIntent operation, @NonNull String callingPackageName) { Objects.requireNonNull(operation, "PendingIntent cannot be null."); + final int callingUid = Binder.getCallingUid(); if (!hasWifiNetworkListenPermission(networkCapabilities)) { enforceAccessPermission(); } ensureValid(networkCapabilities); ensureSufficientPermissionsForRequest(networkCapabilities, - Binder.getCallingPid(), Binder.getCallingUid()); - + Binder.getCallingPid(), callingUid, callingPackageName); final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); - restrictRequestUidsForCaller(nc); + restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName); NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(), NetworkRequest.Type.LISTEN); @@ -7757,12 +7766,13 @@ public class ConnectivityService extends IConnectivityManager.Stub throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated." + " Please use NetworkCapabilities instead."); } - mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName); + final int callingUid = Binder.getCallingUid(); + mAppOpsManager.checkPackage(callingUid, callingPackageName); // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid // and administrator uids to be safe. final NetworkCapabilities nc = new NetworkCapabilities(request.networkCapabilities); - restrictRequestUidsForCaller(nc); + restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName); final NetworkRequest requestWithId = new NetworkRequest( diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index 3e4f3d8188..efea91ab91 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -272,9 +272,23 @@ public class NetworkCapabilitiesTest { netCap.setOwnerUid(123); assertParcelingIsLossless(netCap); netCap.setSSID(TEST_SSID); - assertParcelSane(netCap, 13); + assertParcelSane(netCap, 15); } + @Test + public void testParcelNetworkCapabilitiesWithRequestorUidAndPackageName() { + final NetworkCapabilities netCap = new NetworkCapabilities() + .addCapability(NET_CAPABILITY_INTERNET) + .setRequestorUid(9304) + .setRequestorPackageName("com.android.test") + .addCapability(NET_CAPABILITY_EIMS) + .addCapability(NET_CAPABILITY_NOT_METERED); + assertParcelingIsLossless(netCap); + netCap.setSSID(TEST_SSID); + assertParcelSane(netCap, 15); + } + + @Test public void testOemPaid() { NetworkCapabilities nc = new NetworkCapabilities(); diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java index 7ede14428a..d6bf334ee5 100644 --- a/tests/net/java/android/net/ConnectivityManagerTest.java +++ b/tests/net/java/android/net/ConnectivityManagerTest.java @@ -212,7 +212,8 @@ public class ConnectivityManagerTest { ArgumentCaptor captor = ArgumentCaptor.forClass(Messenger.class); // register callback - when(mService.requestNetwork(any(), captor.capture(), anyInt(), any(), anyInt())) + when(mService.requestNetwork( + any(), captor.capture(), anyInt(), any(), anyInt(), any())) .thenReturn(request); manager.requestNetwork(request, callback, handler); @@ -240,7 +241,8 @@ public class ConnectivityManagerTest { ArgumentCaptor captor = ArgumentCaptor.forClass(Messenger.class); // register callback - when(mService.requestNetwork(any(), captor.capture(), anyInt(), any(), anyInt())) + when(mService.requestNetwork( + any(), captor.capture(), anyInt(), any(), anyInt(), any())) .thenReturn(req1); manager.requestNetwork(req1, callback, handler); @@ -258,7 +260,8 @@ public class ConnectivityManagerTest { verify(callback, timeout(100).times(0)).onLosing(any(), anyInt()); // callback can be registered again - when(mService.requestNetwork(any(), captor.capture(), anyInt(), any(), anyInt())) + when(mService.requestNetwork( + any(), captor.capture(), anyInt(), any(), anyInt(), any())) .thenReturn(req2); manager.requestNetwork(req2, callback, handler); @@ -282,7 +285,8 @@ public class ConnectivityManagerTest { info.targetSdkVersion = VERSION_CODES.N_MR1 + 1; when(mCtx.getApplicationInfo()).thenReturn(info); - when(mService.requestNetwork(any(), any(), anyInt(), any(), anyInt())).thenReturn(request); + when(mService.requestNetwork(any(), any(), anyInt(), any(), anyInt(), any())) + .thenReturn(request); Handler handler = new Handler(Looper.getMainLooper()); manager.requestNetwork(request, callback, handler); diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 50c312cacc..1b059a383e 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -106,6 +106,7 @@ import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -304,6 +305,7 @@ public class ConnectivityServiceTest { private static final String MOBILE_IFNAME = "test_rmnet_data0"; private static final String WIFI_IFNAME = "test_wlan0"; private static final String WIFI_WOL_IFNAME = "test_wlan_wol"; + private static final String TEST_PACKAGE_NAME = "com.android.test.package"; private static final String[] EMPTY_STRING_ARRAY = new String[0]; private MockContext mServiceContext; @@ -649,7 +651,7 @@ public class ConnectivityServiceTest { if (mNmValidationRedirectUrl != null) { mNmCallbacks.showProvisioningNotification( - "test_provisioning_notif_action", "com.android.test.package"); + "test_provisioning_notif_action", TEST_PACKAGE_NAME); mNmProvNotificationRequested = true; } } @@ -2962,7 +2964,7 @@ public class ConnectivityServiceTest { networkCapabilities.addTransportType(TRANSPORT_WIFI) .setNetworkSpecifier(new MatchAllNetworkSpecifier()); mService.requestNetwork(networkCapabilities, null, 0, null, - ConnectivityManager.TYPE_WIFI); + ConnectivityManager.TYPE_WIFI, TEST_PACKAGE_NAME); }); class NonParcelableSpecifier extends NetworkSpecifier { @@ -3001,31 +3003,12 @@ public class ConnectivityServiceTest { } @Test - public void testNetworkSpecifierUidSpoofSecurityException() throws Exception { - class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable { - @Override - public boolean satisfiedBy(NetworkSpecifier other) { - return true; - } - - @Override - public void assertValidFromUid(int requestorUid) { - throw new SecurityException("failure"); - } - - @Override - public int describeContents() { return 0; } - @Override - public void writeToParcel(Parcel dest, int flags) {} - } - + public void testNetworkRequestUidSpoofSecurityException() throws Exception { mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); - - UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier(); - NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier( - networkSpecifier).build(); + NetworkRequest networkRequest = newWifiRequestBuilder().build(); TestNetworkCallback networkCallback = new TestNetworkCallback(); + doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString()); assertThrows(SecurityException.class, () -> { mCm.requestNetwork(networkRequest, networkCallback); }); From 273a3e1c54cc3d92e9ca0adc90e7bfc7fcd18e6f Mon Sep 17 00:00:00 2001 From: markchien Date: Thu, 6 Feb 2020 19:23:26 +0800 Subject: [PATCH 053/229] Use framework-tethering-stub instead of framework-tethering The non-updatable part of the platform now is built with framework-tethering-stub, which is a stub library of framework-tethering. Bug: 147200698 Test: m Change-Id: I97ef83f7f9b4c1376f373713036f5256318f1050 --- core/java/android/net/ConnectivityManager.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index fa12c08f22..a577b20e20 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2423,14 +2423,14 @@ public class ConnectivityManager { /** * Get the set of tethered dhcp ranges. * - * @return an array of 0 or more {@code String} of tethered dhcp ranges. - * @deprecated This API just return the default value which is not used in DhcpServer. + * @deprecated This method is not supported. + * TODO: remove this function when all of clients are removed. * {@hide} */ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) @Deprecated public String[] getTetheredDhcpRanges() { - return getTetheringManager().getTetheredDhcpRanges(); + throw new UnsupportedOperationException("getTetheredDhcpRanges is not supported"); } /** From ca2105f597b758135e7aff3454a408649c13eb26 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Wed, 12 Feb 2020 18:08:16 +0800 Subject: [PATCH 054/229] Add permission check for CaptivePortal#reevaluateNetwork CaptivePortal#reevaluateNetwork is added as a system API which requires a proper permission check. Bug: 148379628 Test: Manually check with captive portal Test: atest FrameworksNetTests Test: make test-api-stubs-docs-update-current-api \ system-api-stubs-docs-update-current-api Change-Id: I559d42089aeb09801d14c251c5165fca793c3cb3 --- core/java/android/net/CaptivePortal.java | 2 ++ services/core/java/com/android/server/ConnectivityService.java | 1 + 2 files changed, 3 insertions(+) diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java index fb35b4bde3..448fe5a051 100644 --- a/core/java/android/net/CaptivePortal.java +++ b/core/java/android/net/CaptivePortal.java @@ -16,6 +16,7 @@ package android.net; import android.annotation.NonNull; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; import android.os.IBinder; @@ -153,6 +154,7 @@ public class CaptivePortal implements Parcelable { */ @SystemApi @TestApi + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void reevaluateNetwork() { try { ICaptivePortal.Stub.asInterface(mBinder).appRequest(APP_REQUEST_REEVALUATION_REQUIRED); diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 687fb7d720..45af631e2d 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3754,6 +3754,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (nm == null) return; if (request == CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED) { + checkNetworkStackPermission(); nm.forceReevaluation(Binder.getCallingUid()); } } From 6a82d893aa2342a4234df6d5a1af3493df2f882e Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 12 Nov 2019 22:31:51 -0800 Subject: [PATCH 055/229] Implement Ikev2VpnRunner This change adds the implementation for IKEv2/IPsec VPNs. Bug: 144246767 Test: Manually tested Change-Id: I5ccec756cec49ccf57ccc4d5ad800eeb5d595a76 --- tests/net/java/com/android/server/connectivity/VpnTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 155c61f3f8..eb78529e87 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -148,6 +148,7 @@ public class VpnTest { @Mock private AppOpsManager mAppOps; @Mock private NotificationManager mNotificationManager; @Mock private Vpn.SystemServices mSystemServices; + @Mock private Vpn.Ikev2SessionCreator mIkev2SessionCreator; @Mock private ConnectivityManager mConnectivityManager; @Mock private KeyStore mKeyStore; private final VpnProfile mVpnProfile = new VpnProfile("key"); @@ -867,7 +868,8 @@ public class VpnTest { * Mock some methods of vpn object. */ private Vpn createVpn(@UserIdInt int userId) { - return new Vpn(Looper.myLooper(), mContext, mNetService, userId, mSystemServices); + return new Vpn(Looper.myLooper(), mContext, mNetService, + userId, mSystemServices, mIkev2SessionCreator); } private static void assertBlocked(Vpn vpn, int... uids) { From a19115d4828d45336fae5b9e407fe55f16686696 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 13 Feb 2020 16:39:05 +0900 Subject: [PATCH 056/229] [NS D01] Remove candidates that don't satisfy the request. This is exactly equivalent to the previous version (though a bit more expensive) but is useful for followup changes. See [NS D03] to see a sample of how this will be used. Bug: 113554781 Test: FrameworksNetTests Change-Id: I39f3c248bd2f23f7b22bd89d2e1e031653fe9ddb --- .../com/android/server/connectivity/NetworkRanker.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/services/core/java/com/android/server/connectivity/NetworkRanker.java index d0aabf95d5..1ae7dc5c36 100644 --- a/services/core/java/com/android/server/connectivity/NetworkRanker.java +++ b/services/core/java/com/android/server/connectivity/NetworkRanker.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.net.NetworkRequest; +import java.util.ArrayList; import java.util.Collection; /** @@ -31,15 +32,15 @@ public class NetworkRanker { /** * Find the best network satisfying this request among the list of passed networks. */ - // Almost equivalent to Collections.max(nais), but allows returning null if no network - // satisfies the request. @Nullable public NetworkAgentInfo getBestNetwork(@NonNull final NetworkRequest request, @NonNull final Collection nais) { + final ArrayList candidates = new ArrayList<>(nais); + candidates.removeIf(nai -> !nai.satisfies(request)); + NetworkAgentInfo bestNetwork = null; int bestScore = Integer.MIN_VALUE; - for (final NetworkAgentInfo nai : nais) { - if (!nai.satisfies(request)) continue; + for (final NetworkAgentInfo nai : candidates) { if (nai.getCurrentScore() > bestScore) { bestNetwork = nai; bestScore = nai.getCurrentScore(); From 7a56387e2c4d7e8c63733f2a18fb138e56668697 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 14 Feb 2020 20:35:25 +0900 Subject: [PATCH 057/229] [NS D02] Mix in the ignore on wifi policy. Ultimately ConnectivityService and its satellites should mix in some measurements to NetworkScore, but in the immediate future they'll just use this to mix in at the new format the policy it used to managed in an ad-hoc way. As a first mix-in, this adds mixing in the IGNORE_ON_WIFI policy, which so far used to be handled in Connectivity as the avoidBadWifi bit. Ultimately this should move to Telephony. Bug: 113554781 Test: ConnectivityServiceTest Change-Id: I4869d5eb9ea74679e57c087005ed3d9b8119fed2 --- core/java/android/net/NetworkScore.java | 21 +++++++--- .../android/server/ConnectivityService.java | 41 ++++++++++++++++++- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java index ae17378cfc..d2e59eb893 100644 --- a/core/java/android/net/NetworkScore.java +++ b/core/java/android/net/NetworkScore.java @@ -21,7 +21,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; -import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -87,7 +86,7 @@ public final class NetworkScore implements Parcelable { /** toString */ public String toString() { return "latency = " + latencyMs + " downlinkBandwidth = " + downlinkBandwidthKBps - + "uplinkBandwidth = " + uplinkBandwidthKBps; + + " uplinkBandwidth = " + uplinkBandwidthKBps; } @NonNull @@ -354,17 +353,27 @@ public final class NetworkScore implements Parcelable { private Metrics mLinkLayerMetrics = new Metrics(Metrics.LATENCY_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN); @NonNull - private Metrics mEndToMetrics = new Metrics(Metrics.LATENCY_UNKNOWN, + private Metrics mEndToEndMetrics = new Metrics(Metrics.LATENCY_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN); private int mSignalStrength = UNKNOWN_SIGNAL_STRENGTH; private int mRange = RANGE_UNKNOWN; private boolean mExiting = false; private int mLegacyScore = 0; - @NonNull private Bundle mExtensions = new Bundle(); /** Create a new builder. */ public Builder() { } + /** @hide */ + public Builder(@NonNull final NetworkScore source) { + mPolicy = source.mPolicy; + mLinkLayerMetrics = source.mLinkLayerMetrics; + mEndToEndMetrics = source.mEndToEndMetrics; + mSignalStrength = source.mSignalStrength; + mRange = source.mRange; + mExiting = source.mExiting; + mLegacyScore = source.mLegacyScore; + } + /** Add a policy flag. */ @NonNull public Builder addPolicy(@Policy final int policy) { mPolicy |= policy; @@ -385,7 +394,7 @@ public final class NetworkScore implements Parcelable { /** Set the end-to-end metrics. */ @NonNull public Builder setEndToEndMetrics(@NonNull final Metrics endToEndMetrics) { - mEndToMetrics = endToEndMetrics; + mEndToEndMetrics = endToEndMetrics; return this; } @@ -417,7 +426,7 @@ public final class NetworkScore implements Parcelable { /** Build the NetworkScore object represented by this builder. */ @NonNull public NetworkScore build() { - return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToMetrics, + return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToEndMetrics, mSignalStrength, mRange, mExiting, mLegacyScore); } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index c47cde34a9..f121cab85c 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3787,8 +3787,9 @@ public class ConnectivityService extends IConnectivityManager.Stub return avoidBadWifi(); } - private void rematchForAvoidBadWifiUpdate() { + ensureRunningOnConnectivityServiceThread(); + mixInAllNetworkScores(); rematchAllNetworksAndRequests(); for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) { if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { @@ -6992,9 +6993,45 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + /** + * Re-mixin all network scores. + * This is called when some global setting like avoidBadWifi has changed. + * TODO : remove this when all usages have been removed. + */ + private void mixInAllNetworkScores() { + ensureRunningOnConnectivityServiceThread(); + for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) { + nai.setNetworkScore(mixInNetworkScore(nai, nai.getNetworkScore())); + } + } + + /** + * Mix in the Connectivity-managed parts of the NetworkScore. + * @param nai The NAI this score applies to. + * @param sourceScore the score sent by the network agent, or the previous score of this NAI. + * @return A new score with the Connectivity-managed parts mixed in. + */ + @NonNull + private NetworkScore mixInNetworkScore(@NonNull final NetworkAgentInfo nai, + @NonNull final NetworkScore sourceScore) { + final NetworkScore.Builder score = new NetworkScore.Builder(sourceScore); + + // TODO : this should be done in Telephony. It should be handled per-network because + // it's a carrier-dependent config. + if (nai.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) { + if (mMultinetworkPolicyTracker.getAvoidBadWifi()) { + score.clearPolicy(NetworkScore.POLICY_IGNORE_ON_WIFI); + } else { + score.addPolicy(NetworkScore.POLICY_IGNORE_ON_WIFI); + } + } + + return score.build(); + } + private void updateNetworkScore(NetworkAgentInfo nai, NetworkScore ns) { if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + ns); - nai.setNetworkScore(ns); + nai.setNetworkScore(mixInNetworkScore(nai, ns)); rematchAllNetworksAndRequests(); sendUpdatedScoreToFactories(nai); } From 66f497c90778fa4696ae6fbd786b310228aabde9 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 14 Feb 2020 17:05:02 +0900 Subject: [PATCH 058/229] [NS D03] Migrate the bad wifi avoidance policy Test: ConnectivityServiceTest Bug: 113554781 Change-Id: I688593cc0379a0d2042e30fbe83e549dcb02723e --- .../server/connectivity/NetworkRanker.java | 27 +++++++++++++++++-- .../server/connectivity/NetworkRankerTest.kt | 2 ++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/services/core/java/com/android/server/connectivity/NetworkRanker.java index 1ae7dc5c36..c536ab25e9 100644 --- a/services/core/java/com/android/server/connectivity/NetworkRanker.java +++ b/services/core/java/com/android/server/connectivity/NetworkRanker.java @@ -16,8 +16,13 @@ package com.android.server.connectivity; +import static android.net.NetworkScore.POLICY_IGNORE_ON_WIFI; + +import static com.android.internal.util.FunctionalUtils.findFirst; + import android.annotation.NonNull; import android.annotation.Nullable; +import android.net.NetworkCapabilities; import android.net.NetworkRequest; import java.util.ArrayList; @@ -37,15 +42,33 @@ public class NetworkRanker { @NonNull final Collection nais) { final ArrayList candidates = new ArrayList<>(nais); candidates.removeIf(nai -> !nai.satisfies(request)); + // Enforce policy. + filterBadWifiAvoidancePolicy(candidates); NetworkAgentInfo bestNetwork = null; int bestScore = Integer.MIN_VALUE; for (final NetworkAgentInfo nai : candidates) { - if (nai.getCurrentScore() > bestScore) { + final int score = nai.getCurrentScore(); + if (score > bestScore) { bestNetwork = nai; - bestScore = nai.getCurrentScore(); + bestScore = score; } } return bestNetwork; } + + // If some network with wifi transport is present, drop all networks with POLICY_IGNORE_ON_WIFI. + private void filterBadWifiAvoidancePolicy( + @NonNull final ArrayList candidates) { + final NetworkAgentInfo wifi = findFirst(candidates, + nai -> nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) + && nai.everValidated + // Horrible hack : there is old UI that will let a user say they want to + // override the policy only for this network only at this time and it + // feeds into the following member. This old UI should probably be removed + // but for now keep backward compatibility. + && !nai.avoidUnvalidated); + if (null == wifi) return; // No wifi : this policy doesn't apply + candidates.removeIf(nai -> nai.getNetworkScore().hasPolicy(POLICY_IGNORE_ON_WIFI)); + } } diff --git a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt index 86c91165f6..a6b371a23b 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt +++ b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt @@ -16,6 +16,7 @@ package com.android.server.connectivity +import android.net.NetworkCapabilities import android.net.NetworkRequest import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 @@ -35,6 +36,7 @@ class NetworkRankerTest { private fun makeNai(satisfy: Boolean, score: Int) = mock(NetworkAgentInfo::class.java).also { doReturn(satisfy).`when`(it).satisfies(any()) doReturn(score).`when`(it).currentScore + it.networkCapabilities = NetworkCapabilities() } @Test From 1355c8b25547cd54ebc543ab650606b40b381d83 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Mon, 17 Feb 2020 16:19:52 +0900 Subject: [PATCH 059/229] [NS D04] Implement a simple speed comparison between scores. This is not used yet to avoid making the change too big to review, but D05 will use this. Refer to D05 for how this is going to be used. Test: ConnectivityServiceTest Change-Id: I32c12702c8bce959682b02f157946d3f37b12a0c --- core/java/android/net/NetworkScore.java | 86 +++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java index d2e59eb893..d207e7960d 100644 --- a/core/java/android/net/NetworkScore.java +++ b/core/java/android/net/NetworkScore.java @@ -83,6 +83,65 @@ public final class NetworkScore implements Parcelable { uplinkBandwidthKBps = uplinkBandwidth; } + /** + * Evaluate whether a metrics codes for faster network is faster than another. + * + * This is a simple comparison of expected speeds. If either of the tested attributes + * are unknown, this returns zero. This implementation just assumes downlink bandwidth + * is more important than uplink bandwidth, which is more important than latency. This + * is not a very good way of evaluating network speed, but it's a start. + * TODO : do something more representative of how fast the network feels + * + * @param other the Metrics to evaluate against + * @return a negative integer, zero, or a positive integer as this metrics is worse than, + * equally good as (or unknown), or better than the passed Metrics. + * @see #compareToPreferringKnown(Metrics) + * @hide + */ + // Can't implement Comparable because this is @hide. + public int compareTo(@NonNull final Metrics other) { + if (downlinkBandwidthKBps != BANDWIDTH_UNKNOWN + && other.downlinkBandwidthKBps != BANDWIDTH_UNKNOWN) { + if (downlinkBandwidthKBps > other.downlinkBandwidthKBps) return 1; + if (downlinkBandwidthKBps < other.downlinkBandwidthKBps) return -1; + } + if (uplinkBandwidthKBps != BANDWIDTH_UNKNOWN + && other.uplinkBandwidthKBps != BANDWIDTH_UNKNOWN) { + if (uplinkBandwidthKBps > other.uplinkBandwidthKBps) return 1; + if (uplinkBandwidthKBps < other.uplinkBandwidthKBps) return -1; + } + if (latencyMs != LATENCY_UNKNOWN && other.latencyMs != LATENCY_UNKNOWN) { + // Latency : lower is better + if (latencyMs > other.latencyMs) return -1; + if (latencyMs < other.latencyMs) return 1; + } + return 0; + } + + /** + * Evaluate whether a metrics codes for faster network is faster than another. + * + * This is a simple comparison of expected speeds. If either of the tested attributes + * are unknown, this prefers the known attributes. This implementation just assumes + * downlink bandwidth is more important than uplink bandwidth, which is more important than + * latency. This is not a very good way of evaluating network speed, but it's a start. + * TODO : do something more representative of how fast the network feels + * + * @param other the Metrics to evaluate against + * @return a negative integer, zero, or a positive integer as this metrics is worse than, + * equally good as (or unknown), or better than the passed Metrics. + * @see #compareTo(Metrics) + * @hide + */ + public int compareToPreferringKnown(@NonNull final Metrics other) { + if (downlinkBandwidthKBps > other.downlinkBandwidthKBps) return 1; + if (downlinkBandwidthKBps < other.downlinkBandwidthKBps) return -1; + if (uplinkBandwidthKBps > other.uplinkBandwidthKBps) return 1; + if (uplinkBandwidthKBps < other.uplinkBandwidthKBps) return -1; + // Latency : lower is better + return -Integer.compare(latencyMs, other.latencyMs); + } + /** toString */ public String toString() { return "latency = " + latencyMs + " downlinkBandwidth = " + downlinkBandwidthKBps @@ -346,6 +405,33 @@ public final class NetworkScore implements Parcelable { return mLegacyScore; } + /** + * Use the metrics to evaluate whether a network is faster than another. + * + * This is purely based on the metrics, and explicitly ignores policy or exiting. It's + * provided to get a decision on two networks when policy can not decide, or to evaluate + * how a network is expected to compare to another if it should validate. + * + * @param other the score to evaluate against + * @return whether this network is probably faster than the other + * @hide + */ + public boolean probablyFasterThan(@NonNull final NetworkScore other) { + if (mLegacyScore > other.mLegacyScore) return true; + final int atEndToEnd = mEndToEndMetrics.compareTo(other.mEndToEndMetrics); + if (atEndToEnd > 0) return true; + if (atEndToEnd < 0) return false; + final int atLinkLayer = mLinkLayerMetrics.compareTo(other.mLinkLayerMetrics); + if (atLinkLayer > 0) return true; + if (atLinkLayer < 0) return false; + final int atEndToEndPreferringKnown = + mEndToEndMetrics.compareToPreferringKnown(other.mEndToEndMetrics); + if (atEndToEndPreferringKnown > 0) return true; + if (atEndToEndPreferringKnown < 0) return false; + // If this returns 0, neither is "probably faster" so just return false. + return mLinkLayerMetrics.compareToPreferringKnown(other.mLinkLayerMetrics) > 0; + } + /** Builder for NetworkScore. */ public static class Builder { private int mPolicy = 0; From fb68c522677d47b42bdd4062776b320e2c127947 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Fri, 17 Jan 2020 19:33:55 -0800 Subject: [PATCH 060/229] Add always-on VPN support for platform VPNs This commit allows Platform VPNs to be started as part of always-on mode. Test: FrameworksNetTests passing, new tests added in subsequent CL Test: Manually tested. Change-Id: I5eda88e5b406a0e425eb7424665cf702e0979324 --- .../android/server/ConnectivityService.java | 14 +-- .../server/ConnectivityServiceTest.java | 3 +- .../android/server/connectivity/VpnTest.java | 86 ++++++++++++++----- 3 files changed, 73 insertions(+), 30 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 0f36260d10..7083281eaa 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -4791,7 +4791,7 @@ public class ConnectivityService extends IConnectivityManager.Stub return false; } - return vpn.startAlwaysOnVpn(); + return vpn.startAlwaysOnVpn(mKeyStore); } } @@ -4806,7 +4806,7 @@ public class ConnectivityService extends IConnectivityManager.Stub Slog.w(TAG, "User " + userId + " has no Vpn configuration"); return false; } - return vpn.isAlwaysOnPackageSupported(packageName); + return vpn.isAlwaysOnPackageSupported(packageName, mKeyStore); } } @@ -4827,11 +4827,11 @@ public class ConnectivityService extends IConnectivityManager.Stub Slog.w(TAG, "User " + userId + " has no Vpn configuration"); return false; } - if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownWhitelist)) { + if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownWhitelist, mKeyStore)) { return false; } if (!startAlwaysOnVpn(userId)) { - vpn.setAlwaysOnPackage(null, false, null); + vpn.setAlwaysOnPackage(null, false, null, mKeyStore); return false; } } @@ -5017,7 +5017,7 @@ public class ConnectivityService extends IConnectivityManager.Stub loge("Starting user already has a VPN"); return; } - userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId); + userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId, mKeyStore); mVpns.put(userId, userVpn); if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) { updateLockdownVpn(); @@ -5088,7 +5088,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) { Slog.d(TAG, "Restarting always-on VPN package " + packageName + " for user " + userId); - vpn.startAlwaysOnVpn(); + vpn.startAlwaysOnVpn(mKeyStore); } } } @@ -5110,7 +5110,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) { Slog.d(TAG, "Removing always-on VPN package " + packageName + " for user " + userId); - vpn.setAlwaysOnPackage(null, false, null); + vpn.setAlwaysOnPackage(null, false, null, mKeyStore); } } } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 957683e05d..08869751b9 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -204,6 +204,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.security.KeyStore; import android.system.Os; import android.test.mock.MockContentResolver; import android.text.TextUtils; @@ -1019,7 +1020,7 @@ public class ConnectivityServiceTest { public MockVpn(int userId) { super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService, - userId); + userId, mock(KeyStore.class)); } public void setNetworkAgent(TestNetworkAgentWrapper agent) { diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index ac1c51837e..0e3b797613 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -72,6 +72,7 @@ import android.os.Looper; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; +import android.provider.Settings; import android.security.Credentials; import android.security.KeyStore; import android.util.ArrayMap; @@ -260,17 +261,17 @@ public class VpnTest { assertFalse(vpn.getLockdown()); // Set always-on without lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList())); + assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList(), mKeyStore)); assertTrue(vpn.getAlwaysOn()); assertFalse(vpn.getLockdown()); // Set always-on with lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList())); + assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList(), mKeyStore)); assertTrue(vpn.getAlwaysOn()); assertTrue(vpn.getLockdown()); // Remove always-on configuration. - assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList())); + assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList(), mKeyStore)); assertFalse(vpn.getAlwaysOn()); assertFalse(vpn.getLockdown()); } @@ -284,11 +285,11 @@ public class VpnTest { assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on without lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null, mKeyStore)); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on with lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null, mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { new UidRange(user.start, user.start + PKG_UIDS[1] - 1), new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) @@ -297,7 +298,7 @@ public class VpnTest { assertUnblocked(vpn, user.start + PKG_UIDS[1]); // Switch to another app. - assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { new UidRange(user.start, user.start + PKG_UIDS[1] - 1), new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) @@ -316,7 +317,8 @@ public class VpnTest { final UidRange user = UidRange.createForUser(primaryUser.id); // Set always-on with lockdown and whitelist app PKGS[2] from lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.singletonList(PKGS[2]))); + assertTrue(vpn.setAlwaysOnPackage( + PKGS[1], true, Collections.singletonList(PKGS[2]), mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { new UidRange(user.start, user.start + PKG_UIDS[1] - 1), new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) @@ -325,7 +327,8 @@ public class VpnTest { assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); // Change whitelisted app to PKGS[3]. - assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.singletonList(PKGS[3]))); + assertTrue(vpn.setAlwaysOnPackage( + PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) })); @@ -337,7 +340,8 @@ public class VpnTest { assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]); // Change the VPN app. - assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList(PKGS[3]))); + assertTrue(vpn.setAlwaysOnPackage( + PKGS[0], true, Collections.singletonList(PKGS[3]), mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { new UidRange(user.start, user.start + PKG_UIDS[1] - 1), new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1) @@ -350,7 +354,7 @@ public class VpnTest { assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); // Remove the whitelist. - assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1), new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) @@ -363,7 +367,8 @@ public class VpnTest { assertUnblocked(vpn, user.start + PKG_UIDS[0]); // Add the whitelist. - assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList(PKGS[1]))); + assertTrue(vpn.setAlwaysOnPackage( + PKGS[0], true, Collections.singletonList(PKGS[1]), mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { new UidRange(user.start + PKG_UIDS[0] + 1, user.stop) })); @@ -375,12 +380,13 @@ public class VpnTest { assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]); // Try whitelisting a package with a comma, should be rejected. - assertFalse(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList("a.b,c.d"))); + assertFalse(vpn.setAlwaysOnPackage( + PKGS[0], true, Collections.singletonList("a.b,c.d"), mKeyStore)); // Pass a non-existent packages in the whitelist, they (and only they) should be ignored. // Whitelisted package should change from PGKS[1] to PKGS[2]. - assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, - Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"))); + assertTrue(vpn.setAlwaysOnPackage( + PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"), mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[]{ new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) @@ -405,7 +411,7 @@ public class VpnTest { final UidRange profile = UidRange.createForUser(tempProfile.id); // Set lockdown. - assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null)); + assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore)); verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { new UidRange(user.start, user.start + PKG_UIDS[3] - 1), new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) @@ -499,22 +505,22 @@ public class VpnTest { .thenReturn(Collections.singletonList(resInfo)); // null package name should return false - assertFalse(vpn.isAlwaysOnPackageSupported(null)); + assertFalse(vpn.isAlwaysOnPackageSupported(null, mKeyStore)); // Pre-N apps are not supported appInfo.targetSdkVersion = VERSION_CODES.M; - assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); + assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0], mKeyStore)); // N+ apps are supported by default appInfo.targetSdkVersion = VERSION_CODES.N; - assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0])); + assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0], mKeyStore)); // Apps that opt out explicitly are not supported appInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT; Bundle metaData = new Bundle(); metaData.putBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, false); svcInfo.metaData = metaData; - assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0])); + assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0], mKeyStore)); } @Test @@ -531,7 +537,7 @@ public class VpnTest { .cancelAsUser(anyString(), anyInt(), eq(userHandle)); // Start showing a notification for disconnected once always-on. - vpn.setAlwaysOnPackage(PKGS[0], false, null); + vpn.setAlwaysOnPackage(PKGS[0], false, null, mKeyStore); order.verify(mNotificationManager) .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle)); @@ -545,7 +551,7 @@ public class VpnTest { .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle)); // Notification should be cleared after unsetting always-on package. - vpn.setAlwaysOnPackage(null, false, null); + vpn.setAlwaysOnPackage(null, false, null, mKeyStore); order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle)); } @@ -920,12 +926,48 @@ public class VpnTest { eq(AppOpsManager.MODE_IGNORED)); } + private void setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled) { + assertTrue(vpn.setAlwaysOnPackage(TEST_VPN_PKG, lockdownEnabled, null, mKeyStore)); + + verify(mKeyStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG))); + verify(mAppOps).setMode( + eq(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN), eq(uid), eq(TEST_VPN_PKG), + eq(AppOpsManager.MODE_ALLOWED)); + + verify(mSystemServices).settingsSecurePutStringForUser( + eq(Settings.Secure.ALWAYS_ON_VPN_APP), eq(TEST_VPN_PKG), eq(primaryUser.id)); + verify(mSystemServices).settingsSecurePutIntForUser( + eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN), eq(lockdownEnabled ? 1 : 0), + eq(primaryUser.id)); + verify(mSystemServices).settingsSecurePutStringForUser( + eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST), eq(""), eq(primaryUser.id)); + } + + @Test + public void testSetAndStartAlwaysOnVpn() throws Exception { + final Vpn vpn = createVpn(primaryUser.id); + setMockedUsers(primaryUser); + + // UID checks must return a different UID; otherwise it'll be treated as already prepared. + final int uid = Process.myUid() + 1; + when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt())) + .thenReturn(uid); + when(mKeyStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) + .thenReturn(mVpnProfile.encode()); + + setAndVerifyAlwaysOnPackage(vpn, uid, false); + assertTrue(vpn.startAlwaysOnVpn(mKeyStore)); + + // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in + // a subsequent CL. + } + /** * Mock some methods of vpn object. */ private Vpn createVpn(@UserIdInt int userId) { return new Vpn(Looper.myLooper(), mContext, mNetService, - userId, mSystemServices, mIkev2SessionCreator); + userId, mKeyStore, mSystemServices, mIkev2SessionCreator); } private static void assertBlocked(Vpn vpn, int... uids) { From 822a150c03d132f5256dd38d3b769fbc8b4f1a90 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Mon, 17 Feb 2020 16:23:20 +0900 Subject: [PATCH 061/229] [NS D05] Rework how to tear down networks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Networks are torn down if they don't satisfy requests but only if they are found unable to ever do so. This is important because general-purpose networks typically turn up unvalidated, which means they would get torn down immediately in the presence of some worse network that is already validated. Note that functionally it's the same as before for the existing scores, except that • An exiting network that doesn't satisfy any request is always torn down immediately – this is WAI • An unmetered network is never torn down when compared to a metered network – this is a bugfix (previously the platform would tear down an unmetered cellular on grounds that it could not beat the performance of a metered Ethernet, but that's wrong ; the bug was never realized because Android always thinks Ethernet is unmetered) • An unvalidated network will not be torn down if the current satisfier is also unvalidated, even if the satisfier is much faster. This is the reason for the change in the test. It's wrong to tear down in this case because even if much slower the slower network should win if it validates and the other doesn't. Test: ConnectivityServiceTest Change-Id: Ic9a3d336306a25d1272976ce467aa7c908af7bef --- .../android/server/ConnectivityService.java | 20 +++--- .../server/connectivity/NetworkAgentInfo.java | 67 ++++++++++++------- .../server/ConnectivityServiceTest.java | 9 +-- 3 files changed, 57 insertions(+), 39 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 7083281eaa..f7eabac3b2 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3430,16 +3430,16 @@ public class ConnectivityService extends IConnectivityManager.Stub // there is hope for it to become one if it validated, then it is needed. ensureRunningOnConnectivityServiceThread(); if (nri.request.isRequest() && nai.satisfies(nri.request) && - (nai.isSatisfyingRequest(nri.request.requestId) || - // Note that this catches two important cases: - // 1. Unvalidated cellular will not be reaped when unvalidated WiFi - // is currently satisfying the request. This is desirable when - // cellular ends up validating but WiFi does not. - // 2. Unvalidated WiFi will not be reaped when validated cellular - // is currently satisfying the request. This is desirable when - // WiFi ends up validating and out scoring cellular. - nri.mSatisfier.getCurrentScore() - < nai.getCurrentScoreAsValidated())) { + (nai.isSatisfyingRequest(nri.request.requestId) + // Note that canPossiblyBeat catches two important cases: + // 1. Unvalidated slow networks will not be reaped when an unvalidated fast + // network is currently satisfying the request. This is desirable for example + // when cellular ends up validating but WiFi/Ethernet does not. + // 2. Fast networks will not be reaped when a validated slow network is + // currently satisfying the request. This is desirable for example when + // Ethernet ends up validating and out scoring WiFi, or WiFi/Ethernet ends + // up validating and out scoring cellular. + || nai.canPossiblyBeat(nri.mSatisfier))) { return false; } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 4612cfd0f7..3860904a3f 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -16,6 +16,8 @@ package com.android.server.connectivity; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; +import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.transportNamesOf; import android.annotation.NonNull; @@ -475,24 +477,16 @@ public class NetworkAgentInfo implements Comparable { return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN); } - private int getCurrentScore(boolean pretendValidated) { - // TODO: We may want to refactor this into a NetworkScore class that takes a base score from - // the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the - // score. The NetworkScore class would provide a nice place to centralize score constants - // so they are not scattered about the transports. - + /** Gets the current score */ + public int getCurrentScore() { // If this network is explicitly selected and the user has decided to use it even if it's - // unvalidated, give it the maximum score. Also give it the maximum score if it's explicitly - // selected and we're trying to see what its score could be. This ensures that we don't tear - // down an explicitly selected network before the user gets a chance to prefer it when - // a higher-scoring network (e.g., Ethernet) is available. - if (networkAgentConfig.explicitlySelected - && (networkAgentConfig.acceptUnvalidated || pretendValidated)) { + // unvalidated, give it the maximum score. + if (networkAgentConfig.explicitlySelected && networkAgentConfig.acceptUnvalidated) { return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE; } int score = mNetworkScore.getLegacyScore(); - if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) { + if (!lastValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) { score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY; } if (score < 0) score = 0; @@ -508,18 +502,6 @@ public class NetworkAgentInfo implements Comparable { return isWifi && !avoidBadWifi && everValidated; } - // Get the current score for this Network. This may be modified from what the - // NetworkAgent sent, as it has modifiers applied to it. - public int getCurrentScore() { - return getCurrentScore(false); - } - - // Get the current score for this Network as if it was validated. This may be modified from - // what the NetworkAgent sent, as it has modifiers applied to it. - public int getCurrentScoreAsValidated() { - return getCurrentScore(true); - } - public void setNetworkScore(@NonNull NetworkScore ns) { mNetworkScore = ns; } @@ -629,6 +611,41 @@ public class NetworkAgentInfo implements Comparable { mLingering = false; } + /** + * Returns whether this NAI has any chance of ever beating this other agent. + * + * The chief use case of this is the decision to tear down this network. ConnectivityService + * tears down networks that don't satisfy any request, unless they have a chance to beat any + * existing satisfier. + * + * @param other the agent to beat + * @return whether this should be given more time to try and beat the other agent + * TODO : remove this and migrate to a ranker-based approach + */ + public boolean canPossiblyBeat(@NonNull final NetworkAgentInfo other) { + // Any explicitly selected network should be held on. + if (networkAgentConfig.explicitlySelected) return true; + // An outscored exiting network should be torn down. + if (mNetworkScore.isExiting()) return false; + // If this network is validated it can be torn down as it can't hope to be better than + // it already is. + if (networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) return false; + // If neither network is validated, keep both until at least one does. + if (!other.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) return true; + // If this network is not metered but the other is, it should be preferable if it validates. + if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED) + && !other.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) { + return true; + } + + // If the control comes here : + // • This network is neither exiting or explicitly selected + // • This network is not validated, but the other is + // • This network is metered, or both networks are unmetered + // Keep it if it's expected to be faster than the other., should it validate. + return mNetworkScore.probablyFasterThan(other.mNetworkScore); + } + public void dumpLingerTimers(PrintWriter pw) { for (LingerTimer timer : mLingerTimers) { pw.println(timer); } } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 08869751b9..5aabc60b22 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -2054,14 +2054,15 @@ public class ConnectivityServiceTest { assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - // Bring up wifi with a score of 70. + // Bring up validated wifi. // Cell is lingered because it would not satisfy any request, even if it validated. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.adjustScore(50); - mWiFiNetworkAgent.connect(false); // Score: 70 + mWiFiNetworkAgent.connect(true); // Score: 60 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + // TODO: Investigate sending validated before losing. callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); + defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); From c736e7639402df760b621d53e7f5e04de75a2c2f Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 14 Feb 2020 23:33:47 +0900 Subject: [PATCH 062/229] [NS D06] Implement more policies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Namely : • Explicitly selected policy • VPN policy • Validated policy These go together to avoid breaking any test, because multiple tests rely on all of these working. Test: ConnectivityServiceTest Change-Id: I7d815f87320c2becbfc93a60a3c54346ff4f47c9 --- .../server/connectivity/NetworkRanker.java | 48 +++++++++++++++++-- .../server/connectivity/NetworkRankerTest.kt | 28 +++++++++-- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/services/core/java/com/android/server/connectivity/NetworkRanker.java index c536ab25e9..fd5a4e82de 100644 --- a/services/core/java/com/android/server/connectivity/NetworkRanker.java +++ b/services/core/java/com/android/server/connectivity/NetworkRanker.java @@ -16,6 +16,9 @@ package com.android.server.connectivity; +import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; +import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; +import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkScore.POLICY_IGNORE_ON_WIFI; import static com.android.internal.util.FunctionalUtils.findFirst; @@ -42,8 +45,15 @@ public class NetworkRanker { @NonNull final Collection nais) { final ArrayList candidates = new ArrayList<>(nais); candidates.removeIf(nai -> !nai.satisfies(request)); - // Enforce policy. - filterBadWifiAvoidancePolicy(candidates); + + // Enforce policy. The order in which the policy is computed is essential, because each + // step may remove some of the candidates. For example, filterValidated drops non-validated + // networks in presence of validated networks for INTERNET requests, but the bad wifi + // avoidance policy takes priority over this, so it must be done before. + filterVpn(candidates); + filterExplicitlySelected(candidates); + filterBadWifiAvoidance(candidates); + filterValidated(request, candidates); NetworkAgentInfo bestNetwork = null; int bestScore = Integer.MIN_VALUE; @@ -57,9 +67,27 @@ public class NetworkRanker { return bestNetwork; } - // If some network with wifi transport is present, drop all networks with POLICY_IGNORE_ON_WIFI. - private void filterBadWifiAvoidancePolicy( + // If a network is a VPN it has priority. + private void filterVpn(@NonNull final ArrayList candidates) { + final NetworkAgentInfo vpn = findFirst(candidates, + nai -> nai.networkCapabilities.hasTransport(TRANSPORT_VPN)); + if (null == vpn) return; // No VPN : this policy doesn't apply. + candidates.removeIf(nai -> !nai.networkCapabilities.hasTransport(TRANSPORT_VPN)); + } + + // If some network is explicitly selected and set to accept unvalidated connectivity, then + // drop all networks that are not explicitly selected. + private void filterExplicitlySelected( @NonNull final ArrayList candidates) { + final NetworkAgentInfo explicitlySelected = findFirst(candidates, + nai -> nai.networkAgentConfig.explicitlySelected + && nai.networkAgentConfig.acceptUnvalidated); + if (null == explicitlySelected) return; // No explicitly selected network accepting unvalid + candidates.removeIf(nai -> !nai.networkAgentConfig.explicitlySelected); + } + + // If some network with wifi transport is present, drop all networks with POLICY_IGNORE_ON_WIFI. + private void filterBadWifiAvoidance(@NonNull final ArrayList candidates) { final NetworkAgentInfo wifi = findFirst(candidates, nai -> nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && nai.everValidated @@ -71,4 +99,16 @@ public class NetworkRanker { if (null == wifi) return; // No wifi : this policy doesn't apply candidates.removeIf(nai -> nai.getNetworkScore().hasPolicy(POLICY_IGNORE_ON_WIFI)); } + + // If some network is validated and the request asks for INTERNET, drop all networks that are + // not validated. + private void filterValidated(@NonNull final NetworkRequest request, + @NonNull final ArrayList candidates) { + if (!request.hasCapability(NET_CAPABILITY_INTERNET)) return; + final NetworkAgentInfo validated = findFirst(candidates, + nai -> nai.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)); + if (null == validated) return; // No validated network + candidates.removeIf(nai -> + !nai.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)); + } } diff --git a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt index a6b371a23b..2b0c2c7215 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt +++ b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt @@ -16,8 +16,14 @@ package com.android.server.connectivity +import android.net.ConnectivityManager.TYPE_WIFI +import android.net.LinkProperties +import android.net.Network +import android.net.NetworkAgentConfig import android.net.NetworkCapabilities +import android.net.NetworkInfo import android.net.NetworkRequest +import android.net.NetworkScore import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 import org.junit.Test @@ -33,10 +39,24 @@ import kotlin.test.assertNull class NetworkRankerTest { private val ranker = NetworkRanker() - private fun makeNai(satisfy: Boolean, score: Int) = mock(NetworkAgentInfo::class.java).also { - doReturn(satisfy).`when`(it).satisfies(any()) - doReturn(score).`when`(it).currentScore - it.networkCapabilities = NetworkCapabilities() + private fun makeNai(satisfy: Boolean, score: Int) = object : NetworkAgentInfo( + null /* messenger */, + null /* asyncChannel*/, + Network(100), + NetworkInfo(TYPE_WIFI, 0 /* subtype */, "" /* typename */, "" /* subtypename */), + LinkProperties(), + NetworkCapabilities(), + NetworkScore.Builder().setLegacyScore(score).build(), + null /* context */, + null /* handler */, + NetworkAgentConfig(), + null /* connectivityService */, + null /* netd */, + null /* dnsResolver */, + null /* networkManagementService */, + 0 /* factorySerialNumber */) { + override fun satisfies(request: NetworkRequest?): Boolean = satisfy + override fun getCurrentScore(): Int = score } @Test From 4bb5b458302964605bc50fff76ea4c14f325bdfb Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Mon, 17 Feb 2020 19:11:04 +0900 Subject: [PATCH 063/229] [NS D07] Use the unmodified legacy score Ranking used to make use of the various adjustments in ConnectivityService. These are now implemented in policy. Test: ConnectivityServiceTest Change-Id: I56109847678ea5cda1752511123ba652c0f4fe36 --- .../java/com/android/server/connectivity/NetworkRanker.java | 2 +- tests/net/java/com/android/server/ConnectivityServiceTest.java | 2 +- .../java/com/android/server/connectivity/NetworkRankerTest.kt | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/services/core/java/com/android/server/connectivity/NetworkRanker.java index fd5a4e82de..80d46e0370 100644 --- a/services/core/java/com/android/server/connectivity/NetworkRanker.java +++ b/services/core/java/com/android/server/connectivity/NetworkRanker.java @@ -58,7 +58,7 @@ public class NetworkRanker { NetworkAgentInfo bestNetwork = null; int bestScore = Integer.MIN_VALUE; for (final NetworkAgentInfo nai : candidates) { - final int score = nai.getCurrentScore(); + final int score = nai.getNetworkScore().getLegacyScore(); if (score > bestScore) { bestNetwork = nai; bestScore = score; diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 5aabc60b22..220cdce0d1 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -5846,7 +5846,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); - trustedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); + trustedCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId)); reset(mNetworkManagementService); diff --git a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt index 2b0c2c7215..d2532c2ce3 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt +++ b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt @@ -28,8 +28,6 @@ import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 import org.junit.Test import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers.any -import org.mockito.Mockito.doReturn import org.mockito.Mockito.mock import kotlin.test.assertEquals import kotlin.test.assertNull From b104cd7c1245095286d0fa224c0f47e4bea357d4 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 20 Feb 2020 07:32:12 +0000 Subject: [PATCH 064/229] Revert "[NS D07] Use the unmodified legacy score" Revert submission 10343065 Reason for revert: This is part of a feature that was punted out of R. Reverted Changes: Ic9a3d3363:[NS D05] Rework how to tear down networks I7d815f873:[NS D06] Implement more policies I561098476:[NS D07] Use the unmodified legacy score Change-Id: I184817e3aa290afdbe6721a7c36332b940434d3a --- .../java/com/android/server/connectivity/NetworkRanker.java | 2 +- tests/net/java/com/android/server/ConnectivityServiceTest.java | 2 +- .../java/com/android/server/connectivity/NetworkRankerTest.kt | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/services/core/java/com/android/server/connectivity/NetworkRanker.java index 80d46e0370..fd5a4e82de 100644 --- a/services/core/java/com/android/server/connectivity/NetworkRanker.java +++ b/services/core/java/com/android/server/connectivity/NetworkRanker.java @@ -58,7 +58,7 @@ public class NetworkRanker { NetworkAgentInfo bestNetwork = null; int bestScore = Integer.MIN_VALUE; for (final NetworkAgentInfo nai : candidates) { - final int score = nai.getNetworkScore().getLegacyScore(); + final int score = nai.getCurrentScore(); if (score > bestScore) { bestNetwork = nai; bestScore = score; diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 220cdce0d1..5aabc60b22 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -5846,7 +5846,7 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(true); - trustedCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); + trustedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId)); reset(mNetworkManagementService); diff --git a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt index d2532c2ce3..2b0c2c7215 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt +++ b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt @@ -28,6 +28,8 @@ import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers.any +import org.mockito.Mockito.doReturn import org.mockito.Mockito.mock import kotlin.test.assertEquals import kotlin.test.assertNull From 751e5a1c37c0592189c0f30edb86d1e0d8623d50 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 20 Feb 2020 07:32:12 +0000 Subject: [PATCH 065/229] Revert "[NS D06] Implement more policies" Revert submission 10343065 Reason for revert: This is part of a feature that was punted out of R. Reverted Changes: Ic9a3d3363:[NS D05] Rework how to tear down networks I7d815f873:[NS D06] Implement more policies I561098476:[NS D07] Use the unmodified legacy score Change-Id: I378449443f99eb0a7f01f31f53398b8f55ce87f1 --- .../server/connectivity/NetworkRanker.java | 48 ++----------------- .../server/connectivity/NetworkRankerTest.kt | 28 ++--------- 2 files changed, 8 insertions(+), 68 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/services/core/java/com/android/server/connectivity/NetworkRanker.java index fd5a4e82de..c536ab25e9 100644 --- a/services/core/java/com/android/server/connectivity/NetworkRanker.java +++ b/services/core/java/com/android/server/connectivity/NetworkRanker.java @@ -16,9 +16,6 @@ package com.android.server.connectivity; -import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; -import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; -import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkScore.POLICY_IGNORE_ON_WIFI; import static com.android.internal.util.FunctionalUtils.findFirst; @@ -45,15 +42,8 @@ public class NetworkRanker { @NonNull final Collection nais) { final ArrayList candidates = new ArrayList<>(nais); candidates.removeIf(nai -> !nai.satisfies(request)); - - // Enforce policy. The order in which the policy is computed is essential, because each - // step may remove some of the candidates. For example, filterValidated drops non-validated - // networks in presence of validated networks for INTERNET requests, but the bad wifi - // avoidance policy takes priority over this, so it must be done before. - filterVpn(candidates); - filterExplicitlySelected(candidates); - filterBadWifiAvoidance(candidates); - filterValidated(request, candidates); + // Enforce policy. + filterBadWifiAvoidancePolicy(candidates); NetworkAgentInfo bestNetwork = null; int bestScore = Integer.MIN_VALUE; @@ -67,27 +57,9 @@ public class NetworkRanker { return bestNetwork; } - // If a network is a VPN it has priority. - private void filterVpn(@NonNull final ArrayList candidates) { - final NetworkAgentInfo vpn = findFirst(candidates, - nai -> nai.networkCapabilities.hasTransport(TRANSPORT_VPN)); - if (null == vpn) return; // No VPN : this policy doesn't apply. - candidates.removeIf(nai -> !nai.networkCapabilities.hasTransport(TRANSPORT_VPN)); - } - - // If some network is explicitly selected and set to accept unvalidated connectivity, then - // drop all networks that are not explicitly selected. - private void filterExplicitlySelected( - @NonNull final ArrayList candidates) { - final NetworkAgentInfo explicitlySelected = findFirst(candidates, - nai -> nai.networkAgentConfig.explicitlySelected - && nai.networkAgentConfig.acceptUnvalidated); - if (null == explicitlySelected) return; // No explicitly selected network accepting unvalid - candidates.removeIf(nai -> !nai.networkAgentConfig.explicitlySelected); - } - // If some network with wifi transport is present, drop all networks with POLICY_IGNORE_ON_WIFI. - private void filterBadWifiAvoidance(@NonNull final ArrayList candidates) { + private void filterBadWifiAvoidancePolicy( + @NonNull final ArrayList candidates) { final NetworkAgentInfo wifi = findFirst(candidates, nai -> nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && nai.everValidated @@ -99,16 +71,4 @@ public class NetworkRanker { if (null == wifi) return; // No wifi : this policy doesn't apply candidates.removeIf(nai -> nai.getNetworkScore().hasPolicy(POLICY_IGNORE_ON_WIFI)); } - - // If some network is validated and the request asks for INTERNET, drop all networks that are - // not validated. - private void filterValidated(@NonNull final NetworkRequest request, - @NonNull final ArrayList candidates) { - if (!request.hasCapability(NET_CAPABILITY_INTERNET)) return; - final NetworkAgentInfo validated = findFirst(candidates, - nai -> nai.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)); - if (null == validated) return; // No validated network - candidates.removeIf(nai -> - !nai.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)); - } } diff --git a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt index 2b0c2c7215..a6b371a23b 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt +++ b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt @@ -16,14 +16,8 @@ package com.android.server.connectivity -import android.net.ConnectivityManager.TYPE_WIFI -import android.net.LinkProperties -import android.net.Network -import android.net.NetworkAgentConfig import android.net.NetworkCapabilities -import android.net.NetworkInfo import android.net.NetworkRequest -import android.net.NetworkScore import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 import org.junit.Test @@ -39,24 +33,10 @@ import kotlin.test.assertNull class NetworkRankerTest { private val ranker = NetworkRanker() - private fun makeNai(satisfy: Boolean, score: Int) = object : NetworkAgentInfo( - null /* messenger */, - null /* asyncChannel*/, - Network(100), - NetworkInfo(TYPE_WIFI, 0 /* subtype */, "" /* typename */, "" /* subtypename */), - LinkProperties(), - NetworkCapabilities(), - NetworkScore.Builder().setLegacyScore(score).build(), - null /* context */, - null /* handler */, - NetworkAgentConfig(), - null /* connectivityService */, - null /* netd */, - null /* dnsResolver */, - null /* networkManagementService */, - 0 /* factorySerialNumber */) { - override fun satisfies(request: NetworkRequest?): Boolean = satisfy - override fun getCurrentScore(): Int = score + private fun makeNai(satisfy: Boolean, score: Int) = mock(NetworkAgentInfo::class.java).also { + doReturn(satisfy).`when`(it).satisfies(any()) + doReturn(score).`when`(it).currentScore + it.networkCapabilities = NetworkCapabilities() } @Test From b3ce7501b78065a19d8e57283bf7f3c699b99648 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 20 Feb 2020 07:32:12 +0000 Subject: [PATCH 066/229] Revert "[NS D05] Rework how to tear down networks" Revert submission 10343065 Reason for revert: This is part of a feature that was punted out of R. Reverted Changes: Ic9a3d3363:[NS D05] Rework how to tear down networks I7d815f873:[NS D06] Implement more policies I561098476:[NS D07] Use the unmodified legacy score Change-Id: I8d2696d15999265d79abfc9163e7e5ccad873cfe --- .../android/server/ConnectivityService.java | 20 +++--- .../server/connectivity/NetworkAgentInfo.java | 67 +++++++------------ .../server/ConnectivityServiceTest.java | 9 ++- 3 files changed, 39 insertions(+), 57 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index f7eabac3b2..7083281eaa 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3430,16 +3430,16 @@ public class ConnectivityService extends IConnectivityManager.Stub // there is hope for it to become one if it validated, then it is needed. ensureRunningOnConnectivityServiceThread(); if (nri.request.isRequest() && nai.satisfies(nri.request) && - (nai.isSatisfyingRequest(nri.request.requestId) - // Note that canPossiblyBeat catches two important cases: - // 1. Unvalidated slow networks will not be reaped when an unvalidated fast - // network is currently satisfying the request. This is desirable for example - // when cellular ends up validating but WiFi/Ethernet does not. - // 2. Fast networks will not be reaped when a validated slow network is - // currently satisfying the request. This is desirable for example when - // Ethernet ends up validating and out scoring WiFi, or WiFi/Ethernet ends - // up validating and out scoring cellular. - || nai.canPossiblyBeat(nri.mSatisfier))) { + (nai.isSatisfyingRequest(nri.request.requestId) || + // Note that this catches two important cases: + // 1. Unvalidated cellular will not be reaped when unvalidated WiFi + // is currently satisfying the request. This is desirable when + // cellular ends up validating but WiFi does not. + // 2. Unvalidated WiFi will not be reaped when validated cellular + // is currently satisfying the request. This is desirable when + // WiFi ends up validating and out scoring cellular. + nri.mSatisfier.getCurrentScore() + < nai.getCurrentScoreAsValidated())) { return false; } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 3860904a3f..4612cfd0f7 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -16,8 +16,6 @@ package com.android.server.connectivity; -import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; -import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.transportNamesOf; import android.annotation.NonNull; @@ -477,16 +475,24 @@ public class NetworkAgentInfo implements Comparable { return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN); } - /** Gets the current score */ - public int getCurrentScore() { + private int getCurrentScore(boolean pretendValidated) { + // TODO: We may want to refactor this into a NetworkScore class that takes a base score from + // the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the + // score. The NetworkScore class would provide a nice place to centralize score constants + // so they are not scattered about the transports. + // If this network is explicitly selected and the user has decided to use it even if it's - // unvalidated, give it the maximum score. - if (networkAgentConfig.explicitlySelected && networkAgentConfig.acceptUnvalidated) { + // unvalidated, give it the maximum score. Also give it the maximum score if it's explicitly + // selected and we're trying to see what its score could be. This ensures that we don't tear + // down an explicitly selected network before the user gets a chance to prefer it when + // a higher-scoring network (e.g., Ethernet) is available. + if (networkAgentConfig.explicitlySelected + && (networkAgentConfig.acceptUnvalidated || pretendValidated)) { return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE; } int score = mNetworkScore.getLegacyScore(); - if (!lastValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) { + if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) { score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY; } if (score < 0) score = 0; @@ -502,6 +508,18 @@ public class NetworkAgentInfo implements Comparable { return isWifi && !avoidBadWifi && everValidated; } + // Get the current score for this Network. This may be modified from what the + // NetworkAgent sent, as it has modifiers applied to it. + public int getCurrentScore() { + return getCurrentScore(false); + } + + // Get the current score for this Network as if it was validated. This may be modified from + // what the NetworkAgent sent, as it has modifiers applied to it. + public int getCurrentScoreAsValidated() { + return getCurrentScore(true); + } + public void setNetworkScore(@NonNull NetworkScore ns) { mNetworkScore = ns; } @@ -611,41 +629,6 @@ public class NetworkAgentInfo implements Comparable { mLingering = false; } - /** - * Returns whether this NAI has any chance of ever beating this other agent. - * - * The chief use case of this is the decision to tear down this network. ConnectivityService - * tears down networks that don't satisfy any request, unless they have a chance to beat any - * existing satisfier. - * - * @param other the agent to beat - * @return whether this should be given more time to try and beat the other agent - * TODO : remove this and migrate to a ranker-based approach - */ - public boolean canPossiblyBeat(@NonNull final NetworkAgentInfo other) { - // Any explicitly selected network should be held on. - if (networkAgentConfig.explicitlySelected) return true; - // An outscored exiting network should be torn down. - if (mNetworkScore.isExiting()) return false; - // If this network is validated it can be torn down as it can't hope to be better than - // it already is. - if (networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) return false; - // If neither network is validated, keep both until at least one does. - if (!other.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) return true; - // If this network is not metered but the other is, it should be preferable if it validates. - if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED) - && !other.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) { - return true; - } - - // If the control comes here : - // • This network is neither exiting or explicitly selected - // • This network is not validated, but the other is - // • This network is metered, or both networks are unmetered - // Keep it if it's expected to be faster than the other., should it validate. - return mNetworkScore.probablyFasterThan(other.mNetworkScore); - } - public void dumpLingerTimers(PrintWriter pw) { for (LingerTimer timer : mLingerTimers) { pw.println(timer); } } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 5aabc60b22..08869751b9 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -2054,15 +2054,14 @@ public class ConnectivityServiceTest { assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); - // Bring up validated wifi. + // Bring up wifi with a score of 70. // Cell is lingered because it would not satisfy any request, even if it validated. mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); - mWiFiNetworkAgent.connect(true); // Score: 60 + mWiFiNetworkAgent.adjustScore(50); + mWiFiNetworkAgent.connect(false); // Score: 70 callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); - // TODO: Investigate sending validated before losing. callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent); - callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent); - defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent); + defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork()); assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork()); From 6f677ac620e5f0d3bbad03207984a5286dbe7f65 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 20 Feb 2020 07:39:19 +0000 Subject: [PATCH 067/229] Revert "[NS D04] Implement a simple speed comparison between scores." Revert submission 10338939 Reason for revert: The feature was punted out of R. Reverted Changes: I32c12702c:[NS D04] Implement a simple speed comparison betwe... I688593cc0:[NS D03] Migrate the bad wifi avoidance policy Change-Id: I28172721d3f3af82ac79ef2c8f61df39943d997b --- core/java/android/net/NetworkScore.java | 86 ------------------------- 1 file changed, 86 deletions(-) diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java index d207e7960d..d2e59eb893 100644 --- a/core/java/android/net/NetworkScore.java +++ b/core/java/android/net/NetworkScore.java @@ -83,65 +83,6 @@ public final class NetworkScore implements Parcelable { uplinkBandwidthKBps = uplinkBandwidth; } - /** - * Evaluate whether a metrics codes for faster network is faster than another. - * - * This is a simple comparison of expected speeds. If either of the tested attributes - * are unknown, this returns zero. This implementation just assumes downlink bandwidth - * is more important than uplink bandwidth, which is more important than latency. This - * is not a very good way of evaluating network speed, but it's a start. - * TODO : do something more representative of how fast the network feels - * - * @param other the Metrics to evaluate against - * @return a negative integer, zero, or a positive integer as this metrics is worse than, - * equally good as (or unknown), or better than the passed Metrics. - * @see #compareToPreferringKnown(Metrics) - * @hide - */ - // Can't implement Comparable because this is @hide. - public int compareTo(@NonNull final Metrics other) { - if (downlinkBandwidthKBps != BANDWIDTH_UNKNOWN - && other.downlinkBandwidthKBps != BANDWIDTH_UNKNOWN) { - if (downlinkBandwidthKBps > other.downlinkBandwidthKBps) return 1; - if (downlinkBandwidthKBps < other.downlinkBandwidthKBps) return -1; - } - if (uplinkBandwidthKBps != BANDWIDTH_UNKNOWN - && other.uplinkBandwidthKBps != BANDWIDTH_UNKNOWN) { - if (uplinkBandwidthKBps > other.uplinkBandwidthKBps) return 1; - if (uplinkBandwidthKBps < other.uplinkBandwidthKBps) return -1; - } - if (latencyMs != LATENCY_UNKNOWN && other.latencyMs != LATENCY_UNKNOWN) { - // Latency : lower is better - if (latencyMs > other.latencyMs) return -1; - if (latencyMs < other.latencyMs) return 1; - } - return 0; - } - - /** - * Evaluate whether a metrics codes for faster network is faster than another. - * - * This is a simple comparison of expected speeds. If either of the tested attributes - * are unknown, this prefers the known attributes. This implementation just assumes - * downlink bandwidth is more important than uplink bandwidth, which is more important than - * latency. This is not a very good way of evaluating network speed, but it's a start. - * TODO : do something more representative of how fast the network feels - * - * @param other the Metrics to evaluate against - * @return a negative integer, zero, or a positive integer as this metrics is worse than, - * equally good as (or unknown), or better than the passed Metrics. - * @see #compareTo(Metrics) - * @hide - */ - public int compareToPreferringKnown(@NonNull final Metrics other) { - if (downlinkBandwidthKBps > other.downlinkBandwidthKBps) return 1; - if (downlinkBandwidthKBps < other.downlinkBandwidthKBps) return -1; - if (uplinkBandwidthKBps > other.uplinkBandwidthKBps) return 1; - if (uplinkBandwidthKBps < other.uplinkBandwidthKBps) return -1; - // Latency : lower is better - return -Integer.compare(latencyMs, other.latencyMs); - } - /** toString */ public String toString() { return "latency = " + latencyMs + " downlinkBandwidth = " + downlinkBandwidthKBps @@ -405,33 +346,6 @@ public final class NetworkScore implements Parcelable { return mLegacyScore; } - /** - * Use the metrics to evaluate whether a network is faster than another. - * - * This is purely based on the metrics, and explicitly ignores policy or exiting. It's - * provided to get a decision on two networks when policy can not decide, or to evaluate - * how a network is expected to compare to another if it should validate. - * - * @param other the score to evaluate against - * @return whether this network is probably faster than the other - * @hide - */ - public boolean probablyFasterThan(@NonNull final NetworkScore other) { - if (mLegacyScore > other.mLegacyScore) return true; - final int atEndToEnd = mEndToEndMetrics.compareTo(other.mEndToEndMetrics); - if (atEndToEnd > 0) return true; - if (atEndToEnd < 0) return false; - final int atLinkLayer = mLinkLayerMetrics.compareTo(other.mLinkLayerMetrics); - if (atLinkLayer > 0) return true; - if (atLinkLayer < 0) return false; - final int atEndToEndPreferringKnown = - mEndToEndMetrics.compareToPreferringKnown(other.mEndToEndMetrics); - if (atEndToEndPreferringKnown > 0) return true; - if (atEndToEndPreferringKnown < 0) return false; - // If this returns 0, neither is "probably faster" so just return false. - return mLinkLayerMetrics.compareToPreferringKnown(other.mLinkLayerMetrics) > 0; - } - /** Builder for NetworkScore. */ public static class Builder { private int mPolicy = 0; From 7b6b7ecc19ac6032850e49bfb4171ff63a7bf2f7 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 20 Feb 2020 07:39:19 +0000 Subject: [PATCH 068/229] Revert "[NS D03] Migrate the bad wifi avoidance policy" Revert submission 10338939 Reason for revert: The feature was punted out of R. Reverted Changes: I32c12702c:[NS D04] Implement a simple speed comparison betwe... I688593cc0:[NS D03] Migrate the bad wifi avoidance policy Change-Id: I640635a1ed94bed3b53466abe2a988caf0eca2b0 --- .../server/connectivity/NetworkRanker.java | 27 ++----------------- .../server/connectivity/NetworkRankerTest.kt | 2 -- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/services/core/java/com/android/server/connectivity/NetworkRanker.java index c536ab25e9..1ae7dc5c36 100644 --- a/services/core/java/com/android/server/connectivity/NetworkRanker.java +++ b/services/core/java/com/android/server/connectivity/NetworkRanker.java @@ -16,13 +16,8 @@ package com.android.server.connectivity; -import static android.net.NetworkScore.POLICY_IGNORE_ON_WIFI; - -import static com.android.internal.util.FunctionalUtils.findFirst; - import android.annotation.NonNull; import android.annotation.Nullable; -import android.net.NetworkCapabilities; import android.net.NetworkRequest; import java.util.ArrayList; @@ -42,33 +37,15 @@ public class NetworkRanker { @NonNull final Collection nais) { final ArrayList candidates = new ArrayList<>(nais); candidates.removeIf(nai -> !nai.satisfies(request)); - // Enforce policy. - filterBadWifiAvoidancePolicy(candidates); NetworkAgentInfo bestNetwork = null; int bestScore = Integer.MIN_VALUE; for (final NetworkAgentInfo nai : candidates) { - final int score = nai.getCurrentScore(); - if (score > bestScore) { + if (nai.getCurrentScore() > bestScore) { bestNetwork = nai; - bestScore = score; + bestScore = nai.getCurrentScore(); } } return bestNetwork; } - - // If some network with wifi transport is present, drop all networks with POLICY_IGNORE_ON_WIFI. - private void filterBadWifiAvoidancePolicy( - @NonNull final ArrayList candidates) { - final NetworkAgentInfo wifi = findFirst(candidates, - nai -> nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) - && nai.everValidated - // Horrible hack : there is old UI that will let a user say they want to - // override the policy only for this network only at this time and it - // feeds into the following member. This old UI should probably be removed - // but for now keep backward compatibility. - && !nai.avoidUnvalidated); - if (null == wifi) return; // No wifi : this policy doesn't apply - candidates.removeIf(nai -> nai.getNetworkScore().hasPolicy(POLICY_IGNORE_ON_WIFI)); - } } diff --git a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt index a6b371a23b..86c91165f6 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt +++ b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt @@ -16,7 +16,6 @@ package com.android.server.connectivity -import android.net.NetworkCapabilities import android.net.NetworkRequest import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 @@ -36,7 +35,6 @@ class NetworkRankerTest { private fun makeNai(satisfy: Boolean, score: Int) = mock(NetworkAgentInfo::class.java).also { doReturn(satisfy).`when`(it).satisfies(any()) doReturn(score).`when`(it).currentScore - it.networkCapabilities = NetworkCapabilities() } @Test From 1d9a206bcac2dfb3f531846aeccdfc35a5779daa Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 20 Feb 2020 07:39:31 +0000 Subject: [PATCH 069/229] Revert "[NS D02] Mix in the ignore on wifi policy." This reverts commit 7a56387e2c4d7e8c63733f2a18fb138e56668697. Reason for revert: The feature was punted out of R. Change-Id: Id9ecdac5292eeddf7c12f2330421248b0f8355a9 --- core/java/android/net/NetworkScore.java | 21 +++------- .../android/server/ConnectivityService.java | 41 +------------------ 2 files changed, 8 insertions(+), 54 deletions(-) diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java index d2e59eb893..ae17378cfc 100644 --- a/core/java/android/net/NetworkScore.java +++ b/core/java/android/net/NetworkScore.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; +import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -86,7 +87,7 @@ public final class NetworkScore implements Parcelable { /** toString */ public String toString() { return "latency = " + latencyMs + " downlinkBandwidth = " + downlinkBandwidthKBps - + " uplinkBandwidth = " + uplinkBandwidthKBps; + + "uplinkBandwidth = " + uplinkBandwidthKBps; } @NonNull @@ -353,27 +354,17 @@ public final class NetworkScore implements Parcelable { private Metrics mLinkLayerMetrics = new Metrics(Metrics.LATENCY_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN); @NonNull - private Metrics mEndToEndMetrics = new Metrics(Metrics.LATENCY_UNKNOWN, + private Metrics mEndToMetrics = new Metrics(Metrics.LATENCY_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN); private int mSignalStrength = UNKNOWN_SIGNAL_STRENGTH; private int mRange = RANGE_UNKNOWN; private boolean mExiting = false; private int mLegacyScore = 0; + @NonNull private Bundle mExtensions = new Bundle(); /** Create a new builder. */ public Builder() { } - /** @hide */ - public Builder(@NonNull final NetworkScore source) { - mPolicy = source.mPolicy; - mLinkLayerMetrics = source.mLinkLayerMetrics; - mEndToEndMetrics = source.mEndToEndMetrics; - mSignalStrength = source.mSignalStrength; - mRange = source.mRange; - mExiting = source.mExiting; - mLegacyScore = source.mLegacyScore; - } - /** Add a policy flag. */ @NonNull public Builder addPolicy(@Policy final int policy) { mPolicy |= policy; @@ -394,7 +385,7 @@ public final class NetworkScore implements Parcelable { /** Set the end-to-end metrics. */ @NonNull public Builder setEndToEndMetrics(@NonNull final Metrics endToEndMetrics) { - mEndToEndMetrics = endToEndMetrics; + mEndToMetrics = endToEndMetrics; return this; } @@ -426,7 +417,7 @@ public final class NetworkScore implements Parcelable { /** Build the NetworkScore object represented by this builder. */ @NonNull public NetworkScore build() { - return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToEndMetrics, + return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToMetrics, mSignalStrength, mRange, mExiting, mLegacyScore); } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 7dab90d5ce..60a30d3317 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3817,9 +3817,8 @@ public class ConnectivityService extends IConnectivityManager.Stub return avoidBadWifi(); } + private void rematchForAvoidBadWifiUpdate() { - ensureRunningOnConnectivityServiceThread(); - mixInAllNetworkScores(); rematchAllNetworksAndRequests(); for (NetworkAgentInfo nai: mNetworkAgentInfos.values()) { if (nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { @@ -7036,45 +7035,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - /** - * Re-mixin all network scores. - * This is called when some global setting like avoidBadWifi has changed. - * TODO : remove this when all usages have been removed. - */ - private void mixInAllNetworkScores() { - ensureRunningOnConnectivityServiceThread(); - for (final NetworkAgentInfo nai : mNetworkAgentInfos.values()) { - nai.setNetworkScore(mixInNetworkScore(nai, nai.getNetworkScore())); - } - } - - /** - * Mix in the Connectivity-managed parts of the NetworkScore. - * @param nai The NAI this score applies to. - * @param sourceScore the score sent by the network agent, or the previous score of this NAI. - * @return A new score with the Connectivity-managed parts mixed in. - */ - @NonNull - private NetworkScore mixInNetworkScore(@NonNull final NetworkAgentInfo nai, - @NonNull final NetworkScore sourceScore) { - final NetworkScore.Builder score = new NetworkScore.Builder(sourceScore); - - // TODO : this should be done in Telephony. It should be handled per-network because - // it's a carrier-dependent config. - if (nai.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) { - if (mMultinetworkPolicyTracker.getAvoidBadWifi()) { - score.clearPolicy(NetworkScore.POLICY_IGNORE_ON_WIFI); - } else { - score.addPolicy(NetworkScore.POLICY_IGNORE_ON_WIFI); - } - } - - return score.build(); - } - private void updateNetworkScore(NetworkAgentInfo nai, NetworkScore ns) { if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + ns); - nai.setNetworkScore(mixInNetworkScore(nai, ns)); + nai.setNetworkScore(ns); rematchAllNetworksAndRequests(); sendUpdatedScoreToFactories(nai); } From d15ca10d6d3bd61f9770565a649ae19dca8f3053 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 20 Feb 2020 08:41:38 +0000 Subject: [PATCH 070/229] Revert "[NS D01] Remove candidates that don't satisfy the request." This reverts commit a19115d4828d45336fae5b9e407fe55f16686696. Reason for revert: The feature was punted out of R. Change-Id: Ia91b3b3c55f735dae64ffa3194614a6f2631a087 --- .../com/android/server/connectivity/NetworkRanker.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/services/core/java/com/android/server/connectivity/NetworkRanker.java index 1ae7dc5c36..d0aabf95d5 100644 --- a/services/core/java/com/android/server/connectivity/NetworkRanker.java +++ b/services/core/java/com/android/server/connectivity/NetworkRanker.java @@ -20,7 +20,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.net.NetworkRequest; -import java.util.ArrayList; import java.util.Collection; /** @@ -32,15 +31,15 @@ public class NetworkRanker { /** * Find the best network satisfying this request among the list of passed networks. */ + // Almost equivalent to Collections.max(nais), but allows returning null if no network + // satisfies the request. @Nullable public NetworkAgentInfo getBestNetwork(@NonNull final NetworkRequest request, @NonNull final Collection nais) { - final ArrayList candidates = new ArrayList<>(nais); - candidates.removeIf(nai -> !nai.satisfies(request)); - NetworkAgentInfo bestNetwork = null; int bestScore = Integer.MIN_VALUE; - for (final NetworkAgentInfo nai : candidates) { + for (final NetworkAgentInfo nai : nais) { + if (!nai.satisfies(request)) continue; if (nai.getCurrentScore() > bestScore) { bestNetwork = nai; bestScore = nai.getCurrentScore(); From fdb872c4ed90ca21b115e0df9b5b6eb046dbc912 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 21 Feb 2020 19:37:21 +0900 Subject: [PATCH 071/229] Revert "Add public fields to NetworkScore and make it @SystemApi" This reverts commit 511f7e3792fcec295a41bf85f4722faeb8cbd166. Bug: 113554781 Test: FrameworksNetTests FrameworksTelephonyTests FrameworksWifiTests Change-Id: Ie1e84bd2a16f088307b195f924f4e49335cbe367 --- .../java/android/net/ConnectivityManager.java | 8 +- .../android/net/IConnectivityManager.aidl | 3 +- core/java/android/net/NetworkAgent.java | 50 +- core/java/android/net/NetworkScore.java | 470 +++--------------- .../android/server/ConnectivityService.java | 22 +- .../server/connectivity/NetworkAgentInfo.java | 2 +- .../android/server/NetworkAgentWrapper.java | 7 +- .../connectivity/LingerMonitorTest.java | 3 +- 8 files changed, 119 insertions(+), 446 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 62eff4522d..38ef814561 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3323,19 +3323,15 @@ public class ConnectivityManager { // of dependent changes that would conflict throughout the automerger graph. Having this // temporarily helps with the process of going through with all these dependent changes across // the entire tree. - // STOPSHIP (b/148055573) : remove this before R is released. /** * @hide * Register a NetworkAgent with ConnectivityService. * @return Network corresponding to NetworkAgent. - * @deprecated use the version that takes a NetworkScore and a provider ID. */ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) - @Deprecated public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkAgentConfig config) { - final NetworkScore ns = new NetworkScore.Builder().setLegacyScore(score).build(); - return registerNetworkAgent(messenger, ni, lp, nc, ns, config, NetworkProvider.ID_NONE); + return registerNetworkAgent(messenger, ni, lp, nc, score, config, NetworkProvider.ID_NONE); } /** @@ -3345,7 +3341,7 @@ public class ConnectivityManager { */ @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, - NetworkCapabilities nc, NetworkScore score, NetworkAgentConfig config, int providerId) { + NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) { try { return mService.registerNetworkAgent(messenger, ni, lp, nc, score, config, providerId); } catch (RemoteException e) { diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index d84d05d522..14345608e9 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -26,7 +26,6 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; -import android.net.NetworkScore; import android.net.NetworkState; import android.net.ISocketKeepaliveCallback; import android.net.ProxyInfo; @@ -164,7 +163,7 @@ interface IConnectivityManager void declareNetworkRequestUnfulfillable(in NetworkRequest request); Network registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp, - in NetworkCapabilities nc, in NetworkScore score, in NetworkAgentConfig config, + in NetworkCapabilities nc, int score, in NetworkAgentConfig config, in int factorySerialNumber); NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities, diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index ddf8dbbcb9..7cc569a42b 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -116,6 +116,13 @@ public abstract class NetworkAgent { */ public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3; + /** + * Centralize the place where base network score, and network score scaling, will be + * stored, so as we can consistently compare apple and oranges, or wifi, ethernet and LTE + * @hide + */ + public static final int WIFI_BASE_SCORE = 60; + /** * Sent by the NetworkAgent to ConnectivityService to pass the current * network score. @@ -265,13 +272,7 @@ public abstract class NetworkAgent { */ public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; - // STOPSHIP (b/148055573) : remove this before R is released. - private static NetworkScore makeNetworkScore(int score) { - return new NetworkScore.Builder().setLegacyScore(score).build(); - } - /** @hide TODO: remove and replace usage with the public constructor. */ - // STOPSHIP (b/148055573) : remove this before R is released. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score) { this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE); @@ -279,7 +280,6 @@ public abstract class NetworkAgent { } /** @hide TODO: remove and replace usage with the public constructor. */ - // STOPSHIP (b/148055573) : remove this before R is released. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) { this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE); @@ -287,7 +287,6 @@ public abstract class NetworkAgent { } /** @hide TODO: remove and replace usage with the public constructor. */ - // STOPSHIP (b/148055573) : remove this before R is released. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, int providerId) { this(looper, context, logTag, ni, nc, lp, score, null, providerId); @@ -295,12 +294,10 @@ public abstract class NetworkAgent { } /** @hide TODO: remove and replace usage with the public constructor. */ - // STOPSHIP (b/148055573) : remove this before R is released. public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, int providerId) { - this(looper, context, logTag, nc, lp, makeNetworkScore(score), config, providerId, ni, - true /* legacy */); + this(looper, context, logTag, nc, lp, score, config, providerId, ni, true /* legacy */); register(); } @@ -326,9 +323,8 @@ public abstract class NetworkAgent { * @param provider the {@link NetworkProvider} managing this agent. */ public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, - @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, - @Nullable NetworkProvider provider) { + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, + @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { this(looper, context, logTag, nc, lp, score, config, provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(), getLegacyNetworkInfo(config), false /* legacy */); @@ -338,12 +334,12 @@ public abstract class NetworkAgent { public final Context context; public final NetworkCapabilities capabilities; public final LinkProperties properties; - public final NetworkScore score; + public final int score; public final NetworkAgentConfig config; public final NetworkInfo info; InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities, - @NonNull LinkProperties properties, @NonNull NetworkScore score, - @NonNull NetworkAgentConfig config, @NonNull NetworkInfo info) { + @NonNull LinkProperties properties, int score, @NonNull NetworkAgentConfig config, + @NonNull NetworkInfo info) { this.context = context; this.capabilities = capabilities; this.properties = properties; @@ -355,7 +351,7 @@ public abstract class NetworkAgent { private volatile InitialConfiguration mInitialConfiguration; private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag, - @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, NetworkScore score, + @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni, boolean legacy) { mHandler = new NetworkAgentHandler(looper); @@ -650,8 +646,22 @@ public abstract class NetworkAgent { * Must be called by the agent to update the score of this network. * @param score the new score. */ - public void sendNetworkScore(@NonNull final NetworkScore score) { - queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, score); + public void sendNetworkScore(int score) { + if (score < 0) { + throw new IllegalArgumentException("Score must be >= 0"); + } + final NetworkScore ns = new NetworkScore(); + ns.putIntExtension(NetworkScore.LEGACY_SCORE, score); + updateScore(ns); + } + + /** + * Must be called by the agent when it has a new {@link NetworkScore} for this network. + * @param ns the new score. + * @hide TODO: unhide the NetworkScore class, and rename to sendNetworkScore. + */ + public void updateScore(@NonNull NetworkScore ns) { + queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new NetworkScore(ns)); } /** diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java index ae17378cfc..13f2994110 100644 --- a/core/java/android/net/NetworkScore.java +++ b/core/java/android/net/NetworkScore.java @@ -15,18 +15,12 @@ */ package android.net; -import android.annotation.IntDef; -import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.SystemApi; -import android.annotation.TestApi; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.Objects; /** @@ -34,392 +28,57 @@ import java.util.Objects; * * A NetworkScore object represents the characteristics of a network that affects how good the * network is considered for a particular use. - * - * This class is not thread-safe. * @hide */ -@TestApi -@SystemApi public final class NetworkScore implements Parcelable { - /** An object containing scoring-relevant metrics for a network. */ - public static class Metrics { - /** Value meaning the latency is unknown. */ - public static final int LATENCY_UNKNOWN = -1; - /** Value meaning the bandwidth is unknown. */ - public static final int BANDWIDTH_UNKNOWN = -1; - - /** - * Round-trip delay in milliseconds to the relevant destination for this Metrics object. - * - * LATENCY_UNKNOWN if unknown. - */ - @IntRange(from = LATENCY_UNKNOWN) - public final int latencyMs; - - /** - * Downlink in kB/s with the relevant destination for this Metrics object. - * - * BANDWIDTH_UNKNOWN if unknown. If directional bandwidth is unknown, up and downlink - * bandwidth can have the same value. - */ - @IntRange(from = BANDWIDTH_UNKNOWN) - public final int downlinkBandwidthKBps; - - /** - * Uplink in kB/s with the relevant destination for this Metrics object. - * - * BANDWIDTH_UNKNOWN if unknown. If directional bandwidth is unknown, up and downlink - * bandwidth can have the same value. - */ - @IntRange(from = BANDWIDTH_UNKNOWN) - public final int uplinkBandwidthKBps; - - /** Constructor */ - public Metrics(@IntRange(from = LATENCY_UNKNOWN) final int latency, - @IntRange(from = BANDWIDTH_UNKNOWN) final int downlinkBandwidth, - @IntRange(from = BANDWIDTH_UNKNOWN) final int uplinkBandwidth) { - latencyMs = latency; - downlinkBandwidthKBps = downlinkBandwidth; - uplinkBandwidthKBps = uplinkBandwidth; - } - - /** toString */ - public String toString() { - return "latency = " + latencyMs + " downlinkBandwidth = " + downlinkBandwidthKBps - + "uplinkBandwidth = " + uplinkBandwidthKBps; - } - - @NonNull - public static final Metrics EMPTY = - new Metrics(LATENCY_UNKNOWN, BANDWIDTH_UNKNOWN, BANDWIDTH_UNKNOWN); - } - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, prefix = "POLICY_", value = { - POLICY_LOCKDOWN_VPN, - POLICY_VPN, - POLICY_IGNORE_ON_WIFI, - POLICY_DEFAULT_SUBSCRIPTION - }) - public @interface Policy { - } - - /** - * This network is a VPN with lockdown enabled. - * - * If a network with this bit is present in the list of candidates and not connected, - * no network can satisfy the request. - */ - public static final int POLICY_LOCKDOWN_VPN = 1 << 0; - - /** - * This network is a VPN. - * - * If a network with this bit is present and the request UID is included in the UID ranges - * of this network, it outscores all other networks without this bit. - */ - public static final int POLICY_VPN = 1 << 1; - - /** - * This network should not be used if a previously validated WiFi network is available. - * - * If a network with this bit is present and a previously validated WiFi is present too, the - * network with this bit is outscored by it. This stays true if the WiFi network - * becomes unvalidated : this network will not be considered. - */ - public static final int POLICY_IGNORE_ON_WIFI = 1 << 2; - - /** - * This network is the default subscription for this transport. - * - * If a network with this bit is present, other networks of the same transport without this - * bit are outscored by it. A device with two active subscriptions and a setting - * to decide the default one would have this policy bit on the network for the default - * subscription so that when both are active at the same time, the device chooses the - * network associated with the default subscription rather than the one with the best link - * quality (which will happen if policy doesn't dictate otherwise). - */ - public static final int POLICY_DEFAULT_SUBSCRIPTION = 1 << 3; - - /** - * Policy bits for this network. Filled in by the NetworkAgent. - */ - private final int mPolicy; - - /** - * Predicted metrics to the gateway (it contains latency and bandwidth to the gateway). - * This is filled by the NetworkAgent with the theoretical values of the link if available, - * although they may fill it with predictions from historical data if available. - * Note that while this member cannot be null, any and all of its members can be unknown. - */ + // The key of bundle which is used to get the legacy network score of NetworkAgentInfo. + // TODO: Remove this when the transition to NetworkScore is over. + public static final String LEGACY_SCORE = "LEGACY_SCORE"; @NonNull - private final Metrics mLinkLayerMetrics; + private final Bundle mExtensions; - /** - * Predicted metrics to representative servers. - * This is filled by connectivity with (if available) a best-effort estimate of the performance - * information to servers the user connects to in similar circumstances, and predicted from - * actual measurements if possible. - * Note that while this member cannot be null, any and all of its members can be unknown. - */ - @NonNull - private final Metrics mEndToEndMetrics; + public NetworkScore() { + mExtensions = new Bundle(); + } - /** Value meaning the signal strength is unknown. */ - public static final int UNKNOWN_SIGNAL_STRENGTH = -1; - - /** The smallest meaningful signal strength. */ - public static final int MIN_SIGNAL_STRENGTH = 0; - - /** The largest meaningful signal strength. */ - public static final int MAX_SIGNAL_STRENGTH = 1000; - - /** - * User-visible measure of the strength of the signal normalized 1~1000. - * This represents a measure of the signal strength for this network. - * If unknown, this has value UNKNOWN_SIGNAL_STRENGTH. - */ - // A good way to populate this value is to fill it with the number of bars displayed in - // the system UI, scaled 0 to 1000. This is what the user sees and it makes sense to them. - // Cellular for example could quantize the ASU value (see SignalStrength#getAsuValue) into - // this, while WiFi could scale the RSSI (see WifiManager#calculateSignalLevel). - @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH) - private final int mSignalStrength; - - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = true, prefix = "RANGE_", value = { - RANGE_UNKNOWN, RANGE_CLOSE, RANGE_SHORT, RANGE_MEDIUM, RANGE_LONG - }) - public @interface Range { + public NetworkScore(@NonNull NetworkScore source) { + mExtensions = new Bundle(source.mExtensions); } /** - * The range of this network is not known. - * This can be used by VPN the range of which depends on the range of the underlying network. + * Put the value of parcelable inside the bundle by key. */ - public static final int RANGE_UNKNOWN = 0; - - /** - * This network typically only operates at close range, like an NFC beacon. - */ - public static final int RANGE_CLOSE = 1; - - /** - * This network typically operates at a range of a few meters to a few dozen meters, like WiFi. - */ - public static final int RANGE_SHORT = 2; - - /** - * This network typically operates at a range of a few dozen to a few hundred meters, like CBRS. - */ - public static final int RANGE_MEDIUM = 3; - - /** - * This network typically offers continuous connectivity up to many kilometers away, like LTE. - */ - public static final int RANGE_LONG = 4; - - /** - * The typical range of this networking technology. - * - * This is one of the RANGE_* constants and is filled by the NetworkAgent. - * This may be useful when evaluating how desirable a network is, because for two networks that - * have equivalent performance and cost, the one that won't lose IP continuity when the user - * moves is probably preferable. - * Agents should fill this with the largest typical range this technology provides. See the - * descriptions of the individual constants for guidance. - * - * If unknown, this is set to RANGE_UNKNOWN. - */ - @Range private final int mRange; - - /** - * A prediction of whether this network is likely to be unusable in a few seconds. - * - * NetworkAgents set this to true to mean they are aware that usability is limited due to - * low signal strength, congestion, or other reasons, and indicates that the system should - * only use this network as a last resort. An example would be a WiFi network when the device - * is about to move outside of range. - * - * This is filled by the NetworkAgent. Agents that don't know whether this network is likely - * to be unusable soon should set this to false. - */ - private final boolean mExiting; - - /** - * The legacy score, as a migration strategy from Q to R. - * STOPSHIP : remove this before R ships. - */ - private final int mLegacyScore; - - /** - * Create a new NetworkScore object. - */ - private NetworkScore(@Policy final int policy, @Nullable final Metrics l2Perf, - @Nullable final Metrics e2ePerf, - @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH) - final int signalStrength, - @Range final int range, final boolean exiting, final int legacyScore) { - mPolicy = policy; - mLinkLayerMetrics = null != l2Perf ? l2Perf : Metrics.EMPTY; - mEndToEndMetrics = null != e2ePerf ? e2ePerf : Metrics.EMPTY; - mSignalStrength = signalStrength; - mRange = range; - mExiting = exiting; - mLegacyScore = legacyScore; + public void putExtension(@Nullable String key, @Nullable Parcelable value) { + mExtensions.putParcelable(key, value); } /** - * Utility function to return a copy of this with a different exiting value. + * Put the value of int inside the bundle by key. */ - @NonNull public NetworkScore withExiting(final boolean exiting) { - return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToEndMetrics, - mSignalStrength, mRange, exiting, mLegacyScore); + public void putIntExtension(@Nullable String key, int value) { + mExtensions.putInt(key, value); } /** - * Utility function to return a copy of this with a different signal strength. + * Get the value of non primitive type by key. */ - @NonNull public NetworkScore withSignalStrength( - @IntRange(from = UNKNOWN_SIGNAL_STRENGTH) final int signalStrength) { - return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToEndMetrics, - signalStrength, mRange, mExiting, mLegacyScore); + public T getExtension(@Nullable String key) { + return mExtensions.getParcelable(key); } /** - * Returns whether this network has a particular policy flag. - * @param policy the policy, as one of the POLICY_* constants. + * Get the value of int by key. */ - public boolean hasPolicy(@Policy final int policy) { - return 0 != (mPolicy & policy); + public int getIntExtension(@Nullable String key) { + return mExtensions.getInt(key); } /** - * Returns the Metrics representing the performance of the link layer. - * - * This contains the theoretical performance of the link, if available. - * Note that while this function cannot return null, any and/or all of the members of the - * returned object can be null if unknown. + * Remove the entry by given key. */ - @NonNull public Metrics getLinkLayerMetrics() { - return mLinkLayerMetrics; - } - - /** - * Returns the Metrics representing the end-to-end performance of the network. - * - * This contains the end-to-end performance of the link, if available. - * Note that while this function cannot return null, any and/or all of the members of the - * returned object can be null if unknown. - */ - @NonNull public Metrics getEndToEndMetrics() { - return mEndToEndMetrics; - } - - /** - * Returns the signal strength of this network normalized 0~1000, or UNKNOWN_SIGNAL_STRENGTH. - */ - @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH) - public int getSignalStrength() { - return mSignalStrength; - } - - /** - * Returns the typical range of this network technology as one of the RANGE_* constants. - */ - @Range public int getRange() { - return mRange; - } - - /** Returns a prediction of whether this network is likely to be unusable in a few seconds. */ - public boolean isExiting() { - return mExiting; - } - - /** - * Get the legacy score. - * @hide - */ - public int getLegacyScore() { - return mLegacyScore; - } - - /** Builder for NetworkScore. */ - public static class Builder { - private int mPolicy = 0; - @NonNull - private Metrics mLinkLayerMetrics = new Metrics(Metrics.LATENCY_UNKNOWN, - Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN); - @NonNull - private Metrics mEndToMetrics = new Metrics(Metrics.LATENCY_UNKNOWN, - Metrics.BANDWIDTH_UNKNOWN, Metrics.BANDWIDTH_UNKNOWN); - private int mSignalStrength = UNKNOWN_SIGNAL_STRENGTH; - private int mRange = RANGE_UNKNOWN; - private boolean mExiting = false; - private int mLegacyScore = 0; - @NonNull private Bundle mExtensions = new Bundle(); - - /** Create a new builder. */ - public Builder() { } - - /** Add a policy flag. */ - @NonNull public Builder addPolicy(@Policy final int policy) { - mPolicy |= policy; - return this; - } - - /** Clear a policy flag */ - @NonNull public Builder clearPolicy(@Policy final int policy) { - mPolicy &= ~policy; - return this; - } - - /** Set the link layer metrics. */ - @NonNull public Builder setLinkLayerMetrics(@NonNull final Metrics linkLayerMetrics) { - mLinkLayerMetrics = linkLayerMetrics; - return this; - } - - /** Set the end-to-end metrics. */ - @NonNull public Builder setEndToEndMetrics(@NonNull final Metrics endToEndMetrics) { - mEndToMetrics = endToEndMetrics; - return this; - } - - /** Set the signal strength. */ - @NonNull public Builder setSignalStrength( - @IntRange(from = UNKNOWN_SIGNAL_STRENGTH, to = MAX_SIGNAL_STRENGTH) - final int signalStrength) { - mSignalStrength = signalStrength; - return this; - } - - /** Set the range. */ - @NonNull public Builder setRange(@Range final int range) { - mRange = range; - return this; - } - - /** Set whether this network is exiting. */ - @NonNull public Builder setExiting(final boolean exiting) { - mExiting = exiting; - return this; - } - - /** Add a parcelable extension. */ - @NonNull public Builder setLegacyScore(final int legacyScore) { - mLegacyScore = legacyScore; - return this; - } - - /** Build the NetworkScore object represented by this builder. */ - @NonNull public NetworkScore build() { - return new NetworkScore(mPolicy, mLinkLayerMetrics, mEndToMetrics, - mSignalStrength, mRange, mExiting, mLegacyScore); - } + public void removeExtension(@Nullable String key) { + mExtensions.remove(key); } @Override @@ -429,17 +88,9 @@ public final class NetworkScore implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(mPolicy); - dest.writeInt(mLinkLayerMetrics.latencyMs); - dest.writeInt(mLinkLayerMetrics.downlinkBandwidthKBps); - dest.writeInt(mLinkLayerMetrics.uplinkBandwidthKBps); - dest.writeInt(mEndToEndMetrics.latencyMs); - dest.writeInt(mEndToEndMetrics.downlinkBandwidthKBps); - dest.writeInt(mEndToEndMetrics.uplinkBandwidthKBps); - dest.writeInt(mSignalStrength); - dest.writeInt(mRange); - dest.writeBoolean(mExiting); - dest.writeInt(mLegacyScore); + synchronized (this) { + dest.writeBundle(mExtensions); + } } public static final @NonNull Creator CREATOR = new Creator() { @@ -455,52 +106,57 @@ public final class NetworkScore implements Parcelable { }; private NetworkScore(@NonNull Parcel in) { - mPolicy = in.readInt(); - mLinkLayerMetrics = new Metrics(in.readInt(), in.readInt(), in.readInt()); - mEndToEndMetrics = new Metrics(in.readInt(), in.readInt(), in.readInt()); - mSignalStrength = in.readInt(); - mRange = in.readInt(); - mExiting = in.readBoolean(); - mLegacyScore = in.readInt(); + mExtensions = in.readBundle(); } + // TODO: Modify this method once new fields are added into this class. @Override public boolean equals(@Nullable Object obj) { if (!(obj instanceof NetworkScore)) { return false; } final NetworkScore other = (NetworkScore) obj; - return mPolicy == other.mPolicy - && mLinkLayerMetrics.latencyMs == other.mLinkLayerMetrics.latencyMs - && mLinkLayerMetrics.uplinkBandwidthKBps - == other.mLinkLayerMetrics.uplinkBandwidthKBps - && mEndToEndMetrics.latencyMs == other.mEndToEndMetrics.latencyMs - && mEndToEndMetrics.uplinkBandwidthKBps - == other.mEndToEndMetrics.uplinkBandwidthKBps - && mSignalStrength == other.mSignalStrength - && mRange == other.mRange - && mExiting == other.mExiting - && mLegacyScore == other.mLegacyScore; + return bundlesEqual(mExtensions, other.mExtensions); } @Override public int hashCode() { - return Objects.hash(mPolicy, - mLinkLayerMetrics.latencyMs, mLinkLayerMetrics.uplinkBandwidthKBps, - mEndToEndMetrics.latencyMs, mEndToEndMetrics.uplinkBandwidthKBps, - mSignalStrength, mRange, mExiting, mLegacyScore); + int result = 29; + for (String key : mExtensions.keySet()) { + final Object value = mExtensions.get(key); + // The key may be null, so call Objects.hash() is safer. + result += 31 * value.hashCode() + 37 * Objects.hash(key); + } + return result; + } + + // mExtensions won't be null since the constructor will create it. + private boolean bundlesEqual(@NonNull Bundle bundle1, @NonNull Bundle bundle2) { + if (bundle1 == bundle2) { + return true; + } + + // This is unlikely but it's fine to add this clause here. + if (null == bundle1 || null == bundle2) { + return false; + } + + if (bundle1.size() != bundle2.size()) { + return false; + } + + for (String key : bundle1.keySet()) { + final Object value1 = bundle1.get(key); + final Object value2 = bundle2.get(key); + if (!Objects.equals(value1, value2)) { + return false; + } + } + return true; } /** Convert to a string */ public String toString() { - return "NetworkScore [" - + "Policy = " + mPolicy - + " LinkLayerMetrics = " + mLinkLayerMetrics - + " EndToEndMetrics = " + mEndToEndMetrics - + " SignalStrength = " + mSignalStrength - + " Range = " + mRange - + " Exiting = " + mExiting - + " LegacyScore = " + mLegacyScore - + "]"; + return "NetworkScore[" + mExtensions.toString() + "]"; } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index f84d35fb77..16dd3ada12 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5779,6 +5779,20 @@ public class ConnectivityService extends IConnectivityManager.Stub return nri.request.requestId == mDefaultRequest.requestId; } + // TODO : remove this method. It's a stopgap measure to help sheperding a number of dependent + // changes that would conflict throughout the automerger graph. Having this method temporarily + // helps with the process of going through with all these dependent changes across the entire + // tree. + /** + * Register a new agent. {@see #registerNetworkAgent} below. + */ + public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, + LinkProperties linkProperties, NetworkCapabilities networkCapabilities, + int currentScore, NetworkAgentConfig networkAgentConfig) { + return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities, + currentScore, networkAgentConfig, NetworkProvider.ID_NONE); + } + /** * Register a new agent with ConnectivityService to handle a network. * @@ -5797,7 +5811,7 @@ public class ConnectivityService extends IConnectivityManager.Stub */ public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - NetworkScore currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { + int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { enforceNetworkFactoryPermission(); LinkProperties lp = new LinkProperties(linkProperties); @@ -5805,10 +5819,12 @@ public class ConnectivityService extends IConnectivityManager.Stub // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network // satisfies mDefaultRequest. final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); + final NetworkScore ns = new NetworkScore(); + ns.putIntExtension(NetworkScore.LEGACY_SCORE, currentScore); final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc, - currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), - this, mNetd, mDnsResolver, mNMS, providerId); + ns, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), this, + mNetd, mDnsResolver, mNMS, providerId); // Make sure the network capabilities reflect what the agent info says. nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); final String extraInfo = networkInfo.getExtraInfo(); diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 4612cfd0f7..58b5cba477 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -491,7 +491,7 @@ public class NetworkAgentInfo implements Comparable { return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE; } - int score = mNetworkScore.getLegacyScore(); + int score = mNetworkScore.getIntExtension(NetworkScore.LEGACY_SCORE); if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) { score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY; } diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index 7ae9e95a52..a35fb407bc 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -40,7 +40,6 @@ import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkProvider; -import android.net.NetworkScore; import android.net.NetworkSpecifier; import android.net.SocketKeepalive; import android.net.UidRange; @@ -156,13 +155,9 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { } } - private NetworkScore makeNetworkScore(final int legacyScore) { - return new NetworkScore.Builder().setLegacyScore(legacyScore).build(); - } - public void adjustScore(int change) { mScore += change; - mNetworkAgent.sendNetworkScore(makeNetworkScore(mScore)); + mNetworkAgent.sendNetworkScore(mScore); } public int getScore() { diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index 25e9057fd1..e863266c4b 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -353,7 +353,8 @@ public class LingerMonitorTest { NetworkCapabilities caps = new NetworkCapabilities(); caps.addCapability(0); caps.addTransportType(transport); - NetworkScore ns = new NetworkScore.Builder().setLegacyScore(50).build(); + NetworkScore ns = new NetworkScore(); + ns.putIntExtension(NetworkScore.LEGACY_SCORE, 50); NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null, caps, ns, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS, NetworkProvider.ID_NONE); From 73f992fd802a39af5dc8c3fc6f06ce3290dd3b64 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Thu, 20 Feb 2020 16:42:27 +0800 Subject: [PATCH 072/229] Remove redundant connected notification Remove the old connected notification since there is a new file - NetworkStackNotifier.java which will send the connected notification when captive portal validated. Bug: 149883761 Test: 1. atest FrameworksNetTests 2. Sign-in a captive portal and see if there is a redundant connected notification. Change-Id: Id11a9b99dd04772a92af8d527104906c47bf64cd Merged-In: Id11a9b99dd04772a92af8d527104906c47bf64cd --- .../android/server/ConnectivityService.java | 40 ++--------------- .../server/connectivity/NetworkAgentInfo.java | 5 --- .../NetworkNotificationManager.java | 19 +++----- .../server/ConnectivityServiceTest.java | 5 --- .../NetworkNotificationManagerTest.java | 44 +++++-------------- 5 files changed, 21 insertions(+), 92 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 16dd3ada12..ffa3ad71c7 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -274,9 +274,6 @@ public class ConnectivityService extends IConnectivityManager.Stub // connect anyway?" dialog after the user selects a network that doesn't validate. private static final int PROMPT_UNVALIDATED_DELAY_MS = 8 * 1000; - // How long to dismiss network notification. - private static final int TIMEOUT_NOTIFICATION_DELAY_MS = 20 * 1000; - // Default to 30s linger time-out. Modifiable only for testing. private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger"; private static final int DEFAULT_LINGER_DELAY_MS = 30_000; @@ -523,11 +520,6 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private static final int EVENT_PROVISIONING_NOTIFICATION = 43; - /** - * This event can handle dismissing notification by given network id. - */ - private static final int EVENT_TIMEOUT_NOTIFICATION = 44; - /** * Used to specify whether a network should be used even if connectivity is partial. * arg1 = whether to accept the network if its connectivity is partial (1 for true or 0 for @@ -535,7 +527,7 @@ public class ConnectivityService extends IConnectivityManager.Stub * arg2 = whether to remember this choice in the future (1 for true or 0 for false) * obj = network */ - private static final int EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY = 45; + private static final int EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY = 44; /** * Event for NetworkMonitor to inform ConnectivityService that the probe status has changed. @@ -544,7 +536,7 @@ public class ConnectivityService extends IConnectivityManager.Stub * arg1 = A bitmask to describe which probes are completed. * arg2 = A bitmask to describe which probes are successful. */ - public static final int EVENT_PROBE_STATUS_CHANGED = 46; + public static final int EVENT_PROBE_STATUS_CHANGED = 45; /** * Event for NetworkMonitor to inform ConnectivityService that captive portal data has changed. @@ -552,7 +544,7 @@ public class ConnectivityService extends IConnectivityManager.Stub * arg2 = netId * obj = captive portal data */ - private static final int EVENT_CAPPORT_DATA_CHANGED = 47; + private static final int EVENT_CAPPORT_DATA_CHANGED = 46; /** * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification @@ -2879,13 +2871,6 @@ public class ConnectivityService extends IConnectivityManager.Stub final boolean valid = ((testResult & NETWORK_VALIDATION_RESULT_VALID) != 0); final boolean wasValidated = nai.lastValidated; final boolean wasDefault = isDefaultNetwork(nai); - // Only show a connected notification if the network is pending validation - // after the captive portal app was open, and it has now validated. - if (nai.captivePortalValidationPending && valid) { - // User is now logged in, network validated. - nai.captivePortalValidationPending = false; - showNetworkNotification(nai, NotificationType.LOGGED_IN); - } if (DBG) { final String logMsg = !TextUtils.isEmpty(redirectUrl) @@ -3766,12 +3751,6 @@ public class ConnectivityService extends IConnectivityManager.Stub new CaptivePortal(new CaptivePortalImpl(network).asBinder())); appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); - // This runs on a random binder thread, but getNetworkAgentInfoForNetwork is thread-safe, - // and captivePortalValidationPending is volatile. - final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai != null) { - nai.captivePortalValidationPending = true; - } Binder.withCleanCallingIdentity(() -> mContext.startActivityAsUser(appIntent, UserHandle.CURRENT)); } @@ -3890,14 +3869,6 @@ public class ConnectivityService extends IConnectivityManager.Stub final String action; final boolean highPriority; switch (type) { - case LOGGED_IN: - action = Settings.ACTION_WIFI_SETTINGS; - mHandler.removeMessages(EVENT_TIMEOUT_NOTIFICATION); - mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_TIMEOUT_NOTIFICATION, - nai.network.netId, 0), TIMEOUT_NOTIFICATION_DELAY_MS); - // High priority because it is a direct result of the user logging in to a portal. - highPriority = true; - break; case NO_INTERNET: action = ConnectivityManager.ACTION_PROMPT_UNVALIDATED; // High priority because it is only displayed for explicitly selected networks. @@ -3925,7 +3896,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } Intent intent = new Intent(action); - if (type != NotificationType.LOGGED_IN && type != NotificationType.PRIVATE_DNS_BROKEN) { + if (type != NotificationType.PRIVATE_DNS_BROKEN) { intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setClassName("com.android.settings", @@ -4141,9 +4112,6 @@ public class ConnectivityService extends IConnectivityManager.Stub case EVENT_DATA_SAVER_CHANGED: handleRestrictBackgroundChanged(toBool(msg.arg1)); break; - case EVENT_TIMEOUT_NOTIFICATION: - mNotifier.clearNotification(msg.arg1, NotificationType.LOGGED_IN); - break; } } } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 58b5cba477..3ed2a1ae23 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -161,10 +161,6 @@ public class NetworkAgentInfo implements Comparable { // Whether a captive portal was found during the last network validation attempt. public boolean lastCaptivePortalDetected; - // Indicates the captive portal app was opened to show a login UI to the user, but the network - // has not validated yet. - public volatile boolean captivePortalValidationPending; - // Set to true when partial connectivity was detected. public boolean partialConnectivity; @@ -646,7 +642,6 @@ public class NetworkAgentInfo implements Comparable { + "acceptUnvalidated{" + networkAgentConfig.acceptUnvalidated + "} " + "everCaptivePortalDetected{" + everCaptivePortalDetected + "} " + "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} " - + "captivePortalValidationPending{" + captivePortalValidationPending + "} " + "partialConnectivity{" + partialConnectivity + "} " + "acceptPartialConnectivity{" + networkAgentConfig.acceptPartialConnectivity + "} " + "clat{" + clatd + "} " diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 25c761ab80..0925de8f95 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -51,7 +51,6 @@ public class NetworkNotificationManager { LOST_INTERNET(SystemMessage.NOTE_NETWORK_LOST_INTERNET), NETWORK_SWITCH(SystemMessage.NOTE_NETWORK_SWITCH), NO_INTERNET(SystemMessage.NOTE_NETWORK_NO_INTERNET), - LOGGED_IN(SystemMessage.NOTE_NETWORK_LOGGED_IN), PARTIAL_CONNECTIVITY(SystemMessage.NOTE_NETWORK_PARTIAL_CONNECTIVITY), SIGN_IN(SystemMessage.NOTE_NETWORK_SIGN_IN), PRIVATE_DNS_BROKEN(SystemMessage.NOTE_NETWORK_PRIVATE_DNS_BROKEN); @@ -114,14 +113,10 @@ public class NetworkNotificationManager { } } - private static int getIcon(int transportType, NotificationType notifyType) { - if (transportType != TRANSPORT_WIFI) { - return R.drawable.stat_notify_rssi_in_range; - } - - return notifyType == NotificationType.LOGGED_IN - ? R.drawable.ic_wifi_signal_4 - : R.drawable.stat_notify_wifi_in_range; // TODO: Distinguish ! from ?. + private static int getIcon(int transportType) { + return (transportType == TRANSPORT_WIFI) + ? R.drawable.stat_notify_wifi_in_range : // TODO: Distinguish ! from ?. + R.drawable.stat_notify_rssi_in_range; } /** @@ -185,7 +180,7 @@ public class NetworkNotificationManager { Resources r = mContext.getResources(); final CharSequence title; final CharSequence details; - int icon = getIcon(transportType, notifyType); + int icon = getIcon(transportType); if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); @@ -235,9 +230,6 @@ public class NetworkNotificationManager { details = r.getString(R.string.network_available_sign_in_detailed, name); break; } - } else if (notifyType == NotificationType.LOGGED_IN) { - title = WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID()); - details = r.getString(R.string.captive_portal_logged_in_detailed); } else if (notifyType == NotificationType.NETWORK_SWITCH) { String fromTransport = getTransportName(transportType); String toTransport = getTransportName(approximateTransportType(switchToNai)); @@ -379,7 +371,6 @@ public class NetworkNotificationManager { case NETWORK_SWITCH: return 2; case LOST_INTERNET: - case LOGGED_IN: return 1; default: return 0; diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 4e75f2a273..497e4ed2cf 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -2751,9 +2751,6 @@ public class ConnectivityServiceTest { // Expect NET_CAPABILITY_VALIDATED onAvailable callback. validatedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent); - // Expect no notification to be shown when captive portal disappears by itself - verify(mNotificationManager, never()).notifyAsUser( - anyString(), eq(NotificationType.LOGGED_IN.eventId), any(), any()); // Break network connectivity. // Expect NET_CAPABILITY_VALIDATED onLost callback. @@ -2815,8 +2812,6 @@ public class ConnectivityServiceTest { mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid()); validatedCallback.expectAvailableCallbacksValidated(mWiFiNetworkAgent); captivePortalCallback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent); - verify(mNotificationManager, times(1)).notifyAsUser(anyString(), - eq(NotificationType.LOGGED_IN.eventId), any(), eq(UserHandle.ALL)); mCm.unregisterNetworkCallback(validatedCallback); mCm.unregisterNetworkCallback(captivePortalCallback); diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java index d57f2250fc..47db5d4316 100644 --- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java @@ -237,20 +237,6 @@ public class NetworkNotificationManagerTest { verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(SIGN_IN.eventId), any()); } - @Test - public void testSameLevelNotifications() { - final int id = 101; - final String tag = NetworkNotificationManager.tagFor(id); - - mManager.showNotification(id, LOGGED_IN, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, times(1)) - .notifyAsUser(eq(tag), eq(LOGGED_IN.eventId), any(), any()); - - mManager.showNotification(id, LOST_INTERNET, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, times(1)) - .notifyAsUser(eq(tag), eq(LOST_INTERNET.eventId), any(), any()); - } - @Test public void testClearNotificationByType() { final int id = 101; @@ -259,31 +245,25 @@ public class NetworkNotificationManagerTest { // clearNotification(int id, NotificationType notifyType) will check if given type is equal // to previous type or not. If they are equal then clear the notification; if they are not // equal then return. - - mManager.showNotification(id, LOGGED_IN, mWifiNai, mCellNai, null, false); + mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false); verify(mNotificationManager, times(1)) - .notifyAsUser(eq(tag), eq(LOGGED_IN.eventId), any(), any()); + .notifyAsUser(eq(tag), eq(NO_INTERNET.eventId), any(), any()); - // Previous notification is LOGGED_IN and given type is LOGGED_IN too. The notification + // Previous notification is NO_INTERNET and given type is NO_INTERNET too. The notification // should be cleared. - mManager.clearNotification(id, LOGGED_IN); + mManager.clearNotification(id, NO_INTERNET); verify(mNotificationManager, times(1)) - .cancelAsUser(eq(tag), eq(LOGGED_IN.eventId), any()); + .cancelAsUser(eq(tag), eq(NO_INTERNET.eventId), any()); - mManager.showNotification(id, LOGGED_IN, mWifiNai, mCellNai, null, false); - verify(mNotificationManager, times(2)) - .notifyAsUser(eq(tag), eq(LOGGED_IN.eventId), any(), any()); - - // LOST_INTERNET notification popup after LOGGED_IN notification. - mManager.showNotification(id, LOST_INTERNET, mWifiNai, mCellNai, null, false); + // SIGN_IN is popped-up. + mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false); verify(mNotificationManager, times(1)) - .notifyAsUser(eq(tag), eq(LOST_INTERNET.eventId), any(), any()); + .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any()); - // Previous notification is LOST_INTERNET and given type is LOGGED_IN. The notification - // shouldn't be cleared. - mManager.clearNotification(id, LOGGED_IN); - // LOST_INTERNET shouldn't be cleared. + // The notification type is not matching previous one, PARTIAL_CONNECTIVITY won't be + // cleared. + mManager.clearNotification(id, PARTIAL_CONNECTIVITY); verify(mNotificationManager, never()) - .cancelAsUser(eq(tag), eq(LOST_INTERNET.eventId), any()); + .cancelAsUser(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId), any()); } } From 87cdb7c771061f7d928b25add51cc98202750598 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Tue, 25 Feb 2020 00:56:07 +0000 Subject: [PATCH 073/229] test: LinkProperties: Unique Route Destinations Routes will always have unique destinations. Update tests to use unique destinations when adding multiple routes. Bug: 142892223 Test: treehugger Change-Id: I238899b0643407a1be29eb66d28728ca5d5dbc80 Merged-In: I238899b0643407a1be29eb66d28728ca5d5dbc80 (cherry picked from commit 891ea460b10c3ee3c74298dad828bd550e66b81f) --- .../java/android/net/LinkPropertiesTest.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java index f25fd4daf8..48b65e592f 100644 --- a/tests/net/common/java/android/net/LinkPropertiesTest.java +++ b/tests/net/common/java/android/net/LinkPropertiesTest.java @@ -315,7 +315,7 @@ public class LinkPropertiesTest { source.addDnsServer(DNS1); source.addDnsServer(DNS2); // set 2 gateways - source.addRoute(new RouteInfo(GATEWAY1)); + source.addRoute(new RouteInfo(LINKADDRV4, GATEWAY1)); source.addRoute(new RouteInfo(GATEWAY2)); source.setMtu(MTU); @@ -327,7 +327,7 @@ public class LinkPropertiesTest { target.addDnsServer(DNS2); target.addDnsServer(DNS1); target.addRoute(new RouteInfo(GATEWAY2)); - target.addRoute(new RouteInfo(GATEWAY1)); + target.addRoute(new RouteInfo(LINKADDRV4, GATEWAY1)); target.setMtu(MTU); assertLinkPropertiesEqual(source, target); @@ -364,12 +364,13 @@ public class LinkPropertiesTest { @Test public void testRouteInterfaces() { - LinkAddress prefix = new LinkAddress(address("2001:db8::"), 32); + LinkAddress prefix1 = new LinkAddress(address("2001:db8:1::"), 48); + LinkAddress prefix2 = new LinkAddress(address("2001:db8:2::"), 48); InetAddress address = ADDRV6; // Add a route with no interface to a LinkProperties with no interface. No errors. LinkProperties lp = new LinkProperties(); - RouteInfo r = new RouteInfo(prefix, address, null); + RouteInfo r = new RouteInfo(prefix1, address, null); assertTrue(lp.addRoute(r)); assertEquals(1, lp.getRoutes().size()); assertAllRoutesHaveInterface(null, lp); @@ -379,7 +380,7 @@ public class LinkPropertiesTest { assertEquals(1, lp.getRoutes().size()); // Add a route with an interface. Expect an exception. - r = new RouteInfo(prefix, address, "wlan0"); + r = new RouteInfo(prefix2, address, "wlan0"); try { lp.addRoute(r); fail("Adding wlan0 route to LP with no interface, expect exception"); @@ -398,7 +399,7 @@ public class LinkPropertiesTest { } catch (IllegalArgumentException expected) {} // If the interface name matches, the route is added. - r = new RouteInfo(prefix, null, "wlan0"); + r = new RouteInfo(prefix2, null, "wlan0"); lp.setInterfaceName("wlan0"); lp.addRoute(r); assertEquals(2, lp.getRoutes().size()); @@ -423,10 +424,12 @@ public class LinkPropertiesTest { assertEquals(3, lp.compareAllRoutes(lp2).added.size()); assertEquals(3, lp.compareAllRoutes(lp2).removed.size()); - // Check remove works - lp.removeRoute(new RouteInfo(prefix, address, null)); + // Remove route with incorrect interface, no route removed. + lp.removeRoute(new RouteInfo(prefix2, null, null)); assertEquals(3, lp.getRoutes().size()); - lp.removeRoute(new RouteInfo(prefix, address, "wlan0")); + + // Check remove works when interface is correct. + lp.removeRoute(new RouteInfo(prefix2, null, "wlan0")); assertEquals(2, lp.getRoutes().size()); assertAllRoutesHaveInterface("wlan0", lp); assertAllRoutesNotHaveInterface("p2p0", lp); From 13a85611f8732adb1a4c071ce410e70da8c27b23 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Thu, 27 Feb 2020 01:16:45 +0000 Subject: [PATCH 074/229] test: ConnectivityService: Validate Route Add/Del Validate route addition and deletion after linkProperties are changed. Bug: 142892223 Test: atest ConnectivityServiceTest#testStackedLinkProperties Change-Id: I18296b933e856a0f8a4c1dbd75bd35024853bfbb Merged-In: I18296b933e856a0f8a4c1dbd75bd35024853bfbb (cherry picked from commit a22a979a0caf3e3533ede410d48127084052aec5) --- .../server/ConnectivityServiceTest.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 4e75f2a273..4236b9d43e 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -5927,6 +5927,12 @@ public class ConnectivityServiceTest { final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64"); final String kNat64PrefixString = "2001:db8:64:64:64:64::"; final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96); + final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(), + MOBILE_IFNAME); + final RouteInfo hostRoute = new RouteInfo(myIpv6, null, MOBILE_IFNAME); + final RouteInfo ipv4Default = new RouteInfo(myIpv4, null, MOBILE_IFNAME); + final RouteInfo stackedDefault = new RouteInfo((IpPrefix) null, myIpv4.getAddress(), + CLAT_PREFIX + MOBILE_IFNAME); final NetworkRequest networkRequest = new NetworkRequest.Builder() .addTransportType(TRANSPORT_CELLULAR) @@ -5939,15 +5945,13 @@ public class ConnectivityServiceTest { final LinkProperties cellLp = new LinkProperties(); cellLp.setInterfaceName(MOBILE_IFNAME); cellLp.addLinkAddress(myIpv6); - cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME)); - cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME)); + cellLp.addRoute(defaultRoute); + cellLp.addRoute(hostRoute); mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); reset(mNetworkManagementService); reset(mMockDnsResolver); reset(mMockNetd); reset(mBatteryStatsService); - when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME)) - .thenReturn(getClatInterfaceConfig(myIpv4)); // Connect with ipv6 link properties. Expect prefix discovery to be started. mCellNetworkAgent.connect(true); @@ -5955,6 +5959,8 @@ public class ConnectivityServiceTest { waitForIdle(); verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt()); + verify(mNetworkManagementService, times(1)).addRoute(eq(cellNetId), eq(defaultRoute)); + verify(mNetworkManagementService, times(1)).addRoute(eq(cellNetId), eq(hostRoute)); verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId)); verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(), TYPE_MOBILE); @@ -5980,12 +5986,14 @@ public class ConnectivityServiceTest { verifyNoMoreInteractions(mMockNetd); verifyNoMoreInteractions(mMockDnsResolver); + reset(mNetworkManagementService); reset(mMockNetd); reset(mMockDnsResolver); + when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME)) + .thenReturn(getClatInterfaceConfig(myIpv4)); // Remove IPv4 address. Expect prefix discovery to be started again. cellLp.removeLinkAddress(myIpv4); - cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME)); mCellNetworkAgent.sendLinkProperties(cellLp); networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); @@ -6007,6 +6015,7 @@ public class ConnectivityServiceTest { List stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork()) .getStackedLinks(); assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0)); + verify(mNetworkManagementService).addRoute(eq(cellNetId), eq(stackedDefault)); // Change trivial linkproperties and see if stacked link is preserved. cellLp.addDnsServer(InetAddress.getByName("8.8.8.8")); @@ -6032,8 +6041,9 @@ public class ConnectivityServiceTest { // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked // linkproperties are cleaned up. cellLp.addLinkAddress(myIpv4); - cellLp.addRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME)); + cellLp.addRoute(ipv4Default); mCellNetworkAgent.sendLinkProperties(cellLp); + verify(mNetworkManagementService).addRoute(eq(cellNetId), eq(stackedDefault)); networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId); @@ -6052,8 +6062,11 @@ public class ConnectivityServiceTest { verifyNoMoreInteractions(mMockNetd); verifyNoMoreInteractions(mMockDnsResolver); + reset(mNetworkManagementService); reset(mMockNetd); reset(mMockDnsResolver); + when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME)) + .thenReturn(getClatInterfaceConfig(myIpv4)); // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone. mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */, @@ -6067,6 +6080,7 @@ public class ConnectivityServiceTest { cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8")); mCellNetworkAgent.sendLinkProperties(cellLp); networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); + verify(mNetworkManagementService, times(1)).removeRoute(eq(cellNetId), eq(ipv4Default)); verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */, kNat64PrefixString, 96); From 76eead56aae71f1f95d4d469efa2776c17fb43a3 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Sun, 8 Mar 2020 06:07:47 +0000 Subject: [PATCH 075/229] Remove the NetworkScore class. This class is useless at this point and introduces overhead. Bug: 113554781 Test: FrameworksNetTests Change-Id: Ib5f540070222865260c16c7182cc13c710a243c2 Merged-In: Ib5f540070222865260c16c7182cc13c710a243c2 (cherry picked from commit c3489ad3a6ce98218ce223cea877586781025b98) --- core/java/android/net/NetworkAgent.java | 15 +- core/java/android/net/NetworkScore.java | 162 ------------------ .../android/server/ConnectivityService.java | 16 +- .../server/connectivity/NetworkAgentInfo.java | 22 +-- .../server/ConnectivityServiceTest.java | 10 +- .../connectivity/LingerMonitorTest.java | 5 +- 6 files changed, 21 insertions(+), 209 deletions(-) delete mode 100644 core/java/android/net/NetworkScore.java diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 7cc569a42b..fef353f604 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -126,7 +126,7 @@ public abstract class NetworkAgent { /** * Sent by the NetworkAgent to ConnectivityService to pass the current * network score. - * obj = network score Integer + * arg1 = network score int * @hide */ public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4; @@ -650,18 +650,7 @@ public abstract class NetworkAgent { if (score < 0) { throw new IllegalArgumentException("Score must be >= 0"); } - final NetworkScore ns = new NetworkScore(); - ns.putIntExtension(NetworkScore.LEGACY_SCORE, score); - updateScore(ns); - } - - /** - * Must be called by the agent when it has a new {@link NetworkScore} for this network. - * @param ns the new score. - * @hide TODO: unhide the NetworkScore class, and rename to sendNetworkScore. - */ - public void updateScore(@NonNull NetworkScore ns) { - queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new NetworkScore(ns)); + queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, score, 0); } /** diff --git a/core/java/android/net/NetworkScore.java b/core/java/android/net/NetworkScore.java deleted file mode 100644 index 13f2994110..0000000000 --- a/core/java/android/net/NetworkScore.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2019 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.NonNull; -import android.annotation.Nullable; -import android.os.Bundle; -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Objects; - -/** - * Object representing the quality of a network as perceived by the user. - * - * A NetworkScore object represents the characteristics of a network that affects how good the - * network is considered for a particular use. - * @hide - */ -public final class NetworkScore implements Parcelable { - - // The key of bundle which is used to get the legacy network score of NetworkAgentInfo. - // TODO: Remove this when the transition to NetworkScore is over. - public static final String LEGACY_SCORE = "LEGACY_SCORE"; - @NonNull - private final Bundle mExtensions; - - public NetworkScore() { - mExtensions = new Bundle(); - } - - public NetworkScore(@NonNull NetworkScore source) { - mExtensions = new Bundle(source.mExtensions); - } - - /** - * Put the value of parcelable inside the bundle by key. - */ - public void putExtension(@Nullable String key, @Nullable Parcelable value) { - mExtensions.putParcelable(key, value); - } - - /** - * Put the value of int inside the bundle by key. - */ - public void putIntExtension(@Nullable String key, int value) { - mExtensions.putInt(key, value); - } - - /** - * Get the value of non primitive type by key. - */ - public T getExtension(@Nullable String key) { - return mExtensions.getParcelable(key); - } - - /** - * Get the value of int by key. - */ - public int getIntExtension(@Nullable String key) { - return mExtensions.getInt(key); - } - - /** - * Remove the entry by given key. - */ - public void removeExtension(@Nullable String key) { - mExtensions.remove(key); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - synchronized (this) { - dest.writeBundle(mExtensions); - } - } - - public static final @NonNull Creator CREATOR = new Creator() { - @Override - public NetworkScore createFromParcel(@NonNull Parcel in) { - return new NetworkScore(in); - } - - @Override - public NetworkScore[] newArray(int size) { - return new NetworkScore[size]; - } - }; - - private NetworkScore(@NonNull Parcel in) { - mExtensions = in.readBundle(); - } - - // TODO: Modify this method once new fields are added into this class. - @Override - public boolean equals(@Nullable Object obj) { - if (!(obj instanceof NetworkScore)) { - return false; - } - final NetworkScore other = (NetworkScore) obj; - return bundlesEqual(mExtensions, other.mExtensions); - } - - @Override - public int hashCode() { - int result = 29; - for (String key : mExtensions.keySet()) { - final Object value = mExtensions.get(key); - // The key may be null, so call Objects.hash() is safer. - result += 31 * value.hashCode() + 37 * Objects.hash(key); - } - return result; - } - - // mExtensions won't be null since the constructor will create it. - private boolean bundlesEqual(@NonNull Bundle bundle1, @NonNull Bundle bundle2) { - if (bundle1 == bundle2) { - return true; - } - - // This is unlikely but it's fine to add this clause here. - if (null == bundle1 || null == bundle2) { - return false; - } - - if (bundle1.size() != bundle2.size()) { - return false; - } - - for (String key : bundle1.keySet()) { - final Object value1 = bundle1.get(key); - final Object value2 = bundle2.get(key); - if (!Objects.equals(value1, value2)) { - return false; - } - } - return true; - } - - /** Convert to a string */ - public String toString() { - return "NetworkScore[" + mExtensions.toString() + "]"; - } -} diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 16dd3ada12..ff41d1cc67 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -101,7 +101,6 @@ import android.net.NetworkPolicyManager; import android.net.NetworkProvider; import android.net.NetworkQuotaInfo; import android.net.NetworkRequest; -import android.net.NetworkScore; import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkStackClient; @@ -2731,8 +2730,7 @@ public class ConnectivityService extends IConnectivityManager.Stub break; } case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: { - final NetworkScore ns = (NetworkScore) msg.obj; - updateNetworkScore(nai, ns); + updateNetworkScore(nai, msg.arg1); break; } case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: { @@ -5819,12 +5817,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network // satisfies mDefaultRequest. final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); - final NetworkScore ns = new NetworkScore(); - ns.putIntExtension(NetworkScore.LEGACY_SCORE, currentScore); final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc, - ns, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), this, - mNetd, mDnsResolver, mNMS, providerId); + currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), + this, mNetd, mDnsResolver, mNMS, providerId); // Make sure the network capabilities reflect what the agent info says. nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); final String extraInfo = networkInfo.getExtraInfo(); @@ -7082,9 +7078,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void updateNetworkScore(NetworkAgentInfo nai, NetworkScore ns) { - if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + ns); - nai.setNetworkScore(ns); + private void updateNetworkScore(@NonNull final NetworkAgentInfo nai, final int score) { + if (VDBG || DDBG) log("updateNetworkScore for " + nai.toShortString() + " to " + score); + nai.setScore(score); rematchAllNetworksAndRequests(); sendUpdatedScoreToFactories(nai); } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 58b5cba477..23b954c03c 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -32,7 +32,6 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkMonitorManager; import android.net.NetworkRequest; -import android.net.NetworkScore; import android.net.NetworkState; import android.os.Handler; import android.os.INetworkManagementService; @@ -236,10 +235,8 @@ public class NetworkAgentInfo implements Comparable { // validated). private boolean mLingering; - // This represents the characteristics of a network that affects how good the network is - // considered for a particular use. - @NonNull - private NetworkScore mNetworkScore; + // This represents the quality of the network with no clear scale. + private int mScore; // The list of NetworkRequests being satisfied by this Network. private final SparseArray mNetworkRequests = new SparseArray<>(); @@ -268,7 +265,7 @@ public class NetworkAgentInfo implements Comparable { private final Handler mHandler; public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info, - LinkProperties lp, NetworkCapabilities nc, @NonNull NetworkScore ns, Context context, + LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd, IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) { this.messenger = messenger; @@ -277,7 +274,7 @@ public class NetworkAgentInfo implements Comparable { networkInfo = info; linkProperties = lp; networkCapabilities = nc; - mNetworkScore = ns; + mScore = score; clatd = new Nat464Xlat(this, netd, dnsResolver, nms); mConnService = connService; mContext = context; @@ -491,7 +488,7 @@ public class NetworkAgentInfo implements Comparable { return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE; } - int score = mNetworkScore.getIntExtension(NetworkScore.LEGACY_SCORE); + int score = mScore; if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) { score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY; } @@ -520,13 +517,8 @@ public class NetworkAgentInfo implements Comparable { return getCurrentScore(true); } - public void setNetworkScore(@NonNull NetworkScore ns) { - mNetworkScore = ns; - } - - @NonNull - public NetworkScore getNetworkScore() { - return mNetworkScore; + public void setScore(final int score) { + mScore = score; } public NetworkState getNetworkState() { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 4e75f2a273..f876a13e41 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6715,7 +6715,7 @@ public class ConnectivityServiceTest { public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception { final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( - null, null, null, null, null, new NetworkCapabilities(), null, + null, null, null, null, null, new NetworkCapabilities(), 0, mServiceContext, null, null, mService, null, null, null, 0); mServiceContext.setPermission( @@ -6731,7 +6731,7 @@ public class ConnectivityServiceTest { public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception { final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( - null, null, null, null, null, new NetworkCapabilities(), null, + null, null, null, null, null, new NetworkCapabilities(), 0, mServiceContext, null, null, mService, null, null, null, 0); mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); @@ -6747,7 +6747,7 @@ public class ConnectivityServiceTest { public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception { final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( - null, null, null, null, null, new NetworkCapabilities(), null, + null, null, null, null, null, new NetworkCapabilities(), 0, mServiceContext, null, null, mService, null, null, null, 0); setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, @@ -6773,7 +6773,7 @@ public class ConnectivityServiceTest { nc.setAdministratorUids(Arrays.asList(Process.myUid())); final NetworkAgentInfo naiWithUid = new NetworkAgentInfo( - null, null, null, null, null, nc, null, mServiceContext, null, null, + null, null, null, null, null, nc, 0, mServiceContext, null, null, mService, null, null, null, 0); setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, @@ -6795,7 +6795,7 @@ public class ConnectivityServiceTest { nc.setAdministratorUids(Arrays.asList(Process.myUid())); final NetworkAgentInfo naiWithUid = new NetworkAgentInfo( - null, null, null, null, null, nc, null, mServiceContext, null, null, + null, null, null, null, null, nc, 0, mServiceContext, null, null, mService, null, null, null, 0); setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index e863266c4b..24a8717722 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -38,7 +38,6 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkProvider; -import android.net.NetworkScore; import android.os.INetworkManagementService; import android.text.format.DateUtils; @@ -353,10 +352,8 @@ public class LingerMonitorTest { NetworkCapabilities caps = new NetworkCapabilities(); caps.addCapability(0); caps.addTransportType(transport); - NetworkScore ns = new NetworkScore(); - ns.putIntExtension(NetworkScore.LEGACY_SCORE, 50); NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null, - caps, ns, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS, + caps, 50, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS, NetworkProvider.ID_NONE); nai.everValidated = true; return nai; From e58e7a4d858d6f628532478f0eaad586d0bb69b2 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Wed, 4 Mar 2020 04:53:17 +0000 Subject: [PATCH 076/229] Add more assertions to testStackedLinkProperties. Check all routes that are added and removed instead of just some of them. This is in preparation of an upcoming change that switches to adding and creating routes by issuing direct calls to netd. Also rename the misleading ipv4Default route variable to ipv4Subnet, which is what it actually is. Bug: 142892223 Test: test-only change Change-Id: I7d111382be215a926a7d7d4701bd3c3e94372b99 Merged-In: I7d111382be215a926a7d7d4701bd3c3e94372b99 (cherry picked from commit dcb35cb9a5d1c250e6564b6e66a4b436dd11c795) --- .../server/ConnectivityServiceTest.java | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 4236b9d43e..1efc2a5602 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -5929,8 +5929,8 @@ public class ConnectivityServiceTest { final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96); final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME); - final RouteInfo hostRoute = new RouteInfo(myIpv6, null, MOBILE_IFNAME); - final RouteInfo ipv4Default = new RouteInfo(myIpv4, null, MOBILE_IFNAME); + final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME); + final RouteInfo ipv4Subnet = new RouteInfo(myIpv4, null, MOBILE_IFNAME); final RouteInfo stackedDefault = new RouteInfo((IpPrefix) null, myIpv4.getAddress(), CLAT_PREFIX + MOBILE_IFNAME); @@ -5946,7 +5946,7 @@ public class ConnectivityServiceTest { cellLp.setInterfaceName(MOBILE_IFNAME); cellLp.addLinkAddress(myIpv6); cellLp.addRoute(defaultRoute); - cellLp.addRoute(hostRoute); + cellLp.addRoute(ipv6Subnet); mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp); reset(mNetworkManagementService); reset(mMockDnsResolver); @@ -5959,8 +5959,7 @@ public class ConnectivityServiceTest { waitForIdle(); verify(mMockNetd, times(1)).networkCreatePhysical(eq(cellNetId), anyInt()); - verify(mNetworkManagementService, times(1)).addRoute(eq(cellNetId), eq(defaultRoute)); - verify(mNetworkManagementService, times(1)).addRoute(eq(cellNetId), eq(hostRoute)); + assertRoutesAdded(cellNetId, ipv6Subnet, defaultRoute); verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId)); verify(mBatteryStatsService).noteNetworkInterfaceType(cellLp.getInterfaceName(), TYPE_MOBILE); @@ -5976,6 +5975,7 @@ public class ConnectivityServiceTest { cellLp.addLinkAddress(myIpv4); mCellNetworkAgent.sendLinkProperties(cellLp); networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); + assertRoutesAdded(cellNetId, ipv4Subnet); verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId); verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any()); @@ -5997,6 +5997,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(cellLp); networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); + assertRoutesRemoved(cellNetId, ipv4Subnet); // When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started. Nat464Xlat clat = getNat464Xlat(mCellNetworkAgent); @@ -6015,7 +6016,7 @@ public class ConnectivityServiceTest { List stackedLps = mCm.getLinkProperties(mCellNetworkAgent.getNetwork()) .getStackedLinks(); assertEquals(makeClatLinkProperties(myIpv4), stackedLps.get(0)); - verify(mNetworkManagementService).addRoute(eq(cellNetId), eq(stackedDefault)); + assertRoutesAdded(cellNetId, stackedDefault); // Change trivial linkproperties and see if stacked link is preserved. cellLp.addDnsServer(InetAddress.getByName("8.8.8.8")); @@ -6041,10 +6042,10 @@ public class ConnectivityServiceTest { // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked // linkproperties are cleaned up. cellLp.addLinkAddress(myIpv4); - cellLp.addRoute(ipv4Default); + cellLp.addRoute(ipv4Subnet); mCellNetworkAgent.sendLinkProperties(cellLp); - verify(mNetworkManagementService).addRoute(eq(cellNetId), eq(stackedDefault)); networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); + assertRoutesAdded(cellNetId, ipv4Subnet); verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId); @@ -6055,6 +6056,7 @@ public class ConnectivityServiceTest { expected.setNat64Prefix(kNat64Prefix); assertEquals(expected, actualLpAfterIpv4); assertEquals(0, actualLpAfterIpv4.getStackedLinks().size()); + assertRoutesRemoved(cellNetId, stackedDefault); // The interface removed callback happens but has no effect after stop is called. clat.interfaceRemoved(CLAT_PREFIX + MOBILE_IFNAME); @@ -6080,7 +6082,7 @@ public class ConnectivityServiceTest { cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8")); mCellNetworkAgent.sendLinkProperties(cellLp); networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); - verify(mNetworkManagementService, times(1)).removeRoute(eq(cellNetId), eq(ipv4Default)); + assertRoutesRemoved(cellNetId, ipv4Subnet); // Directly-connected routes auto-added. verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId); mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */, kNat64PrefixString, 96); @@ -6092,15 +6094,20 @@ public class ConnectivityServiceTest { clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true); networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, (lp) -> lp.getStackedLinks().size() == 1 && lp.getNat64Prefix() != null); + assertRoutesAdded(cellNetId, stackedDefault); // NAT64 prefix is removed. Expect that clat is stopped. mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */, kNat64PrefixString, 96); networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, (lp) -> lp.getStackedLinks().size() == 0 && lp.getNat64Prefix() == null); + assertRoutesRemoved(cellNetId, ipv4Subnet, stackedDefault); + + // Stop has no effect because clat is already stopped. verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, (lp) -> lp.getStackedLinks().size() == 0); + verifyNoMoreInteractions(mMockNetd); // Clean up. mCellNetworkAgent.disconnect(); @@ -6668,6 +6675,20 @@ public class ConnectivityServiceTest { } } + private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception { + InOrder inOrder = inOrder(mNetworkManagementService); + for (int i = 0; i < routes.length; i++) { + inOrder.verify(mNetworkManagementService).addRoute(eq(netId), eq(routes[i])); + } + } + + private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception { + InOrder inOrder = inOrder(mNetworkManagementService); + for (int i = 0; i < routes.length; i++) { + inOrder.verify(mNetworkManagementService).removeRoute(eq(netId), eq(routes[i])); + } + } + @Test public void testRegisterUnregisterConnectivityDiagnosticsCallback() throws Exception { final NetworkRequest wifiRequest = From de03bda1c38f5efeef1fcc905cc98dacd8e72eda Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Fri, 6 Mar 2020 00:38:43 +0000 Subject: [PATCH 077/229] Remove polling of TetheringManager in ConnectivityManager. Test: manual Bug: 144742179 Merged-In: I7d88b38eb3d741534e980b7d1e226a411b71fae2 (cherry picked from commit f8a55a19faa938b4e58310f9a90926276b7936ea) Change-Id: I5cc4231bfb9a0709d677acbb317ee98af31bd041 --- .../java/android/net/ConnectivityManager.java | 60 ++++++------------- 1 file changed, 19 insertions(+), 41 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 38ef814561..fc6954fb48 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -53,7 +53,6 @@ import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.ServiceSpecificException; -import android.os.SystemClock; import android.provider.Settings; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -808,7 +807,7 @@ public class ConnectivityManager { private INetworkManagementService mNMService; private INetworkPolicyManager mNPManager; - private TetheringManager mTetheringManager; + private final TetheringManager mTetheringManager; /** * Tests if a given integer represents a valid network type. @@ -2274,6 +2273,7 @@ public class ConnectivityManager { public ConnectivityManager(Context context, IConnectivityManager service) { mContext = Preconditions.checkNotNull(context, "missing context"); mService = Preconditions.checkNotNull(service, "missing IConnectivityManager"); + mTetheringManager = (TetheringManager) mContext.getSystemService(Context.TETHERING_SERVICE); sInstance = this; } @@ -2347,28 +2347,6 @@ public class ConnectivityManager { return getInstanceOrNull(); } - private static final int TETHERING_TIMEOUT_MS = 60_000; - private final Object mTetheringLock = new Object(); - - private TetheringManager getTetheringManager() { - synchronized (mTetheringLock) { - if (mTetheringManager != null) { - return mTetheringManager; - } - final long before = System.currentTimeMillis(); - while ((mTetheringManager = (TetheringManager) mContext.getSystemService( - Context.TETHERING_SERVICE)) == null) { - if (System.currentTimeMillis() - before > TETHERING_TIMEOUT_MS) { - Log.e(TAG, "Timeout waiting tethering service not ready yet"); - throw new IllegalStateException("No tethering service yet"); - } - SystemClock.sleep(100); - } - - return mTetheringManager; - } - } - /** * Get the set of tetherable, available interfaces. This list is limited by * device configuration and current interface existence. @@ -2382,7 +2360,7 @@ public class ConnectivityManager { @UnsupportedAppUsage @Deprecated public String[] getTetherableIfaces() { - return getTetheringManager().getTetherableIfaces(); + return mTetheringManager.getTetherableIfaces(); } /** @@ -2397,7 +2375,7 @@ public class ConnectivityManager { @UnsupportedAppUsage @Deprecated public String[] getTetheredIfaces() { - return getTetheringManager().getTetheredIfaces(); + return mTetheringManager.getTetheredIfaces(); } /** @@ -2418,7 +2396,7 @@ public class ConnectivityManager { @UnsupportedAppUsage @Deprecated public String[] getTetheringErroredIfaces() { - return getTetheringManager().getTetheringErroredIfaces(); + return mTetheringManager.getTetheringErroredIfaces(); } /** @@ -2462,7 +2440,7 @@ public class ConnectivityManager { @UnsupportedAppUsage @Deprecated public int tether(String iface) { - return getTetheringManager().tether(iface); + return mTetheringManager.tether(iface); } /** @@ -2486,7 +2464,7 @@ public class ConnectivityManager { @UnsupportedAppUsage @Deprecated public int untether(String iface) { - return getTetheringManager().untether(iface); + return mTetheringManager.untether(iface); } /** @@ -2512,7 +2490,7 @@ public class ConnectivityManager { @RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported() { - return getTetheringManager().isTetheringSupported(); + return mTetheringManager.isTetheringSupported(); } /** @@ -2605,7 +2583,7 @@ public class ConnectivityManager { final TetheringRequest request = new TetheringRequest.Builder(type) .setSilentProvisioning(!showProvisioningUi).build(); - getTetheringManager().startTethering(request, executor, tetheringCallback); + mTetheringManager.startTethering(request, executor, tetheringCallback); } /** @@ -2624,7 +2602,7 @@ public class ConnectivityManager { @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int type) { - getTetheringManager().stopTethering(type); + mTetheringManager.stopTethering(type); } /** @@ -2682,7 +2660,7 @@ public class ConnectivityManager { synchronized (mTetheringEventCallbacks) { mTetheringEventCallbacks.put(callback, tetherCallback); - getTetheringManager().registerTetheringEventCallback(executor, tetherCallback); + mTetheringManager.registerTetheringEventCallback(executor, tetherCallback); } } @@ -2704,7 +2682,7 @@ public class ConnectivityManager { synchronized (mTetheringEventCallbacks) { final TetheringEventCallback tetherCallback = mTetheringEventCallbacks.remove(callback); - getTetheringManager().unregisterTetheringEventCallback(tetherCallback); + mTetheringManager.unregisterTetheringEventCallback(tetherCallback); } } @@ -2724,7 +2702,7 @@ public class ConnectivityManager { @UnsupportedAppUsage @Deprecated public String[] getTetherableUsbRegexs() { - return getTetheringManager().getTetherableUsbRegexs(); + return mTetheringManager.getTetherableUsbRegexs(); } /** @@ -2742,7 +2720,7 @@ public class ConnectivityManager { @UnsupportedAppUsage @Deprecated public String[] getTetherableWifiRegexs() { - return getTetheringManager().getTetherableWifiRegexs(); + return mTetheringManager.getTetherableWifiRegexs(); } /** @@ -2761,7 +2739,7 @@ public class ConnectivityManager { @UnsupportedAppUsage @Deprecated public String[] getTetherableBluetoothRegexs() { - return getTetheringManager().getTetherableBluetoothRegexs(); + return mTetheringManager.getTetherableBluetoothRegexs(); } /** @@ -2785,7 +2763,7 @@ public class ConnectivityManager { @UnsupportedAppUsage @Deprecated public int setUsbTethering(boolean enable) { - return getTetheringManager().setUsbTethering(enable); + return mTetheringManager.setUsbTethering(enable); } /** @@ -2902,7 +2880,7 @@ public class ConnectivityManager { @UnsupportedAppUsage @Deprecated public int getLastTetherError(String iface) { - return getTetheringManager().getLastTetherError(iface); + return mTetheringManager.getLastTetherError(iface); } /** @hide */ @@ -2973,7 +2951,7 @@ public class ConnectivityManager { } }; - getTetheringManager().requestLatestTetheringEntitlementResult(type, wrappedListener, + mTetheringManager.requestLatestTetheringEntitlementResult(type, wrappedListener, showEntitlementUi); } @@ -4469,7 +4447,7 @@ public class ConnectivityManager { public void factoryReset() { try { mService.factoryReset(); - getTetheringManager().stopAllTethering(); + mTetheringManager.stopAllTethering(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } From 78d504da06c83e93f40887d5b74f129079d83157 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Mon, 9 Mar 2020 05:22:45 +0000 Subject: [PATCH 078/229] Ignore NetworkAgentConfigTest on Q NetworkAgentConfig did not exist on Q. Test: atest CtsNetTestCasesLatestSdk:android.net.NetworkAgentConfigTest on Q and R devices Bug: 150918852 Merged-In: I5414d7767c39327ff41673ff13ccd34982e10742 (cherry picked from commit d7fedf26d03759cb26a19a6558cf39189b66a681) Change-Id: I868398148d80afb73659df4d7312f1c2e245ead9 --- .../common/java/android/net/NetworkAgentConfigTest.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt index d250ad3a2b..173dbd1271 100644 --- a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt +++ b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt @@ -16,16 +16,23 @@ package android.net +import android.os.Build import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 +import com.android.testutils.DevSdkIgnoreRule +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.assertParcelSane +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) @SmallTest class NetworkAgentConfigTest { - @Test + @Rule @JvmField + val ignoreRule = DevSdkIgnoreRule() + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) fun testParcelNetworkAgentConfig() { val config = NetworkAgentConfig.Builder().apply { setExplicitlySelected(true) From 890f021f5abc279d24810ee0ee23dfeb9d22931c Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Mon, 9 Mar 2020 05:22:31 +0000 Subject: [PATCH 079/229] Skip LinkAddress tests that are R-specific on Q Address lifetime was added in R so tests for it should not be run on Q. Test: CtsNetTestCasesLatestSdk:android.net.LinkAddressTest on both devices Bug: 150918852 Merged-In: I98b14727eabcf569829eee8df34afc057eba6f93 (cherry picked from commit 4e00259d220590acf781382de0542cbae75ec16f) Change-Id: I9599afa8ae64bb13c93d5f26ebedf3f8dedff6d9 --- .../java/android/net/LinkAddressTest.java | 46 +++++++++++++++---- 1 file changed, 37 insertions(+), 9 deletions(-) diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java index 06c6301d66..99dac1439b 100644 --- a/tests/net/common/java/android/net/LinkAddressTest.java +++ b/tests/net/common/java/android/net/LinkAddressTest.java @@ -28,8 +28,8 @@ import static android.system.OsConstants.RT_SCOPE_SITE; import static android.system.OsConstants.RT_SCOPE_UNIVERSE; import static com.android.testutils.MiscAssertsKt.assertEqualBothWays; +import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals; import static com.android.testutils.MiscAssertsKt.assertNotEqualEitherWay; -import static com.android.testutils.ParcelUtilsKt.assertParcelSane; import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless; import static org.junit.Assert.assertEquals; @@ -38,11 +38,17 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.os.Build; import android.os.SystemClock; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.testutils.DevSdkIgnoreRule; +import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; + +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -57,6 +63,8 @@ import java.util.List; @RunWith(AndroidJUnit4.class) @SmallTest public class LinkAddressTest { + @Rule + public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); private static final String V4 = "192.0.2.1"; private static final String V6 = "2001:db8::1"; @@ -318,15 +326,29 @@ public class LinkAddressTest { l = new LinkAddress(V6_ADDRESS, 64, 123, 456); assertParcelingIsLossless(l); - l = new LinkAddress(V6_ADDRESS, 64, 123, 456, - 1L, 3600000L); - assertParcelingIsLossless(l); l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK); - assertParcelSane(l, 6); + assertParcelingIsLossless(l); } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testLifetimeParceling() { + final LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, 456, 1L, 3600000L); + assertParcelingIsLossless(l); + } + + @Test @IgnoreAfter(Build.VERSION_CODES.Q) + public void testFieldCount_Q() { + assertFieldCountEquals(4, LinkAddress.class); + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testFieldCount() { + // Make sure any new field is covered by the above parceling tests when changing this number + assertFieldCountEquals(6, LinkAddress.class); + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testDeprecationTime() { try { new LinkAddress(V6_ADDRESS, 64, 0, 456, @@ -347,7 +369,7 @@ public class LinkAddressTest { } catch (IllegalArgumentException expected) { } } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testExpirationTime() { try { new LinkAddress(V6_ADDRESS, 64, 0, 456, @@ -366,10 +388,13 @@ public class LinkAddressTest { public void testGetFlags() { LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, RT_SCOPE_HOST); assertEquals(123, l.getFlags()); + } + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testGetFlags_Deprecation() { // Test if deprecated bit was added/remove automatically based on the provided deprecation // time - l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST, + LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST, 1L, LinkAddress.LIFETIME_PERMANENT); // Check if the flag is added automatically. assertTrue((l.getFlags() & IFA_F_DEPRECATED) != 0); @@ -458,8 +483,11 @@ public class LinkAddressTest { (IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC), RT_SCOPE_UNIVERSE); assertGlobalPreferred(l, "v6,global,tempaddr+optimistic"); + } - l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testIsGlobalPreferred_DeprecatedInFuture() { + final LinkAddress l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_UNIVERSE, SystemClock.elapsedRealtime() + 100000, SystemClock.elapsedRealtime() + 200000); // Although the deprecated bit is set, but the deprecation time is in the future, test From d7e80c1f34659cf211b03d679b0a9e0b4c7943f2 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Mon, 9 Mar 2020 05:21:49 +0000 Subject: [PATCH 080/229] Ignore testReevaluateNetwork until Q The method did not exist until Q, so the test is not relevant on such devices. Test: atest CtsNetTestCasesLatestSdk:android.net.CaptivePortalTest on Q and R devices Bug: 150918852 Merged-In: I913b6eaa61bfd4f1964b324dcb4dd272aa8cc583 (cherry picked from commit 4d166d7bd95d9582335aafaa03fb242206449054) Change-Id: I2ddeee53d4ef63f01b791e3e95161194e29d3978 --- tests/net/common/java/android/net/CaptivePortalTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/net/common/java/android/net/CaptivePortalTest.java b/tests/net/common/java/android/net/CaptivePortalTest.java index ca4ba63142..7a60cc105a 100644 --- a/tests/net/common/java/android/net/CaptivePortalTest.java +++ b/tests/net/common/java/android/net/CaptivePortalTest.java @@ -18,19 +18,26 @@ package android.net; import static org.junit.Assert.assertEquals; +import android.os.Build; import android.os.RemoteException; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; +import com.android.testutils.DevSdkIgnoreRule; +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest public class CaptivePortalTest { + @Rule + public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); + private static final int DEFAULT_TIMEOUT_MS = 5000; private static final String TEST_PACKAGE_NAME = "com.google.android.test"; @@ -84,6 +91,7 @@ public class CaptivePortalTest { assertEquals(result.mCode, CaptivePortal.APP_RETURN_WANTED_AS_IS); } + @IgnoreUpTo(Build.VERSION_CODES.Q) @Test public void testReevaluateNetwork() { final MyCaptivePortalImpl result = runCaptivePortalTest(c -> c.reevaluateNetwork()); From 911106c17c7df914d7f70f3326c7415873e75278 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Wed, 4 Mar 2020 13:36:11 +0000 Subject: [PATCH 081/229] Merge NetworkStatsService handler changes. ===== Remove the need of accessing handler in NSS unit test Currently, to wait for handler becomes idle, specific message is used and the test would wait for condition variable to be open when the message is processed. However, this is already done in the HandlerUtils. Thus, there is no need to post such message manually in the handler. Test: atest FrameworksNetTests Bug: 150664039 Change-Id: Iab32b2dbab01634ca159dcb90fc9f929d1fed1a2 ===== Remove setHandler in NetworkStatsService Currently, internal handler is set by setHandler after constructing NSS object. This was introduced in ag/866187 to access the handler in the unit test. However, the design put NSS in a bad situation where all classes that need handler or executor could not be final and need to be dynamically allocated in order to get a valid handler. Thus, since the usage of handler is removed in previous patch, this change eliminate setHandler by initializing the handler in the constructor. Test: atest FrameworksNetTests Bug: 150664039 Change-Id: I794a24d00b0ca9fdc78091e7b9ab7307e0f034b7 ===== Bug: 150664039 Change-Id: If256ed4437ddcbcc72a6f766cff2f4cc512ee3f7 Merged-In: If256ed4437ddcbcc72a6f766cff2f4cc512ee3f7 (cherry picked from commit 2a6439d7e2a3926e10a0b9a4dc730b1a022d8138) --- .../server/net/NetworkStatsServiceTest.java | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index a9e0b9abba..36deca3e37 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -64,6 +64,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.annotation.NonNull; import android.app.AlarmManager; import android.app.usage.NetworkStatsManager; import android.content.Context; @@ -163,7 +164,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { private @Mock IBinder mBinder; private @Mock AlarmManager mAlarmManager; private HandlerThread mHandlerThread; - private Handler mHandler; private NetworkStatsService mService; private INetworkStatsSession mSession; @@ -192,15 +192,11 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); - mService = new NetworkStatsService( - mServiceContext, mNetManager, mAlarmManager, wakeLock, mClock, - mServiceContext.getSystemService(TelephonyManager.class), mSettings, - mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir)); mHandlerThread = new HandlerThread("HandlerThread"); - mHandlerThread.start(); - Handler.Callback callback = new NetworkStatsService.HandlerCallback(mService); - mHandler = new Handler(mHandlerThread.getLooper(), callback); - mService.setHandler(mHandler, callback); + final NetworkStatsService.Dependencies deps = makeDependencies(); + mService = new NetworkStatsService(mServiceContext, mNetManager, mAlarmManager, wakeLock, + mClock, mServiceContext.getSystemService(TelephonyManager.class), mSettings, + mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir), deps); mElapsedRealtime = 0L; @@ -217,11 +213,21 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // catch INetworkManagementEventObserver during systemReady() ArgumentCaptor networkObserver = - ArgumentCaptor.forClass(INetworkManagementEventObserver.class); + ArgumentCaptor.forClass(INetworkManagementEventObserver.class); verify(mNetManager).registerObserver(networkObserver.capture()); mNetworkObserver = networkObserver.getValue(); } + @NonNull + private NetworkStatsService.Dependencies makeDependencies() { + return new NetworkStatsService.Dependencies() { + @Override + public HandlerThread makeHandlerThread() { + return mHandlerThread; + } + }; + } + @After public void tearDown() throws Exception { IoUtils.deleteContents(mStatsDir); @@ -234,6 +240,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mSession.close(); mService = null; + + mHandlerThread.quitSafely(); } @Test @@ -939,9 +947,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { long minThresholdInBytes = 2 * 1024 * 1024; // 2 MB assertEquals(minThresholdInBytes, request.thresholdInBytes); - // Send dummy message to make sure that any previous message has been handled - mHandler.sendMessage(mHandler.obtainMessage(-1)); - HandlerUtilsKt.waitForIdle(mHandler, WAIT_TIMEOUT); + HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT); // Make sure that the caller binder gets connected verify(mBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt()); @@ -1077,7 +1083,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // Simulates alert quota of the provider has been reached. cb.onAlertReached(); - HandlerUtilsKt.waitForIdle(mHandler, WAIT_TIMEOUT); + HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT); // Verifies that polling is triggered by alert reached. provider.expectStatsUpdate(0 /* unused */); @@ -1294,9 +1300,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { private void forcePollAndWaitForIdle() { mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); - // Send dummy message to make sure that any previous message has been handled - mHandler.sendMessage(mHandler.obtainMessage(-1)); - HandlerUtilsKt.waitForIdle(mHandler, WAIT_TIMEOUT); + HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT); } static class LatchedHandler extends Handler { From 5f3c53a268556bd4d8252b40b328f8cd2c26c5e1 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Tue, 11 Feb 2020 10:03:26 -0800 Subject: [PATCH 082/229] Clear UIDs when sharing NetworkCapabilties for ConnectivityDiagnostics. ConnectivityDiagnostics shares NetworkCapabilities in ConnectivityReports and DataStallReports. These NetworkCapabilities need to have their UIDs scrubbed before they are shared with callbacks. Bug: 148942124 Test: atest FrameworksNetTests Change-Id: I5bde5a8116f7e36b8f4de49adf4cab8ec45a5aa4 Merged-In: I5bde5a8116f7e36b8f4de49adf4cab8ec45a5aa4 (cherry picked from commit 3de243265558fb5505b4daabe715a5090104450f) --- .../android/server/ConnectivityService.java | 16 +++++++++++++-- .../server/ConnectivityServiceTest.java | 20 ++++++++++++++----- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index ff41d1cc67..6e0f52063a 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -7835,12 +7835,15 @@ public class ConnectivityService extends IConnectivityManager.Stub private void handleNetworkTestedWithExtras( @NonNull ConnectivityReportEvent reportEvent, @NonNull PersistableBundle extras) { final NetworkAgentInfo nai = reportEvent.mNai; + final NetworkCapabilities networkCapabilities = + new NetworkCapabilities(nai.networkCapabilities); + clearNetworkCapabilitiesUids(networkCapabilities); final ConnectivityReport report = new ConnectivityReport( reportEvent.mNai.network, reportEvent.mTimestampMillis, nai.linkProperties, - nai.networkCapabilities, + networkCapabilities, extras); final List results = getMatchingPermissionedCallbacks(nai); @@ -7856,13 +7859,16 @@ public class ConnectivityService extends IConnectivityManager.Stub private void handleDataStallSuspected( @NonNull NetworkAgentInfo nai, long timestampMillis, int detectionMethod, @NonNull PersistableBundle extras) { + final NetworkCapabilities networkCapabilities = + new NetworkCapabilities(nai.networkCapabilities); + clearNetworkCapabilitiesUids(networkCapabilities); final DataStallReport report = new DataStallReport( nai.network, timestampMillis, detectionMethod, nai.linkProperties, - nai.networkCapabilities, + networkCapabilities, extras); final List results = getMatchingPermissionedCallbacks(nai); @@ -7888,6 +7894,12 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private void clearNetworkCapabilitiesUids(@NonNull NetworkCapabilities nc) { + nc.setUids(null); + nc.setAdministratorUids(Collections.EMPTY_LIST); + nc.setOwnerUid(Process.INVALID_UID); + } + private List getMatchingPermissionedCallbacks( @NonNull NetworkAgentInfo nai) { final List results = new ArrayList<>(); diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index c2c3ba3e8b..c1999dba69 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -23,8 +23,6 @@ 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; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport; -import static android.net.ConnectivityDiagnosticsManager.DataStallReport; import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL; @@ -100,6 +98,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.startsWith; import static org.mockito.Matchers.anyInt; @@ -6875,8 +6874,13 @@ public class ConnectivityServiceTest { HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); // Verify onConnectivityReport fired - verify(mConnectivityDiagnosticsCallback) - .onConnectivityReport(any(ConnectivityReport.class)); + verify(mConnectivityDiagnosticsCallback).onConnectivityReport( + argThat(report -> { + final NetworkCapabilities nc = report.getNetworkCapabilities(); + return nc.getUids() == null + && nc.getAdministratorUids().isEmpty() + && nc.getOwnerUid() == Process.INVALID_UID; + })); } @Test @@ -6891,7 +6895,13 @@ public class ConnectivityServiceTest { HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); // Verify onDataStallSuspected fired - verify(mConnectivityDiagnosticsCallback).onDataStallSuspected(any(DataStallReport.class)); + verify(mConnectivityDiagnosticsCallback).onDataStallSuspected( + argThat(report -> { + final NetworkCapabilities nc = report.getNetworkCapabilities(); + return nc.getUids() == null + && nc.getAdministratorUids().isEmpty() + && nc.getOwnerUid() == Process.INVALID_UID; + })); } @Test From 6617c9be421abd47a51f88b6ccbb56c015c2ffed Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Wed, 4 Mar 2020 18:04:01 +0000 Subject: [PATCH 083/229] Accept MAINLINE_NETWORK_STACK permission on register/unregister network provider Registering/Unregistering network provider needs NETWORK_FACTORY which is signature only permission. But mainline modules can't grant this permission because it's not signed with platform key. Hence, these APIs should also accept MAINLINE_NETWORK_STACK permission that allow mainline module to register/unregister network provider. Bug: 150733435 Test: atest FrameworksNetTests Change-Id: Id22113aa0db01244817b4b008f5573c5e7b317f0 Merged-In: Id22113aa0db01244817b4b008f5573c5e7b317f0 (cherry picked from aosp/1248727) --- .../java/android/net/ConnectivityManager.java | 28 ++++++++++++++----- .../android/server/ConnectivityService.java | 4 +-- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index fc6954fb48..81735ac8f6 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3222,7 +3222,9 @@ public class ConnectivityManager { /** {@hide} - returns the factory serial number */ @UnsupportedAppUsage - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) public int registerNetworkFactory(Messenger messenger, String name) { try { return mService.registerNetworkFactory(messenger, name); @@ -3233,7 +3235,9 @@ public class ConnectivityManager { /** {@hide} */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) public void unregisterNetworkFactory(Messenger messenger) { try { mService.unregisterNetworkFactory(messenger); @@ -3253,7 +3257,9 @@ public class ConnectivityManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) public int registerNetworkProvider(@NonNull NetworkProvider provider) { if (provider.getProviderId() != NetworkProvider.ID_NONE) { throw new IllegalStateException("NetworkProviders can only be registered once"); @@ -3276,7 +3282,9 @@ public class ConnectivityManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) public void unregisterNetworkProvider(@NonNull NetworkProvider provider) { try { mService.unregisterNetworkProvider(provider.getMessenger()); @@ -3288,7 +3296,9 @@ public class ConnectivityManager { /** @hide exposed via the NetworkProvider class. */ - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) { try { mService.declareNetworkRequestUnfulfillable(request); @@ -3306,7 +3316,9 @@ public class ConnectivityManager { * Register a NetworkAgent with ConnectivityService. * @return Network corresponding to NetworkAgent. */ - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkAgentConfig config) { return registerNetworkAgent(messenger, ni, lp, nc, score, config, NetworkProvider.ID_NONE); @@ -3317,7 +3329,9 @@ public class ConnectivityManager { * Register a NetworkAgent with ConnectivityService. * @return Network corresponding to NetworkAgent. */ - @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + @RequiresPermission(anyOf = { + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_FACTORY}) public Network registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp, NetworkCapabilities nc, int score, NetworkAgentConfig config, int providerId) { try { diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 7287a44600..8cb8baf9ac 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2083,9 +2083,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void enforceNetworkFactoryPermission() { - mContext.enforceCallingOrSelfPermission( + enforceAnyPermissionOf( android.Manifest.permission.NETWORK_FACTORY, - "ConnectivityService"); + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } private boolean checkSettingsPermission() { From f78e440b277d314ba36f8c7a78cd88e2a6caa240 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Tue, 10 Mar 2020 11:47:02 +0000 Subject: [PATCH 084/229] Skip Route tests that are R-specific on Q MTU was added in R so test for it should be run on Q. Also revise test to adopt rule. Test: atest CtsNetTestCasesLatestSdk:android.net.LinkAddressTest on both devices Bug: 150918852 Change-Id: Ibab9cfae0d35b26c6e4ca0defbb89769b04201d4 Merged-In: Ibab9cfae0d35b26c6e4ca0defbb89769b04201d4 (cherry picked from commit 09e5726e158d543b7632cd6e22f6e4c29b0bef52) --- .../java/android/net/RouteInfoTest.java | 85 ++++++++++++++++--- 1 file changed, 74 insertions(+), 11 deletions(-) diff --git a/tests/net/common/java/android/net/RouteInfoTest.java b/tests/net/common/java/android/net/RouteInfoTest.java index fe51b3af4d..1658262c17 100644 --- a/tests/net/common/java/android/net/RouteInfoTest.java +++ b/tests/net/common/java/android/net/RouteInfoTest.java @@ -19,19 +19,40 @@ package android.net; import static android.net.RouteInfo.RTN_UNREACHABLE; import static com.android.testutils.MiscAssertsKt.assertEqualBothWays; +import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals; import static com.android.testutils.MiscAssertsKt.assertNotEqualEitherWay; -import static com.android.testutils.ParcelUtilsKt.assertParcelSane; import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless; -import android.test.suitebuilder.annotation.SmallTest; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; -import junit.framework.TestCase; +import android.os.Build; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.testutils.DevSdkIgnoreRule; +import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; -public class RouteInfoTest extends TestCase { +@RunWith(AndroidJUnit4.class) +@SmallTest +public class RouteInfoTest { + @Rule + public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); + + private static final int INVALID_ROUTE_TYPE = -1; private InetAddress Address(String addr) { return InetAddress.parseNumericAddress(addr); @@ -41,15 +62,32 @@ public class RouteInfoTest extends TestCase { return new IpPrefix(prefix); } - @SmallTest + @Test public void testConstructor() { RouteInfo r; - // Invalid input. try { r = new RouteInfo((IpPrefix) null, null, "rmnet0"); fail("Expected RuntimeException: destination and gateway null"); - } catch(RuntimeException e) {} + } catch (RuntimeException e) { } + + try { + r = new RouteInfo(Prefix("2001:db8:ace::/49"), Address("2001:db8::1"), "rmnet0", + INVALID_ROUTE_TYPE); + fail("Invalid route type should cause exception"); + } catch (IllegalArgumentException e) { } + + try { + r = new RouteInfo(Prefix("2001:db8:ace::/49"), Address("192.0.2.1"), "rmnet0", + RTN_UNREACHABLE); + fail("Address family mismatch should cause exception"); + } catch (IllegalArgumentException e) { } + + try { + r = new RouteInfo(Prefix("0.0.0.0/0"), Address("2001:db8::1"), "rmnet0", + RTN_UNREACHABLE); + fail("Address family mismatch should cause exception"); + } catch (IllegalArgumentException e) { } // Null destination is default route. r = new RouteInfo((IpPrefix) null, Address("2001:db8::1"), null); @@ -74,6 +112,7 @@ public class RouteInfoTest extends TestCase { assertNull(r.getInterface()); } + @Test public void testMatches() { class PatchedRouteInfo { private final RouteInfo mRouteInfo; @@ -113,6 +152,7 @@ public class RouteInfoTest extends TestCase { assertFalse(ipv4Default.matches(Address("2001:db8::f00"))); } + @Test public void testEquals() { // IPv4 RouteInfo r1 = new RouteInfo(Prefix("2001:db8:ace::/48"), Address("2001:db8::1"), "wlan0"); @@ -146,6 +186,7 @@ public class RouteInfoTest extends TestCase { assertNotEqualEitherWay(r1, r3); } + @Test public void testHostAndDefaultRoutes() { RouteInfo r; @@ -228,6 +269,7 @@ public class RouteInfoTest extends TestCase { assertFalse(r.isIPv6Default()); } + @Test public void testTruncation() { LinkAddress l; RouteInfo r; @@ -244,6 +286,7 @@ public class RouteInfoTest extends TestCase { // Make sure that creating routes to multicast addresses doesn't throw an exception. Even though // there's nothing we can do with them, we don't want to crash if, e.g., someone calls // requestRouteToHostAddress("230.0.0.0", MOBILE_HIPRI); + @Test public void testMulticastRoute() { RouteInfo r; r = new RouteInfo(Prefix("230.0.0.0/32"), Address("192.0.2.1"), "wlan0"); @@ -251,16 +294,36 @@ public class RouteInfoTest extends TestCase { // No exceptions? Good. } + @Test public void testParceling() { RouteInfo r; - - r = new RouteInfo(Prefix("::/0"), Address("2001:db8::"), null); + r = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), null); assertParcelingIsLossless(r); - r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0"); - assertParcelSane(r, 7); + assertParcelingIsLossless(r); + r = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0", RTN_UNREACHABLE); + assertParcelingIsLossless(r); } + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testMtuParceling() { + final RouteInfo r = new RouteInfo(Prefix("ff02::1/128"), Address("2001:db8::"), "testiface", + RTN_UNREACHABLE, 1450 /* mtu */); + assertParcelingIsLossless(r); + } + + @Test @IgnoreAfter(Build.VERSION_CODES.Q) + public void testFieldCount_Q() { + assertFieldCountEquals(6, RouteInfo.class); + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testFieldCount() { + // Make sure any new field is covered by the above parceling tests when changing this number + assertFieldCountEquals(7, RouteInfo.class); + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testMtu() { RouteInfo r; r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0", From 1494a56ecfc63b3d7a9b8d1c5928dc0c88da8fce Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Wed, 11 Mar 2020 11:14:59 +0000 Subject: [PATCH 085/229] Add CTS for SocketUtils.makePacketSocketAddress(int, int, byte[]) Bug: 149426063 Bug: 150640362 Test: atest CtsNetTestCasesLatestSdk:android.net.util.SocketUtilsTest on both Q and R devices Change-Id: I4b5a3dfb78b404d414b7dc358e6f16c3414a8b33 Merged-In: I4b5a3dfb78b404d414b7dc358e6f16c3414a8b33 (cherry picked from aosp/1243868) --- .../java/android/net/util/SocketUtilsTest.kt | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/tests/net/common/java/android/net/util/SocketUtilsTest.kt b/tests/net/common/java/android/net/util/SocketUtilsTest.kt index 9c7cfb0c71..aaf97f3688 100644 --- a/tests/net/common/java/android/net/util/SocketUtilsTest.kt +++ b/tests/net/common/java/android/net/util/SocketUtilsTest.kt @@ -14,8 +14,9 @@ * limitations under the License. */ -package android.net.util; +package android.net.util +import android.os.Build import android.system.NetlinkSocketAddress import android.system.Os import android.system.OsConstants.AF_INET @@ -26,18 +27,26 @@ import android.system.OsConstants.SOCK_DGRAM import android.system.PacketSocketAddress import androidx.test.filters.SmallTest import androidx.test.runner.AndroidJUnit4 +import com.android.testutils.DevSdkIgnoreRule +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Assert.fail +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith private const val TEST_INDEX = 123 private const val TEST_PORT = 555 +private const val FF_BYTE = 0xff.toByte() + @RunWith(AndroidJUnit4::class) @SmallTest class SocketUtilsTest { + @Rule @JvmField + val ignoreRule = DevSdkIgnoreRule() + @Test fun testMakeNetlinkSocketAddress() { val nlAddress = SocketUtils.makeNetlinkSocketAddress(TEST_PORT, RTMGRP_NEIGH) @@ -50,16 +59,21 @@ class SocketUtilsTest { } @Test - fun testMakePacketSocketAddress() { + fun testMakePacketSocketAddress_Q() { val pkAddress = SocketUtils.makePacketSocketAddress(ETH_P_ALL, TEST_INDEX) assertTrue("Not PacketSocketAddress object", pkAddress is PacketSocketAddress) - val ff = 0xff.toByte() - val pkAddress2 = SocketUtils.makePacketSocketAddress(TEST_INDEX, - byteArrayOf(ff, ff, ff, ff, ff, ff)) + val pkAddress2 = SocketUtils.makePacketSocketAddress(TEST_INDEX, ByteArray(6) { FF_BYTE }) assertTrue("Not PacketSocketAddress object", pkAddress2 is PacketSocketAddress) } + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testMakePacketSocketAddress() { + val pkAddress = SocketUtils.makePacketSocketAddress( + ETH_P_ALL, TEST_INDEX, ByteArray(6) { FF_BYTE }) + assertTrue("Not PacketSocketAddress object", pkAddress is PacketSocketAddress) + } + @Test fun testCloseSocket() { // Expect no exception happening with null object. From 58d144f6ed3e5aca99781fa4391bb85922cf70f2 Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Thu, 20 Feb 2020 21:47:01 -0800 Subject: [PATCH 086/229] services.net: Use the new ModuleNetworkStackClient Use the new ModuleNetworkStackClient to retrieve instances IpMemoryStore & IpClient. Bug: 145825329 Test: Compiles Change-Id: I065525fdbd64b9509ef0f47bb35954d267c65fd2 --- tests/net/java/android/net/IpMemoryStoreTest.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/net/java/android/net/IpMemoryStoreTest.java b/tests/net/java/android/net/IpMemoryStoreTest.java index b81ca36429..442ac5605e 100644 --- a/tests/net/java/android/net/IpMemoryStoreTest.java +++ b/tests/net/java/android/net/IpMemoryStoreTest.java @@ -35,6 +35,7 @@ import android.net.ipmemorystore.IOnStatusListener; import android.net.ipmemorystore.NetworkAttributes; import android.net.ipmemorystore.NetworkAttributesParcelable; import android.net.ipmemorystore.Status; +import android.net.networkstack.ModuleNetworkStackClient; import android.os.RemoteException; import androidx.test.filters.SmallTest; @@ -67,7 +68,7 @@ public class IpMemoryStoreTest { @Mock Context mMockContext; @Mock - NetworkStackClient mNetworkStackClient; + ModuleNetworkStackClient mModuleNetworkStackClient; @Mock IIpMemoryStore mMockService; @Mock @@ -90,14 +91,14 @@ public class IpMemoryStoreTest { ((IIpMemoryStoreCallbacks) invocation.getArgument(0)) .onIpMemoryStoreFetched(mMockService); return null; - }).when(mNetworkStackClient).fetchIpMemoryStore(any()); + }).when(mModuleNetworkStackClient).fetchIpMemoryStore(any()); } else { - doNothing().when(mNetworkStackClient).fetchIpMemoryStore(mCbCaptor.capture()); + doNothing().when(mModuleNetworkStackClient).fetchIpMemoryStore(mCbCaptor.capture()); } mStore = new IpMemoryStore(mMockContext) { @Override - protected NetworkStackClient getNetworkStackClient() { - return mNetworkStackClient; + protected ModuleNetworkStackClient getModuleNetworkStackClient(Context ctx) { + return mModuleNetworkStackClient; } }; } From 7b4eada7c272ca4870cc3cfaa25b13738e6e3cfe Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Thu, 12 Mar 2020 11:12:31 +0000 Subject: [PATCH 087/229] Add javadoc for Network#netId Bug: 151156820 Test: m doc-comment-check-docs Change-Id: I18e6022c7b0b8bf132069f33d916d1b16d53d4f0 Merged-In: Iea34a5c58a8b77c83258a39a8a44601e21a482f5 (cherry picked from commit ab23c0fef8c02a9d63b1b48628eb687f589aac72) --- core/java/android/net/Network.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index c5681cb6d7..6f5471baa7 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -61,6 +61,7 @@ import javax.net.SocketFactory; public class Network implements Parcelable { /** + * The unique id of the network. * @hide */ @SystemApi From 487b677f3abf3a92cb3841abb873b3e66701f46e Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 2 Mar 2020 19:46:35 +0900 Subject: [PATCH 088/229] Ensure that NetworkFactory objects cannot be reused. NetworkFactory is turning into a one-time object that cannot be re-used. Check for this in ConnectivityService. Bug: 148635501 Test: test continues to pass Change-Id: I793436ee0f4b5d778788ad34b8a2575d2ad0ed80 --- .../server/ConnectivityServiceTest.java | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index c2c3ba3e8b..7c6fe23a3b 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -2426,7 +2426,7 @@ public class ConnectivityServiceTest { assertEquals(expectedRequestCount, testFactory.getMyRequestCount()); assertTrue(testFactory.getMyStartRequested()); - testFactory.unregister(); + testFactory.terminate(); if (networkCallback != null) mCm.unregisterNetworkCallback(networkCallback); handlerThread.quit(); } @@ -2451,6 +2451,38 @@ public class ConnectivityServiceTest { // Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed. } + @Test + public void testNetworkFactoryUnregister() throws Exception { + final NetworkCapabilities filter = new NetworkCapabilities(); + filter.clearAll(); + + final HandlerThread handlerThread = new HandlerThread("testNetworkFactoryRequests"); + handlerThread.start(); + + // Checks that calling setScoreFilter on a NetworkFactory immediately before closing it + // does not crash. + for (int i = 0; i < 100; i++) { + final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), + mServiceContext, "testFactory", filter); + // Register the factory and don't be surprised when the default request arrives. + testFactory.register(); + testFactory.expectAddRequestsWithScores(0); + testFactory.waitForNetworkRequests(1); + + testFactory.setScoreFilter(42); + testFactory.terminate(); + + if (i % 2 == 0) { + try { + testFactory.register(); + fail("Re-registering terminated NetworkFactory should throw"); + } catch (IllegalStateException expected) { + } + } + } + handlerThread.quit(); + } + @Test public void testNoMutableNetworkRequests() throws Exception { PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), 0); @@ -3488,7 +3520,7 @@ public class ConnectivityServiceTest { cellNetworkCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); assertLength(1, mCm.getAllNetworks()); - testFactory.unregister(); + testFactory.terminate(); mCm.unregisterNetworkCallback(cellNetworkCallback); handlerThread.quit(); } @@ -3828,7 +3860,7 @@ public class ConnectivityServiceTest { mCm.unregisterNetworkCallback(networkCallback); } - testFactory.unregister(); + testFactory.terminate(); handlerThread.quit(); } From d884e63e6196b6b586ab8ef6c428d60fd1f268a2 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Thu, 12 Mar 2020 17:52:33 +0800 Subject: [PATCH 089/229] Removing some of the API don't have to be @SystemApi Some of the API we made @SystemApi won't be used by mainline module. Removing these from the surface. Bug: 151266974 Test: atest FrameworksNetTests atest FrameworksTelephonyTests atest FrameworksWifiTests Change-Id: Ie30efa172f93a7557fb6ef56f4daf80e958c3787 --- core/java/android/net/NetworkAgent.java | 4 ++++ core/java/android/net/NetworkAgentConfig.java | 6 ++++++ core/java/android/net/NetworkCapabilities.java | 1 - core/java/android/net/NetworkProvider.java | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index fef353f604..5c754a1b97 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -78,6 +78,7 @@ public abstract class NetworkAgent { /** * The ID of the {@link NetworkProvider} that created this object, or * {@link NetworkProvider#ID_NONE} if unknown. + * @hide */ public final int providerId; @@ -584,6 +585,7 @@ public abstract class NetworkAgent { * * @deprecated this is for backward compatibility only. * @param legacySubtype the legacy subtype. + * @hide */ @Deprecated public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) { @@ -608,6 +610,7 @@ public abstract class NetworkAgent { * * @deprecated this is for backward compatibility only. * @param extraInfo the ExtraInfo. + * @hide */ @Deprecated public void setLegacyExtraInfo(@Nullable final String extraInfo) { @@ -711,6 +714,7 @@ public abstract class NetworkAgent { /** * Called when ConnectivityService request a bandwidth update. The parent factory * shall try to overwrite this method and produce a bandwidth update if capable. + * @hide */ public void onBandwidthUpdateRequested() { pollLceData(); diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java index 7e2db4a4fa..ca9328a713 100644 --- a/core/java/android/net/NetworkAgentConfig.java +++ b/core/java/android/net/NetworkAgentConfig.java @@ -108,6 +108,7 @@ public final class NetworkAgentConfig implements Parcelable { /** * * @return whether the sign in to network notification is enabled by this configuration. + * @hide */ public boolean isProvisioningNotificationEnabled() { return !provisioningNotificationDisabled; @@ -122,6 +123,7 @@ public final class NetworkAgentConfig implements Parcelable { /** * @return the subscriber ID, or null if none. + * @hide */ @Nullable public String getSubscriberId() { @@ -138,6 +140,7 @@ public final class NetworkAgentConfig implements Parcelable { /** * @return whether NAT64 prefix detection is enabled. + * @hide */ public boolean isNat64DetectionEnabled() { return !skip464xlat; @@ -247,6 +250,7 @@ public final class NetworkAgentConfig implements Parcelable { * Sets the subscriber ID for this network. * * @return this builder, to facilitate chaining. + * @hide */ @NonNull public Builder setSubscriberId(@Nullable String subscriberId) { @@ -259,6 +263,7 @@ public final class NetworkAgentConfig implements Parcelable { * and reduce idle traffic on networks that are known to be IPv6-only without a NAT64. * * @return this builder, to facilitate chaining. + * @hide */ @NonNull public Builder disableNat64Detection() { @@ -271,6 +276,7 @@ public final class NetworkAgentConfig implements Parcelable { * perform its own carrier-specific provisioning procedure. * * @return this builder, to facilitate chaining. + * @hide */ @NonNull public Builder disableProvisioningNotification() { diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 83f99802b8..116e343ff2 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -613,7 +613,6 @@ public final class NetworkCapabilities implements Parcelable { * @return {@code true} if the network should be restricted. * @hide */ - @SystemApi public boolean deduceRestrictedCapability() { // Check if we have any capability that forces the network to be restricted. final boolean forceRestrictedCapability = diff --git a/core/java/android/net/NetworkProvider.java b/core/java/android/net/NetworkProvider.java index 2c0e4aa700..418d6915d4 100644 --- a/core/java/android/net/NetworkProvider.java +++ b/core/java/android/net/NetworkProvider.java @@ -106,10 +106,12 @@ public class NetworkProvider { } // TODO: consider adding a register() method so ConnectivityManager does not need to call this. + /** @hide */ public @Nullable Messenger getMessenger() { return mMessenger; } + /** @hide */ public @NonNull String getName() { return mName; } From 1378facba476eb8320f00fc0cbe36dfbf3fbbf6a Mon Sep 17 00:00:00 2001 From: Roshan Pius Date: Fri, 21 Feb 2020 07:37:30 -0800 Subject: [PATCH 090/229] services.net: Add a static library needed by wifi module Add a new static library that compiles against system_current which includes all the parts needed by the wifi mainline module. Also, a) Refactored TcpKeepalivePacketData to use public APIs. The parcel read/write methods in the base class are @hide and they're not used by the other child class (NatKeepalivePacketData). So, remove the @hide method from base class and use it direcly in the child class. b) Add jar-jar rules for all the statically linked dependencies in wifi service jar rules. Exempt-From-Owner-Approval: Minor change on top of owner's approval. Bug: 145825329 Test: Device boots up & connects to wifi networks. Change-Id: Ifde69b579cfe5b813766f676acb10e436e64a44c --- .../java/android/net/KeepalivePacketData.java | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/core/java/android/net/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java index 2b8b7e69de..6c0ba2f63a 100644 --- a/core/java/android/net/KeepalivePacketData.java +++ b/core/java/android/net/KeepalivePacketData.java @@ -22,7 +22,6 @@ import static android.net.InvalidPacketException.ERROR_INVALID_PORT; import android.annotation.NonNull; import android.annotation.SystemApi; import android.net.util.IpUtils; -import android.os.Parcel; import android.util.Log; import java.net.InetAddress; @@ -30,7 +29,6 @@ import java.net.InetAddress; /** * Represents the actual packets that are sent by the * {@link android.net.SocketKeepalive} API. - * * @hide */ @SystemApi @@ -54,6 +52,9 @@ public class KeepalivePacketData { /** Packet data. A raw byte string of packet data, not including the link-layer header. */ private final byte[] mPacket; + // Note: If you add new fields, please modify the parcelling code in the child classes. + + // This should only be constructed via static factory methods, such as // nattKeepalivePacket. /** @@ -87,21 +88,4 @@ public class KeepalivePacketData { return mPacket.clone(); } - /** @hide */ - public void writeToParcel(Parcel out, int flags) { - out.writeString(srcAddress.getHostAddress()); - out.writeString(dstAddress.getHostAddress()); - out.writeInt(srcPort); - out.writeInt(dstPort); - out.writeByteArray(mPacket); - } - - /** @hide */ - protected KeepalivePacketData(Parcel in) { - srcAddress = NetworkUtils.numericToInetAddress(in.readString()); - dstAddress = NetworkUtils.numericToInetAddress(in.readString()); - srcPort = in.readInt(); - dstPort = in.readInt(); - mPacket = in.createByteArray(); - } } From 025f73910a2848835c8882d9b95e714ecb820f5a Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Fri, 13 Mar 2020 20:51:48 +0000 Subject: [PATCH 091/229] Update Javadoc comments for ConnectivityDiagnostics constants. API Council feedback requested adding documentation for detection method constants used in DataStallReport to indicate how the Data Stall was detected. Bug: 150598997 Test: n/a Change-Id: Ib08f05562dd4b17973eeee97452d9f56d37e80fe Merged-In: Ib08f05562dd4b17973eeee97452d9f56d37e80fe (cherry picked from commit 52d9e61121883945931de533b5cfd44da30c0248) --- core/java/android/net/ConnectivityDiagnosticsManager.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java index d009144034..1710ccb319 100644 --- a/core/java/android/net/ConnectivityDiagnosticsManager.java +++ b/core/java/android/net/ConnectivityDiagnosticsManager.java @@ -368,7 +368,14 @@ public class ConnectivityDiagnosticsManager { /** Class that includes information for a suspected data stall on a specific Network */ public static final class DataStallReport implements Parcelable { + /** + * Indicates that the Data Stall was detected using DNS events. + */ public static final int DETECTION_METHOD_DNS_EVENTS = 1; + + /** + * Indicates that the Data Stall was detected using TCP metrics. + */ public static final int DETECTION_METHOD_TCP_METRICS = 2; /** @hide */ From b0b8333e829034c262e362ccb56bce88ea42640b Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Sat, 14 Mar 2020 05:13:42 +0000 Subject: [PATCH 092/229] Resolve ambiguous argument. CTS tests don't have access to TestNetworkAgent and therefore require overloading this method, which means 'null' is ambiguous. Bug: 139268426 Test: FrameworksNetTests Change-Id: I5d7deea82d7114fa38f37b90f94fe7e6073bd848 (cherry picked from commit ff83f1d7eea38c4143869cbf10dca5972421f6cd) --- .../net/java/com/android/server/ConnectivityServiceTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 6985415a6a..f9d66f9a26 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -3723,7 +3723,7 @@ public class ConnectivityServiceTest { mCm.requestNetwork(nr, networkCallback, timeoutMs); // pass timeout and validate that UNAVAILABLE is called - networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null); + networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null); // create a network satisfying request - validate that request not triggered mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); @@ -3814,7 +3814,7 @@ public class ConnectivityServiceTest { // Simulate the factory releasing the request as unfulfillable and expect onUnavailable! testFactory.triggerUnfulfillable(requests.get(newRequestId)); - networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, null); + networkCallback.expectCallback(CallbackEntry.UNAVAILABLE, (Network) null); testFactory.waitForRequests(); // unregister network callback - a no-op (since already freed by the From 04b7e0b17cdf9d837c3702e2db1326333cd41195 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Tue, 10 Mar 2020 05:47:55 +0000 Subject: [PATCH 093/229] Add test for getDeprecationTime and getExpirationTime Add for cts coverage for system API Bug: 139268426 Bug: 135998869 Test: atest FrameworksNetTests Test: atest CtsNetTestCasesLatestSdk:android.net.LinkAddressTest Change-Id: I64cd2c914f2da71383af7cdef2cf64c60a7d268c Merged-In: I64cd2c914f2da71383af7cdef2cf64c60a7d268c (cherry picked from commit 1e7f68f39c0855a45dbf4eeecbff430a2f6f3396) --- tests/net/common/java/android/net/LinkAddressTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java index 99dac1439b..c74c112490 100644 --- a/tests/net/common/java/android/net/LinkAddressTest.java +++ b/tests/net/common/java/android/net/LinkAddressTest.java @@ -367,6 +367,9 @@ public class LinkAddressTest { -2, 100000L); fail("negative deprecation time should cause exception"); } catch (IllegalArgumentException expected) { } + + LinkAddress addr = new LinkAddress(V6_ADDRESS, 64, 0, 456, 100000L, 200000L); + assertEquals(100000L, addr.getDeprecationTime()); } @Test @IgnoreUpTo(Build.VERSION_CODES.Q) @@ -382,6 +385,9 @@ public class LinkAddressTest { 100000L, -2); fail("negative expiration time should cause exception"); } catch (IllegalArgumentException expected) { } + + LinkAddress addr = new LinkAddress(V6_ADDRESS, 64, 0, 456, 100000L, 200000L); + assertEquals(200000L, addr.getExpirationTime()); } @Test From 22d0bfd7c448d1276168816585af747edf90843a Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Thu, 5 Mar 2020 15:19:48 -0800 Subject: [PATCH 094/229] Update ConnectivityDiagnosticsCallback function name. API Council feedback suggests renaming ConnectivityDiagnosticsCallback 'onConnectivityReport' function to be 'onConnectivityReportAvailable'. Bug: 150598997 Test: atest FrameworksNetTests Change-Id: Ieea727ecee6cf358a53a215fd4b06233dfe967ea (cherry picked from commit 324b224cc48fcb12125bd1727be70ad2effbfce3) --- .../android/net/ConnectivityDiagnosticsManager.java | 10 +++++----- .../java/com/android/server/ConnectivityService.java | 2 +- .../net/ConnectivityDiagnosticsManagerTest.java | 6 +++--- .../com/android/server/ConnectivityServiceTest.java | 5 +++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java index 1710ccb319..fbfd73964a 100644 --- a/core/java/android/net/ConnectivityDiagnosticsManager.java +++ b/core/java/android/net/ConnectivityDiagnosticsManager.java @@ -233,8 +233,8 @@ public class ConnectivityDiagnosticsManager { * Constructor for ConnectivityReport. * *

Apps should obtain instances through {@link - * ConnectivityDiagnosticsCallback#onConnectivityReport} instead of instantiating their own - * instances (unless for testing purposes). + * ConnectivityDiagnosticsCallback#onConnectivityReportAvailable} instead of instantiating + * their own instances (unless for testing purposes). * * @param network The Network for which this ConnectivityReport applies * @param reportTimestamp The timestamp for the report @@ -622,10 +622,10 @@ public class ConnectivityDiagnosticsManager { /** @hide */ @VisibleForTesting - public void onConnectivityReport(@NonNull ConnectivityReport report) { + public void onConnectivityReportAvailable(@NonNull ConnectivityReport report) { Binder.withCleanCallingIdentity(() -> { mExecutor.execute(() -> { - mCb.onConnectivityReport(report); + mCb.onConnectivityReportAvailable(report); }); }); } @@ -666,7 +666,7 @@ public class ConnectivityDiagnosticsManager { * * @param report The ConnectivityReport containing information about a connectivity check */ - public void onConnectivityReport(@NonNull ConnectivityReport report) {} + public void onConnectivityReportAvailable(@NonNull ConnectivityReport report) {} /** * Called when the platform suspects a data stall on some Network. diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 3a3358c4c0..62ea862835 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -7817,7 +7817,7 @@ public class ConnectivityService extends IConnectivityManager.Stub getMatchingPermissionedCallbacks(nai); for (final IConnectivityDiagnosticsCallback cb : results) { try { - cb.onConnectivityReport(report); + cb.onConnectivityReportAvailable(report); } catch (RemoteException ex) { loge("Error invoking onConnectivityReport", ex); } diff --git a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java index 8eb5cfa48c..1d6c107667 100644 --- a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java +++ b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java @@ -304,12 +304,12 @@ public class ConnectivityDiagnosticsManagerTest { } @Test - public void testConnectivityDiagnosticsCallbackOnConnectivityReport() { - mBinder.onConnectivityReport(createSampleConnectivityReport()); + public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable() { + mBinder.onConnectivityReportAvailable(createSampleConnectivityReport()); // The callback will be invoked synchronously by inline executor. Immediately check the // latch without waiting. - verify(mCb).onConnectivityReport(eq(createSampleConnectivityReport())); + verify(mCb).onConnectivityReportAvailable(eq(createSampleConnectivityReport())); } @Test diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 671c56499a..de8bf3c560 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6894,14 +6894,15 @@ public class ConnectivityServiceTest { } @Test - public void testConnectivityDiagnosticsCallbackOnConnectivityReport() throws Exception { + public void testConnectivityDiagnosticsCallbackOnConnectivityReportAvailable() + throws Exception { setUpConnectivityDiagnosticsCallback(); // Block until all other events are done processing. HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); // Verify onConnectivityReport fired - verify(mConnectivityDiagnosticsCallback).onConnectivityReport( + verify(mConnectivityDiagnosticsCallback).onConnectivityReportAvailable( argThat(report -> { final NetworkCapabilities nc = report.getNetworkCapabilities(); return nc.getUids() == null From 1c7f159f4427f3dcae63109f539ca6c966fefb17 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Mon, 16 Mar 2020 15:48:50 +0000 Subject: [PATCH 095/229] Protect ConnectivityService from SecurityException in permission check. ConnectivityService currently calls LocationPermissionChecker#checkLocationPermission. This method call throws a SecurityException if the given package name and UID do not match. This permission check is made from the ConnectivityService Thread, so any Exception being thrown will crash the SystemServer. This is not acceptable, so surround the permission check in a try-catch in case any SecurityExceptions are thrown. Bug: 149119324 Test: atest ConnectivityServiceTest Change-Id: Ibe2874f2a5249432270aa1b9eb7d004bbba35ac2 Merged-In: Ibe2874f2a5249432270aa1b9eb7d004bbba35ac2 (cherry picked from commit 9eacc855b63b36f5b937e703b20d4b0bb077ab75) --- .../android/server/ConnectivityService.java | 11 ++++++++-- .../server/ConnectivityServiceTest.java | 20 +++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 62ea862835..deae459e39 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -7892,8 +7892,15 @@ public class ConnectivityService extends IConnectivityManager.Stub return true; } - if (!mLocationPermissionChecker.checkLocationPermission( - callbackPackageName, null /* featureId */, callbackUid, null /* message */)) { + // LocationPermissionChecker#checkLocationPermission can throw SecurityException if the uid + // and package name don't match. Throwing on the CS thread is not acceptable, so wrap the + // call in a try-catch. + try { + if (!mLocationPermissionChecker.checkLocationPermission( + callbackPackageName, null /* featureId */, callbackUid, null /* message */)) { + return false; + } + } catch (SecurityException e) { return false; } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index de8bf3c560..c21772a5d1 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6788,6 +6788,26 @@ public class ConnectivityServiceTest { mContext.getOpPackageName())); } + @Test + public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception { + final NetworkAgentInfo naiWithoutUid = + new NetworkAgentInfo( + null, null, null, null, null, new NetworkCapabilities(), 0, + mServiceContext, null, null, mService, null, null, null, 0); + + mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); + + try { + assertFalse( + "Mismatched uid/package name should not pass the location permission check", + mService.checkConnectivityDiagnosticsPermissions( + Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid, + mContext.getOpPackageName())); + } catch (SecurityException e) { + fail("checkConnectivityDiagnosticsPermissions shouldn't surface a SecurityException"); + } + } + @Test public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception { final NetworkAgentInfo naiWithoutUid = From 8e9e1a03748470e3eee75326baed21d5175c429f Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Mon, 16 Mar 2020 20:31:58 +0000 Subject: [PATCH 096/229] Add support for registering test networks with administrators. CTS testing for ConnectivityDiagnosticsManager requires registering TestNetworks with the administrator UIDs set. This sets up the CTS process to be an administrator over the test network, which allows it to receive ConnectivityDiagnosticsCallback callbacks. Bug: 148032944 Test: atest android.net.cts.ConnectivityDiagnosticsManagerTest Test: atest IpSecManagerTunnelTest Change-Id: I7a443c368cf1ac470fbe40883ca24bc3143153b0 Merged-In: I7a443c368cf1ac470fbe40883ca24bc3143153b0 (cherry picked from commit 7b105b6194679fad6afe3615f0654b547034be6c) --- .../net/ConnectivityDiagnosticsManager.java | 2 +- core/java/android/net/TestNetworkManager.java | 40 ++++++++++++++----- .../android/server/TestNetworkService.java | 13 ++++++ 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java index fbfd73964a..6f0a4f9744 100644 --- a/core/java/android/net/ConnectivityDiagnosticsManager.java +++ b/core/java/android/net/ConnectivityDiagnosticsManager.java @@ -136,7 +136,7 @@ public class ConnectivityDiagnosticsManager { * {@link #NETWORK_VALIDATION_RESULT_PARTIALLY_VALID}, * {@link #NETWORK_VALIDATION_RESULT_SKIPPED}. * - * @see android.net.NetworkCapabilities#CAPABILITY_VALIDATED + * @see android.net.NetworkCapabilities#NET_CAPABILITY_VALIDATED */ @NetworkValidationResult public static final String KEY_NETWORK_VALIDATION_RESULT = "networkValidationResult"; diff --git a/core/java/android/net/TestNetworkManager.java b/core/java/android/net/TestNetworkManager.java index 4ac4a69e4b..c3284df397 100644 --- a/core/java/android/net/TestNetworkManager.java +++ b/core/java/android/net/TestNetworkManager.java @@ -16,6 +16,7 @@ package android.net; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.TestApi; import android.os.IBinder; import android.os.RemoteException; @@ -53,6 +54,19 @@ public class TestNetworkManager { } } + private void setupTestNetwork( + @NonNull String iface, + @Nullable LinkProperties lp, + boolean isMetered, + @NonNull int[] administratorUids, + @NonNull IBinder binder) { + try { + mService.setupTestNetwork(iface, lp, isMetered, administratorUids, binder); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Sets up a capability-limited, testing-only network for a given interface * @@ -66,11 +80,7 @@ public class TestNetworkManager { public void setupTestNetwork( @NonNull LinkProperties lp, boolean isMetered, @NonNull IBinder binder) { Preconditions.checkNotNull(lp, "Invalid LinkProperties"); - try { - mService.setupTestNetwork(lp.getInterfaceName(), lp, isMetered, binder); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + setupTestNetwork(lp.getInterfaceName(), lp, isMetered, new int[0], binder); } /** @@ -82,11 +92,21 @@ public class TestNetworkManager { */ @TestApi public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) { - try { - mService.setupTestNetwork(iface, null, true, binder); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + setupTestNetwork(iface, null, true, new int[0], binder); + } + + /** + * Sets up a capability-limited, testing-only network for a given interface with the given + * administrator UIDs. + * + * @param iface the name of the interface to be used for the Network LinkProperties. + * @param administratorUids The administrator UIDs to be used for the test-only network + * @param binder A binder object guarding the lifecycle of this test network. + * @hide + */ + public void setupTestNetwork( + @NonNull String iface, @NonNull int[] administratorUids, @NonNull IBinder binder) { + setupTestNetwork(iface, null, true, administratorUids, binder); } /** diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index 35a980286d..f772a4a5a3 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -53,6 +53,7 @@ import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; @@ -230,6 +231,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { @Nullable LinkProperties lp, boolean isMetered, int callingUid, + @NonNull int[] administratorUids, @NonNull IBinder binder) throws RemoteException, SocketException { Objects.requireNonNull(looper, "missing Looper"); @@ -248,6 +250,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); nc.setNetworkSpecifier(new StringNetworkSpecifier(iface)); + nc.setAdministratorUids(intArrayToList(administratorUids)); if (!isMetered) { nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); } @@ -290,6 +293,14 @@ class TestNetworkService extends ITestNetworkManager.Stub { return new TestNetworkAgent(looper, context, ni, nc, lp, callingUid, binder); } + private List intArrayToList(@NonNull int[] array) { + final List list = new ArrayList<>(array.length); + for (final int i : array) { + list.add(i); + } + return list; + } + /** * Sets up a Network with extremely limited privileges, guarded by the MANAGE_TEST_NETWORKS * permission. @@ -301,6 +312,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { @NonNull String iface, @Nullable LinkProperties lp, boolean isMetered, + @NonNull int[] administratorUids, @NonNull IBinder binder) { enforceTestNetworkPermissions(mContext); @@ -335,6 +347,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { lp, isMetered, callingUid, + administratorUids, binder); mTestNetworkTracker.put(agent.getNetwork().netId, agent); From da59e2d2586f2141b4598eccd36a5e322c6d281d Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Fri, 13 Mar 2020 05:34:10 +0000 Subject: [PATCH 097/229] Add test for NetworkAgentConfig Bug: 139268426 Test: atest CtsNetTestCasesLatestSdk:android.net.NetworkAgentConfigTest Change-Id: If9158d086bacb0ade94d59898ac223e4c8f4f73a Merged-In: If9158d086bacb0ade94d59898ac223e4c8f4f73a (cherry picked from aosp/1253722) --- .../android/net/NetworkAgentConfigTest.kt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt index 173dbd1271..de65ba2497 100644 --- a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt +++ b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt @@ -22,6 +22,9 @@ import androidx.test.runner.AndroidJUnit4 import com.android.testutils.DevSdkIgnoreRule import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.assertParcelSane +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -43,4 +46,27 @@ class NetworkAgentConfigTest { }.build() assertParcelSane(config, 9) } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testBuilder() { + val config = NetworkAgentConfig.Builder().apply { + setExplicitlySelected(true) + setLegacyType(ConnectivityManager.TYPE_ETHERNET) + setSubscriberId("MySubId") + setPartialConnectivityAcceptable(false) + setUnvalidatedConnectivityAcceptable(true) + setLegacyTypeName("TEST_NETWORK") + disableNat64Detection() + disableProvisioningNotification() + }.build() + + assertTrue(config.isExplicitlySelected()) + assertEquals(ConnectivityManager.TYPE_ETHERNET, config.getLegacyType()) + assertEquals("MySubId", config.getSubscriberId()) + assertFalse(config.isPartialConnectivityAcceptable()) + assertTrue(config.isUnvalidatedConnectivityAcceptable()) + assertEquals("TEST_NETWORK", config.getLegacyTypeName()) + assertFalse(config.isNat64DetectionEnabled()) + assertFalse(config.isProvisioningNotificationEnabled()) + } } From 268e185cae87a1c6d283e6a46c410b751eb8e56b Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 6 Mar 2020 14:50:48 +0800 Subject: [PATCH 098/229] [SP21] Address comments for API council review about aosp/1172143 Test: atest FrameworksNetTests ImsPhoneCallTrackerTest Test: atest TetheringTests NetworkStackTests Test: m doc-comment-check-docs Fix: 148552904 Change-Id: I141393f229e772d2eb9f7c156849e379bd71b845 Merged-In: I141393f229e772d2eb9f7c156849e379bd71b845 (cherry picked from aosp/1253717) --- .../server/net/NetworkStatsServiceTest.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index 36deca3e37..a0f996fb7b 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -1026,7 +1026,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]); // Verifies that one requestStatsUpdate will be called during iface update. - provider.expectStatsUpdate(0 /* unused */); + provider.expectOnRequestStatsUpdate(0 /* unused */); // Create some initial traffic and report to the service. incrementCurrentTime(HOUR_IN_MILLIS); @@ -1037,7 +1037,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { .addValues(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 1L)); - cb.onStatsUpdated(0 /* unused */, expectedStats, expectedStats); + cb.notifyStatsUpdated(0 /* unused */, expectedStats, expectedStats); // Make another empty mutable stats object. This is necessary since the new NetworkStats // object will be used to compare with the old one in NetworkStatsRecoder, two of them @@ -1047,8 +1047,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { forcePollAndWaitForIdle(); // Verifies that one requestStatsUpdate and setAlert will be called during polling. - provider.expectStatsUpdate(0 /* unused */); - provider.expectSetAlert(MB_IN_BYTES); + provider.expectOnRequestStatsUpdate(0 /* unused */); + provider.expectOnSetAlert(MB_IN_BYTES); // Verifies that service recorded history, does not verify uid tag part. assertUidTotal(sTemplateWifi, UID_RED, 128L, 2L, 128L, 2L, 1); @@ -1082,13 +1082,13 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { assertNotNull(cb); // Simulates alert quota of the provider has been reached. - cb.onAlertReached(); + cb.notifyAlertReached(); HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT); // Verifies that polling is triggered by alert reached. - provider.expectStatsUpdate(0 /* unused */); + provider.expectOnRequestStatsUpdate(0 /* unused */); // Verifies that global alert will be re-armed. - provider.expectSetAlert(MB_IN_BYTES); + provider.expectOnSetAlert(MB_IN_BYTES); } private static File getBaseDir(File statsDir) { From 11ad688fc72e2f93481a1ac28d30f7bb62dbb041 Mon Sep 17 00:00:00 2001 From: junyulai Date: Fri, 13 Mar 2020 19:04:17 +0800 Subject: [PATCH 099/229] [SP24] Rename functions that add Entry unconditionally Currently, in NetworkStats, there are many methods to manipulate the records. However, some methods are similar and ambiguous, such as addEntry, addValues, setValues, addIfaceValues, combineValues and combineAllValues. Thus, properly grouping and renaming methods are necessary. In this change, for methods that add one record unconditionally, name them insertEntry. setIfaceValues -> insertEntry addEntry -> insertEntry Test: atest FrameworksNetTests ImsPhoneCallTrackerTest TetheringTests Test: m doc-comment-check-docs Bug: 148895143 Change-Id: I801ddc49e283a254b9586700c9b597c0adb0d459 Merged-In: I801ddc49e283a254b9586700c9b597c0adb0d459 (cherry picked from aosp/1256352) --- .../java/android/net/NetworkStatsTest.java | 278 +++++++++--------- .../server/net/NetworkStatsObserversTest.java | 26 +- .../server/net/NetworkStatsServiceTest.java | 139 ++++----- 3 files changed, 223 insertions(+), 220 deletions(-) diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java index 33d77d288e..e71d599525 100644 --- a/tests/net/java/android/net/NetworkStatsTest.java +++ b/tests/net/java/android/net/NetworkStatsTest.java @@ -64,15 +64,15 @@ public class NetworkStatsTest { @Test public void testFindIndex() throws Exception { final NetworkStats stats = new NetworkStats(TEST_START, 5) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 1024L, 8L, 0L, 0L, 10) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, 0L, 0L, 1024L, 8L, 11) - .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 12) - .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, + .insertEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12); assertEquals(4, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, @@ -94,21 +94,21 @@ public class NetworkStatsTest { @Test public void testFindIndexHinted() { final NetworkStats stats = new NetworkStats(TEST_START, 3) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 1024L, 8L, 0L, 0L, 10) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11) - .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12) - .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1024L, 8L, 0L, 0L, 10) - .addEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 0L, 0L, 1024L, 8L, 11) - .addEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, + .insertEntry(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11) - .addEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12) - .addEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, + .insertEntry(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 12); // verify that we correctly find across regardless of hinting @@ -143,27 +143,27 @@ public class NetworkStatsTest { assertEquals(0, stats.size()); assertEquals(4, stats.internalSize()); - stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 1L, 1L, 2L, 2L, 3); - stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2L, 2L, 2L, 2L, 4); - stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, + stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, DEFAULT_NETWORK_YES, 3L, 3L, 2L, 2L, 5); - stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, + stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, DEFAULT_NETWORK_NO, 3L, 3L, 2L, 2L, 5); assertEquals(4, stats.size()); assertEquals(4, stats.internalSize()); - stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4L, 40L, 4L, 40L, 7); - stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 5L, 50L, 4L, 40L, 8); - stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 6L, 60L, 5L, 50L, 10); - stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, + stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, DEFAULT_NETWORK_YES, 7L, 70L, 5L, 50L, 11); - stats.addEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, + stats.insertEntry(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, DEFAULT_NETWORK_NO, 7L, 70L, 5L, 50L, 11); assertEquals(9, stats.size()); @@ -193,8 +193,8 @@ public class NetworkStatsTest { public void testCombineExisting() throws Exception { final NetworkStats stats = new NetworkStats(TEST_START, 10); - stats.addEntry(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 10); - stats.addEntry(TEST_IFACE, 1001, SET_DEFAULT, 0xff, 128L, 1L, 128L, 1L, 2); + stats.insertEntry(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 10); + stats.insertEntry(TEST_IFACE, 1001, SET_DEFAULT, 0xff, 128L, 1L, 128L, 1L, 2); stats.combineValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, -128L, -1L, -128L, -1L, -1); @@ -215,12 +215,12 @@ public class NetworkStatsTest { @Test public void testSubtractIdenticalData() throws Exception { final NetworkStats before = new NetworkStats(TEST_START, 2) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12); + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12); final NetworkStats after = new NetworkStats(TEST_START, 2) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12); + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12); final NetworkStats result = after.subtract(before); @@ -234,12 +234,12 @@ public class NetworkStatsTest { @Test public void testSubtractIdenticalRows() throws Exception { final NetworkStats before = new NetworkStats(TEST_START, 2) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12); + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12); final NetworkStats after = new NetworkStats(TEST_START, 2) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1025L, 9L, 2L, 1L, 15) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 3L, 1L, 1028L, 9L, 20); + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1025L, 9L, 2L, 1L, 15) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 3L, 1L, 1028L, 9L, 20); final NetworkStats result = after.subtract(before); @@ -253,13 +253,13 @@ public class NetworkStatsTest { @Test public void testSubtractNewRows() throws Exception { final NetworkStats before = new NetworkStats(TEST_START, 2) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12); + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12); final NetworkStats after = new NetworkStats(TEST_START, 3) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12) - .addEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 20); + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 11) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 12) + .insertEntry(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 20); final NetworkStats result = after.subtract(before); @@ -275,11 +275,11 @@ public class NetworkStatsTest { @Test public void testSubtractMissingRows() throws Exception { final NetworkStats before = new NetworkStats(TEST_START, 2) - .addEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 0L, 0L, 0L, 0) - .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2048L, 0L, 0L, 0L, 0); + .insertEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 0L, 0L, 0L, 0) + .insertEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2048L, 0L, 0L, 0L, 0); final NetworkStats after = new NetworkStats(TEST_START, 1) - .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2049L, 2L, 3L, 4L, 0); + .insertEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 2049L, 2L, 3L, 4L, 0); final NetworkStats result = after.subtract(before); @@ -293,40 +293,40 @@ public class NetworkStatsTest { @Test public void testTotalBytes() throws Exception { final NetworkStats iface = new NetworkStats(TEST_START, 2) - .addEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 128L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 256L, 0L, 0L, 0L, 0L); + .insertEntry(TEST_IFACE, UID_ALL, SET_DEFAULT, TAG_NONE, 128L, 0L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 256L, 0L, 0L, 0L, 0L); assertEquals(384L, iface.getTotalBytes()); final NetworkStats uidSet = new NetworkStats(TEST_START, 3) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L); + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE, 101, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L); assertEquals(96L, uidSet.getTotalBytes()); final NetworkStats uidTag = new NetworkStats(TEST_START, 6) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L); + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 0L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L); assertEquals(64L, uidTag.getTotalBytes()); final NetworkStats uidMetered = new NetworkStats(TEST_START, 3) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L); assertEquals(96L, uidMetered.getTotalBytes()); final NetworkStats uidRoaming = new NetworkStats(TEST_START, 3) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L); assertEquals(96L, uidRoaming.getTotalBytes()); } @@ -343,11 +343,11 @@ public class NetworkStatsTest { @Test public void testGroupedByIfaceAll() throws Exception { final NetworkStats uidStats = new NetworkStats(TEST_START, 3) - .addEntry(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L) - .addEntry(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO, + .insertEntry(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 128L, 8L, 0L, 2L, 20L) - .addEntry(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES, + .insertEntry(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES, DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L); final NetworkStats grouped = uidStats.groupedByIface(); @@ -361,19 +361,19 @@ public class NetworkStatsTest { @Test public void testGroupedByIface() throws Exception { final NetworkStats uidStats = new NetworkStats(TEST_START, 7) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L) - .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L) - .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 64L, 4L, 0L, 0L, 0L) - .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L); final NetworkStats grouped = uidStats.groupedByIface(); @@ -390,19 +390,19 @@ public class NetworkStatsTest { @Test public void testAddAllValues() { final NetworkStats first = new NetworkStats(TEST_START, 5) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, + .insertEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L); final NetworkStats second = new NetworkStats(TEST_START, 2) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, + .insertEntry(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L); first.combineAllValues(second); @@ -421,19 +421,19 @@ public class NetworkStatsTest { @Test public void testGetTotal() { final NetworkStats stats = new NetworkStats(TEST_START, 7) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L) - .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L) - .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 64L, 4L, 0L, 0L, 0L) - .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 512L,32L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L); assertValues(stats.getTotal(null), 1408L, 88L, 0L, 2L, 20L); @@ -459,7 +459,7 @@ public class NetworkStatsTest { assertEquals(0, after.size()); // Test 1 item stats. - before.addEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, 1L, 128L, 0L, 2L, 20L); + before.insertEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, 1L, 128L, 0L, 2L, 20L); after = before.clone(); after.removeUids(new int[0]); assertEquals(1, after.size()); @@ -469,12 +469,12 @@ public class NetworkStatsTest { assertEquals(0, after.size()); // Append remaining test items. - before.addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L) - .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L) - .addEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 16L, 0L, 0L, 0L) - .addEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 8L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 4L, 0L, 0L, 0L) - .addEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 64L, 2L, 0L, 0L, 0L); + before.insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L) + .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 16L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 16L, 8L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 32L, 4L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 64L, 2L, 0L, 0L, 0L); assertEquals(7, before.size()); // Test remove with empty uid list. @@ -505,12 +505,12 @@ public class NetworkStatsTest { @Test public void testClone() throws Exception { final NetworkStats original = new NetworkStats(TEST_START, 5) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L) - .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L); + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L) + .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L); // make clone and mutate original final NetworkStats clone = original.clone(); - original.addEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L); + original.insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L); assertEquals(3, original.size()); assertEquals(2, clone.size()); @@ -523,8 +523,8 @@ public class NetworkStatsTest { public void testAddWhenEmpty() throws Exception { final NetworkStats red = new NetworkStats(TEST_START, -1); final NetworkStats blue = new NetworkStats(TEST_START, 5) - .addEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L) - .addEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L); + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L) + .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L); // We're mostly checking that we don't crash red.combineAllValues(blue); @@ -537,37 +537,37 @@ public class NetworkStatsTest { final String underlyingIface = "wlan0"; final int testTag1 = 8888; NetworkStats delta = new NetworkStats(TEST_START, 17) - .addEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 39605L, 46L, 12259L, 55L, 0L) - .addEntry(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L) - .addEntry(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 72667L, 197L, 43909L, 241L, 0L) - .addEntry(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 9297L, 17L, 4128L, 21L, 0L) // VPN package also uses some traffic through unprotected network. - .addEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4983L, 10L, 1801L, 12L, 0L) - .addEntry(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L) // Tag entries - .addEntry(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO, + .insertEntry(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 21691L, 41L, 13820L, 51L, 0L) - .addEntry(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO, + .insertEntry(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1281L, 2L, 665L, 2L, 0L) // Irrelevant entries - .addEntry(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1685L, 5L, 2070L, 6L, 0L) // Underlying Iface entries - .addEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 5178L, 8L, 2139L, 11L, 0L) - .addEntry(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L) - .addEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, + ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L) + .insertEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 149873L, 287L, 59217L /* smaller than sum(tun0) */, 299L /* smaller than sum(tun0) */, 0L) - .addEntry(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, - DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L); + .insertEntry(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, + ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L); delta.migrateTun(tunUid, tunIface, new String[]{underlyingIface}); assertEquals(20, delta.size()); @@ -635,19 +635,19 @@ public class NetworkStatsTest { final String underlyingIface = "wlan0"; NetworkStats delta = new NetworkStats(TEST_START, 9) // 2 different apps sent/receive data via tun0. - .addEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L) - .addEntry(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L) // VPN package resends data through the tunnel (with exaggerated overhead) - .addEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 240000, 100L, 120000L, 60L, 0L) // 1 app already has some traffic on the underlying interface, the other doesn't yet - .addEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 1000L, 10L, 2000L, 20L, 0L) // Traffic through the underlying interface via the vpn app. // This test should redistribute this data correctly. - .addEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 75500L, 37L, 130000L, 70L, 0L); delta.migrateTun(tunUid, tunIface, new String[]{underlyingIface}); @@ -697,9 +697,9 @@ public class NetworkStatsTest { DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); NetworkStats stats = new NetworkStats(TEST_START, 3) - .addEntry(entry1) - .addEntry(entry2) - .addEntry(entry3); + .insertEntry(entry1) + .insertEntry(entry2) + .insertEntry(entry3); stats.filter(UID_ALL, INTERFACES_ALL, TAG_ALL); assertEquals(3, stats.size()); @@ -724,9 +724,9 @@ public class NetworkStatsTest { DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); NetworkStats stats = new NetworkStats(TEST_START, 3) - .addEntry(entry1) - .addEntry(entry2) - .addEntry(entry3); + .insertEntry(entry1) + .insertEntry(entry2) + .insertEntry(entry3); stats.filter(testUid, INTERFACES_ALL, TAG_ALL); assertEquals(2, stats.size()); @@ -755,10 +755,10 @@ public class NetworkStatsTest { DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); NetworkStats stats = new NetworkStats(TEST_START, 4) - .addEntry(entry1) - .addEntry(entry2) - .addEntry(entry3) - .addEntry(entry4); + .insertEntry(entry1) + .insertEntry(entry2) + .insertEntry(entry3) + .insertEntry(entry4); stats.filter(UID_ALL, new String[] { testIf1, testIf2 }, TAG_ALL); assertEquals(3, stats.size()); @@ -778,8 +778,8 @@ public class NetworkStatsTest { DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); NetworkStats stats = new NetworkStats(TEST_START, 3) - .addEntry(entry1) - .addEntry(entry2); + .insertEntry(entry1) + .insertEntry(entry2); stats.filter(UID_ALL, new String[] { }, TAG_ALL); assertEquals(0, stats.size()); @@ -802,9 +802,9 @@ public class NetworkStatsTest { DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); NetworkStats stats = new NetworkStats(TEST_START, 3) - .addEntry(entry1) - .addEntry(entry2) - .addEntry(entry3); + .insertEntry(entry1) + .insertEntry(entry2) + .insertEntry(entry3); stats.filter(UID_ALL, INTERFACES_ALL, testTag); assertEquals(2, stats.size()); @@ -831,10 +831,10 @@ public class NetworkStatsTest { DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L); NetworkStats stats = new NetworkStats(TEST_START, 4) - .addEntry(entry1) - .addEntry(entry2) - .addEntry(entry3) - .addEntry(entry4); + .insertEntry(entry1) + .insertEntry(entry2) + .insertEntry(entry3) + .insertEntry(entry4); stats.filterDebugEntries(); @@ -891,14 +891,14 @@ public class NetworkStatsTest { 0 /* operations */); final NetworkStats statsXt = new NetworkStats(TEST_START, 3) - .addEntry(appEntry) - .addEntry(xtRootUidEntry) - .addEntry(otherEntry); + .insertEntry(appEntry) + .insertEntry(xtRootUidEntry) + .insertEntry(otherEntry); final NetworkStats statsEbpf = new NetworkStats(TEST_START, 3) - .addEntry(appEntry) - .addEntry(ebpfRootUidEntry) - .addEntry(otherEntry); + .insertEntry(appEntry) + .insertEntry(ebpfRootUidEntry) + .insertEntry(otherEntry); statsXt.apply464xlatAdjustments(stackedIface, false); statsEbpf.apply464xlatAdjustments(stackedIface, true); @@ -945,8 +945,8 @@ public class NetworkStatsTest { 0 /* operations */); NetworkStats stats = new NetworkStats(TEST_START, 2) - .addEntry(firstEntry) - .addEntry(secondEntry); + .insertEntry(firstEntry) + .insertEntry(secondEntry); // Empty map: no adjustment stats.apply464xlatAdjustments(new ArrayMap<>(), false); diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java index f0e5774a5d..a6f7a36ff0 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java @@ -240,7 +240,7 @@ public class NetworkStatsObserversTest { // Baseline NetworkStats xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */) - .addIfaceValues(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L); + .insertEntry(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L); NetworkStats uidSnapshot = null; mStatsObservers.updateStats( @@ -264,14 +264,14 @@ public class NetworkStatsObserversTest { // Baseline NetworkStats xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */) - .addIfaceValues(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L); + .insertEntry(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L); NetworkStats uidSnapshot = null; mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); // Delta xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */) - .addIfaceValues(TEST_IFACE, BASE_BYTES + 1024L, 10L, BASE_BYTES + 2048L, 20L); + .insertEntry(TEST_IFACE, BASE_BYTES + 1024L, 10L, BASE_BYTES + 2048L, 20L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); waitForObserverToIdle(); @@ -294,14 +294,14 @@ public class NetworkStatsObserversTest { // Baseline NetworkStats xtSnapshot = new NetworkStats(TEST_START, 1 /* initialSize */) - .addIfaceValues(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L); + .insertEntry(TEST_IFACE, BASE_BYTES, 8L, BASE_BYTES, 16L); NetworkStats uidSnapshot = null; mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); // Delta xtSnapshot = new NetworkStats(TEST_START + MINUTE_IN_MILLIS, 1 /* initialSize */) - .addIfaceValues(TEST_IFACE, BASE_BYTES + THRESHOLD_BYTES, 12L, + .insertEntry(TEST_IFACE, BASE_BYTES + THRESHOLD_BYTES, 12L, BASE_BYTES + THRESHOLD_BYTES, 22L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); @@ -326,14 +326,14 @@ public class NetworkStatsObserversTest { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); // Delta uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); mStatsObservers.updateStats( @@ -359,14 +359,14 @@ public class NetworkStatsObserversTest { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); // Delta uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); mStatsObservers.updateStats( @@ -391,14 +391,14 @@ public class NetworkStatsObserversTest { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); // Delta uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); mStatsObservers.updateStats( @@ -424,14 +424,14 @@ public class NetworkStatsObserversTest { // Baseline NetworkStats xtSnapshot = null; NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */) - .addEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO, + .insertEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L); mStatsObservers.updateStats( xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces, TEST_START); // Delta uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */) - .addEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO, + .insertEntry(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L); mStatsObservers.updateStats( diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index a0f996fb7b..6be50c6560 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -263,7 +263,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { incrementCurrentTime(HOUR_IN_MILLIS); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L)); + .insertEntry(TEST_IFACE, 1024L, 1L, 2048L, 2L)); expectNetworkStatsUidDetail(buildEmptyStats()); forcePollAndWaitForIdle(); @@ -276,7 +276,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { incrementCurrentTime(DAY_IN_MILLIS); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 4096L, 4L, 8192L, 8L)); + .insertEntry(TEST_IFACE, 4096L, 4L, 8192L, 8L)); expectNetworkStatsUidDetail(buildEmptyStats()); forcePollAndWaitForIdle(); @@ -306,13 +306,13 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { incrementCurrentTime(HOUR_IN_MILLIS); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 1024L, 8L, 2048L, 16L)); + .insertEntry(TEST_IFACE, 1024L, 8L, 2048L, 16L)); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 256L, 2L, 128L, 1L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L) - .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 256L, 2L, 128L, 1L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L) + .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L)); mService.setUidForeground(UID_RED, false); mService.incrementOperationCount(UID_RED, 0xFAAD, 4); mService.setUidForeground(UID_RED, true); @@ -375,7 +375,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { incrementCurrentTime(2 * HOUR_IN_MILLIS); expectSettings(0L, HOUR_IN_MILLIS, WEEK_IN_MILLIS); expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 512L, 4L, 512L, 4L)); + .insertEntry(TEST_IFACE, 512L, 4L, 512L, 4L)); expectNetworkStatsUidDetail(buildEmptyStats()); forcePollAndWaitForIdle(); @@ -415,11 +415,11 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { incrementCurrentTime(HOUR_IN_MILLIS); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L)); + .insertEntry(TEST_IFACE, 2048L, 16L, 512L, 4L)); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) - .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) + .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); mService.incrementOperationCount(UID_RED, 0xF00D, 10); forcePollAndWaitForIdle(); @@ -437,11 +437,11 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectDefaultSettings(); states = new NetworkState[] {buildMobile3gState(IMSI_2)}; expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L)); + .insertEntry(TEST_IFACE, 2048L, 16L, 512L, 4L)); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) - .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) + .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]); forcePollAndWaitForIdle(); @@ -451,12 +451,12 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { incrementCurrentTime(HOUR_IN_MILLIS); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 2176L, 17L, 1536L, 12L)); + .insertEntry(TEST_IFACE, 2176L, 17L, 1536L, 12L)); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) - .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L) - .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) + .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 640L, 5L, 1024L, 8L, 0L) + .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L)); mService.incrementOperationCount(UID_BLUE, 0xFAAD, 10); forcePollAndWaitForIdle(); @@ -488,12 +488,13 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { incrementCurrentTime(HOUR_IN_MILLIS); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 4128L, 258L, 544L, 34L)); + .insertEntry(TEST_IFACE, 4128L, 258L, 544L, 34L)); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) - .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L) - .addEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) + .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, + 4096L, 258L, 512L, 32L, 0L) + .insertEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); mService.incrementOperationCount(UID_RED, 0xFAAD, 10); forcePollAndWaitForIdle(); @@ -509,12 +510,13 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // special "removed" bucket. expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 4128L, 258L, 544L, 34L)); + .insertEntry(TEST_IFACE, 4128L, 258L, 544L, 34L)); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) - .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L) - .addEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) + .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, + 4096L, 258L, 512L, 32L, 0L) + .insertEntry(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); final Intent intent = new Intent(ACTION_UID_REMOVED); intent.putExtra(EXTRA_UID, UID_BLUE); mServiceContext.sendBroadcast(intent); @@ -546,8 +548,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)); mService.incrementOperationCount(UID_RED, 0xF00D, 5); forcePollAndWaitForIdle(); @@ -562,8 +564,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { states = new NetworkState[] {buildMobile4gState(TEST_IFACE2)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)); mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]); forcePollAndWaitForIdle(); @@ -574,10 +576,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) - .addEntry(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L) - .addEntry(TEST_IFACE2, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) + .insertEntry(TEST_IFACE2, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L) + .insertEntry(TEST_IFACE2, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L)); mService.incrementOperationCount(UID_RED, 0xFAAD, 5); forcePollAndWaitForIdle(); @@ -601,9 +603,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) - .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) + .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L)); mService.incrementOperationCount(UID_RED, 0xF00D, 1); forcePollAndWaitForIdle(); @@ -618,9 +620,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) - .addEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) + .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, + 2048L, 16L, 1024L, 8L, 0L)); forcePollAndWaitForIdle(); // first verify entire history present @@ -664,9 +667,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3) - .addEntry(entry1) - .addEntry(entry2) - .addEntry(entry3)); + .insertEntry(entry1) + .insertEntry(entry2) + .insertEntry(entry3)); mService.incrementOperationCount(UID_RED, 0xF00D, 1); NetworkStats stats = mService.getDetailedUidStats(INTERFACES_ALL); @@ -714,11 +717,11 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { .thenReturn(augmentedIfaceFilter); when(mStatsFactory.readNetworkStatsDetail(eq(UID_ALL), any(), eq(TAG_ALL))) .thenReturn(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(uidStats)); + .insertEntry(uidStats)); when(mNetManager.getNetworkStatsTethering(STATS_PER_UID)) .thenReturn(new NetworkStats(getElapsedRealtime(), 2) - .addEntry(tetheredStats1) - .addEntry(tetheredStats2)); + .insertEntry(tetheredStats1) + .insertEntry(tetheredStats2)); NetworkStats stats = mService.getDetailedUidStats(ifaceFilter); @@ -755,8 +758,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)); mService.incrementOperationCount(UID_RED, 0xF00D, 1); forcePollAndWaitForIdle(); @@ -770,10 +773,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L)); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L) + .insertEntry(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L)); mService.setUidForeground(UID_RED, true); mService.incrementOperationCount(UID_RED, 0xFAAD, 1); @@ -814,9 +817,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // and DEFAULT_NETWORK_YES, because these three properties aren't tracked at that layer. // We layer them on top by inspecting the iface properties. expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0L)); mService.incrementOperationCount(UID_RED, 0xF00D, 1); @@ -853,9 +856,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // ROAMING_NO, because metered and roaming isn't tracked at that layer. We layer it // on top by inspecting the iface properties. expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO, + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO, DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0L) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO, + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO, DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0L)); forcePollAndWaitForIdle(); @@ -888,17 +891,17 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // Traffic seen by kernel counters (includes software tethering). final NetworkStats ifaceStats = new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 1536L, 12L, 384L, 3L); + .insertEntry(TEST_IFACE, 1536L, 12L, 384L, 3L); // Hardware tethering traffic, not seen by kernel counters. final NetworkStats tetherStatsHardware = new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 512L, 4L, 128L, 1L); + .insertEntry(TEST_IFACE, 512L, 4L, 128L, 1L); // Traffic for UID_RED. final NetworkStats uidStats = new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L); + .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L); // All tethering traffic, both hardware and software. final NetworkStats tetherStats = new NetworkStats(getElapsedRealtime(), 1) - .addEntry(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L, + .insertEntry(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L, 0L); expectNetworkStatsSummary(ifaceStats, tetherStatsHardware); @@ -957,7 +960,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { incrementCurrentTime(HOUR_IN_MILLIS); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L)); + .insertEntry(TEST_IFACE, 1024L, 1L, 2048L, 2L)); expectNetworkStatsUidDetail(buildEmptyStats()); forcePollAndWaitForIdle(); @@ -972,7 +975,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { incrementCurrentTime(DAY_IN_MILLIS); expectDefaultSettings(); expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 4096000L, 4L, 8192000L, 8L)); + .insertEntry(TEST_IFACE, 4096000L, 4L, 8192000L, 8L)); expectNetworkStatsUidDetail(buildEmptyStats()); forcePollAndWaitForIdle(); From 8dd5ea04d6ad831458df38e2a05c53f71272bb82 Mon Sep 17 00:00:00 2001 From: junyulai Date: Mon, 16 Mar 2020 13:27:28 +0800 Subject: [PATCH 100/229] [SP25] Rename functions that add Entry conditionally Currently, in NetworkStats, there are many methods to manipulate the records. However, some methods are similar and ambiguous, such as addEntry, addValues, setValues, addIfaceValues, combineValues and combineAllValues. Thus, properly grouping and renaming methods are necessary. In this change, for methods that add one record conditionally, name them addEntry. addValues -> addEntry Test: atest FrameworksNetTests ImsPhoneCallTrackerTest TetheringTests Fix: 148895143 Change-Id: I9495a198cf247e6c79100f7ac1edcea370b071de --- .../java/com/android/server/net/NetworkStatsServiceTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index 6be50c6560..b346c92391 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -1034,10 +1034,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // Create some initial traffic and report to the service. incrementCurrentTime(HOUR_IN_MILLIS); final NetworkStats expectedStats = new NetworkStats(0L, 1) - .addValues(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, + .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 1L)) - .addValues(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, + .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 1L)); cb.notifyStatsUpdated(0 /* unused */, expectedStats, expectedStats); From fa4521c1a788133a59f12833aab8c424c7eb77c1 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Thu, 12 Mar 2020 14:45:47 +0800 Subject: [PATCH 101/229] Add KeepalivePacketDataTest Add test for constructor of KeepalivePacketData and InvalidPacketException Bug: 151109466 Test: atest CtsNetTestCasesLatestSdk:android.net.KeepalivePacketDataTest on both Q and R devices Change-Id: Ic9db4b9b83ff96c87f41c5f381763c3ee8dd27c8 Merged-In: Ic9db4b9b83ff96c87f41c5f381763c3ee8dd27c8 --- .../android/net/KeepalivePacketDataTest.kt | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 tests/net/common/java/android/net/KeepalivePacketDataTest.kt diff --git a/tests/net/common/java/android/net/KeepalivePacketDataTest.kt b/tests/net/common/java/android/net/KeepalivePacketDataTest.kt new file mode 100644 index 0000000000..f464ec6cf0 --- /dev/null +++ b/tests/net/common/java/android/net/KeepalivePacketDataTest.kt @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2020 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.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS +import android.net.InvalidPacketException.ERROR_INVALID_PORT +import android.os.Build +import androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 +import com.android.testutils.DevSdkIgnoreRule +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo +import java.net.InetAddress +import java.util.Arrays +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Assert.fail +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +@SmallTest +class KeepalivePacketDataTest { + @Rule @JvmField + val ignoreRule: DevSdkIgnoreRule = DevSdkIgnoreRule() + + private val INVALID_PORT = 65537 + private val TEST_DST_PORT = 4244 + private val TEST_SRC_PORT = 4243 + + private val TESTBYTES = byteArrayOf(12, 31, 22, 44) + private val TEST_SRC_ADDRV4 = "198.168.0.2".address() + private val TEST_DST_ADDRV4 = "198.168.0.1".address() + private val TEST_ADDRV6 = "2001:db8::1".address() + + private fun String.address() = InetAddresses.parseNumericAddress(this) + + // Add for test because constructor of KeepalivePacketData is protected. + private inner class TestKeepalivePacketData( + srcAddress: InetAddress? = TEST_SRC_ADDRV4, + srcPort: Int = TEST_SRC_PORT, + dstAddress: InetAddress? = TEST_DST_ADDRV4, + dstPort: Int = TEST_DST_PORT, + data: ByteArray = TESTBYTES + ) : KeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, data) + + @Test + @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testConstructor() { + var data: TestKeepalivePacketData + + try { + data = TestKeepalivePacketData(srcAddress = null) + fail("Null src address should cause exception") + } catch (e: InvalidPacketException) { + assertEquals(e.error, ERROR_INVALID_IP_ADDRESS) + } + + try { + data = TestKeepalivePacketData(dstAddress = null) + fail("Null dst address should cause exception") + } catch (e: InvalidPacketException) { + assertEquals(e.error, ERROR_INVALID_IP_ADDRESS) + } + + try { + data = TestKeepalivePacketData(dstAddress = TEST_ADDRV6) + fail("Ip family mismatched should cause exception") + } catch (e: InvalidPacketException) { + assertEquals(e.error, ERROR_INVALID_IP_ADDRESS) + } + + try { + data = TestKeepalivePacketData(srcPort = INVALID_PORT) + fail("Invalid srcPort should cause exception") + } catch (e: InvalidPacketException) { + assertEquals(e.error, ERROR_INVALID_PORT) + } + + try { + data = TestKeepalivePacketData(dstPort = INVALID_PORT) + fail("Invalid dstPort should cause exception") + } catch (e: InvalidPacketException) { + assertEquals(e.error, ERROR_INVALID_PORT) + } + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testSrcAddress() = assertEquals(TEST_SRC_ADDRV4, TestKeepalivePacketData().srcAddress) + + @Test + @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testDstAddress() = assertEquals(TEST_DST_ADDRV4, TestKeepalivePacketData().dstAddress) + + @Test + @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testSrcPort() = assertEquals(TEST_SRC_PORT, TestKeepalivePacketData().srcPort) + + @Test + @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testDstPort() = assertEquals(TEST_DST_PORT, TestKeepalivePacketData().dstPort) + + @Test + @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testPacket() = assertTrue(Arrays.equals(TESTBYTES, TestKeepalivePacketData().packet)) +} \ No newline at end of file From b05dcda675daa0454ff4fa732c3e93b975df3838 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Fri, 13 Mar 2020 16:37:04 +0800 Subject: [PATCH 102/229] Add NattKeepalivePacketDataTest Add test for constructor and parcel Test: atest CtsNetTestCasesLatestSdk:android.net.NattKeepalivePacketDataTest on both Q and R devices Bug: 151402211 Change-Id: I97015365604be1846e3ecbaf60ac99e334705565 Merged-In: I97015365604be1846e3ecbaf60ac99e334705565 --- .../android/net/NattKeepalivePacketData.java | 17 +++ .../net/NattKeepalivePacketDataTest.kt | 114 ++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 tests/net/common/java/android/net/NattKeepalivePacketDataTest.kt diff --git a/core/java/android/net/NattKeepalivePacketData.java b/core/java/android/net/NattKeepalivePacketData.java index bd39c13ba0..29da4952da 100644 --- a/core/java/android/net/NattKeepalivePacketData.java +++ b/core/java/android/net/NattKeepalivePacketData.java @@ -20,6 +20,7 @@ import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS; import static android.net.InvalidPacketException.ERROR_INVALID_PORT; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.util.IpUtils; import android.os.Parcel; @@ -30,6 +31,7 @@ import java.net.Inet4Address; import java.net.InetAddress; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.Objects; /** @hide */ @SystemApi @@ -121,4 +123,19 @@ public final class NattKeepalivePacketData extends KeepalivePacketData implement return new NattKeepalivePacketData[size]; } }; + + @Override + public boolean equals(@Nullable final Object o) { + if (!(o instanceof NattKeepalivePacketData)) return false; + final NattKeepalivePacketData other = (NattKeepalivePacketData) o; + return this.srcAddress.equals(other.srcAddress) + && this.dstAddress.equals(other.dstAddress) + && this.srcPort == other.srcPort + && this.dstPort == other.dstPort; + } + + @Override + public int hashCode() { + return Objects.hash(srcAddress, dstAddress, srcPort, dstPort); + } } diff --git a/tests/net/common/java/android/net/NattKeepalivePacketDataTest.kt b/tests/net/common/java/android/net/NattKeepalivePacketDataTest.kt new file mode 100644 index 0000000000..46f39dd016 --- /dev/null +++ b/tests/net/common/java/android/net/NattKeepalivePacketDataTest.kt @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2020 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.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS +import android.net.InvalidPacketException.ERROR_INVALID_PORT +import android.net.NattSocketKeepalive.NATT_PORT +import android.os.Build +import androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 +import com.android.testutils.assertEqualBothWays +import com.android.testutils.assertFieldCountEquals +import com.android.testutils.assertParcelSane +import com.android.testutils.DevSdkIgnoreRule +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo +import com.android.testutils.parcelingRoundTrip +import java.net.InetAddress +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotEquals +import org.junit.Assert.fail +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +@SmallTest +class NattKeepalivePacketDataTest { + @Rule @JvmField + val ignoreRule: DevSdkIgnoreRule = DevSdkIgnoreRule() + + /* Refer to the definition in {@code NattKeepalivePacketData} */ + private val IPV4_HEADER_LENGTH = 20 + private val UDP_HEADER_LENGTH = 8 + + private val TEST_PORT = 4243 + private val TEST_PORT2 = 4244 + private val TEST_SRC_ADDRV4 = "198.168.0.2".address() + private val TEST_DST_ADDRV4 = "198.168.0.1".address() + private val TEST_ADDRV6 = "2001:db8::1".address() + + private fun String.address() = InetAddresses.parseNumericAddress(this) + private fun nattKeepalivePacket( + srcAddress: InetAddress? = TEST_SRC_ADDRV4, + srcPort: Int = TEST_PORT, + dstAddress: InetAddress? = TEST_DST_ADDRV4, + dstPort: Int = NATT_PORT + ) = NattKeepalivePacketData.nattKeepalivePacket(srcAddress, srcPort, dstAddress, dstPort) + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testConstructor() { + try { + nattKeepalivePacket(dstPort = TEST_PORT) + fail("Dst port is not NATT port should cause exception") + } catch (e: InvalidPacketException) { + assertEquals(e.error, ERROR_INVALID_PORT) + } + + try { + nattKeepalivePacket(srcAddress = TEST_ADDRV6) + fail("A v6 srcAddress should cause exception") + } catch (e: InvalidPacketException) { + assertEquals(e.error, ERROR_INVALID_IP_ADDRESS) + } + + try { + nattKeepalivePacket(dstAddress = TEST_ADDRV6) + fail("A v6 dstAddress should cause exception") + } catch (e: InvalidPacketException) { + assertEquals(e.error, ERROR_INVALID_IP_ADDRESS) + } + + try { + parcelingRoundTrip( + NattKeepalivePacketData(TEST_SRC_ADDRV4, TEST_PORT, TEST_DST_ADDRV4, TEST_PORT, + byteArrayOf(12, 31, 22, 44))) + fail("Invalid data should cause exception") + } catch (e: IllegalArgumentException) { } + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testParcel() { + assertParcelSane(nattKeepalivePacket(), 0) + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testEquals() { + assertEqualBothWays(nattKeepalivePacket(), nattKeepalivePacket()) + assertNotEquals(nattKeepalivePacket(dstAddress = TEST_SRC_ADDRV4), nattKeepalivePacket()) + assertNotEquals(nattKeepalivePacket(srcAddress = TEST_DST_ADDRV4), nattKeepalivePacket()) + // Test src port only because dst port have to be NATT_PORT + assertNotEquals(nattKeepalivePacket(srcPort = TEST_PORT2), nattKeepalivePacket()) + // Make sure the parceling test is updated if fields are added in the base class. + assertFieldCountEquals(5, KeepalivePacketData::class.java) + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testHashCode() { + assertEquals(nattKeepalivePacket().hashCode(), nattKeepalivePacket().hashCode()) + } +} \ No newline at end of file From 56b6a95256fd58737bf5b58df38d2121ea609a8e Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 31 Dec 2019 13:40:15 +0800 Subject: [PATCH 103/229] [SM05] Enable record mobile network stats by collapsed rat type Switch on the recording in device side. Metrics will be collected in follow-up patches which can be independently enabled/disabled. This change also fix the fail in NetworkStatsCollectionTest which caused by enabling this feature, where the rounding problem happened when records are distributed into smaller buckets and categorized into more NetworkIdentity. Test: atest FrameworksNetTests Bug: 129082217 Change-Id: If330e85330a4ff713dd420c98d42fa741eabd90a Merged-In: If330e85330a4ff713dd420c98d42fa741eabd90a (cherry picked from commit 2d4fa2c0fae8c2d79a25093d9f732a33c2f91dd4) --- .../net/NetworkStatsCollectionTest.java | 90 +++++++-------- .../server/net/NetworkStatsServiceTest.java | 109 +++++++++++++++++- 2 files changed, 149 insertions(+), 50 deletions(-) diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java index 8f90f13ce7..551498f2c0 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java @@ -319,33 +319,33 @@ public class NetworkStatsCollectionTest { assertEntry(18322, 75, 15031, 75, history.getValues(i++, null)); assertEntry(527798, 761, 78570, 652, history.getValues(i++, null)); assertEntry(527797, 760, 78570, 651, history.getValues(i++, null)); - assertEntry(10747, 50, 16838, 55, history.getValues(i++, null)); - assertEntry(10747, 49, 16838, 54, history.getValues(i++, null)); + assertEntry(10747, 50, 16839, 55, history.getValues(i++, null)); + assertEntry(10747, 49, 16837, 54, history.getValues(i++, null)); assertEntry(89191, 151, 18021, 140, history.getValues(i++, null)); assertEntry(89190, 150, 18020, 139, history.getValues(i++, null)); - assertEntry(3821, 22, 4525, 26, history.getValues(i++, null)); - assertEntry(3820, 22, 4524, 26, history.getValues(i++, null)); - assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); - assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); - assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); - assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); + assertEntry(3821, 23, 4525, 26, history.getValues(i++, null)); + assertEntry(3820, 21, 4524, 26, history.getValues(i++, null)); + assertEntry(91686, 159, 18576, 146, history.getValues(i++, null)); + assertEntry(91685, 159, 18574, 146, history.getValues(i++, null)); + assertEntry(8289, 36, 6864, 39, history.getValues(i++, null)); + assertEntry(8289, 34, 6862, 37, history.getValues(i++, null)); assertEntry(113914, 174, 18364, 157, history.getValues(i++, null)); assertEntry(113913, 173, 18364, 157, history.getValues(i++, null)); - assertEntry(11378, 49, 9261, 49, history.getValues(i++, null)); - assertEntry(11377, 48, 9261, 49, history.getValues(i++, null)); - assertEntry(201765, 328, 41808, 291, history.getValues(i++, null)); - assertEntry(201765, 328, 41807, 290, history.getValues(i++, null)); - assertEntry(106106, 218, 39917, 201, history.getValues(i++, null)); - assertEntry(106105, 217, 39917, 201, history.getValues(i++, null)); + assertEntry(11378, 49, 9261, 50, history.getValues(i++, null)); + assertEntry(11377, 48, 9261, 48, history.getValues(i++, null)); + assertEntry(201766, 328, 41808, 291, history.getValues(i++, null)); + assertEntry(201764, 328, 41807, 290, history.getValues(i++, null)); + assertEntry(106106, 219, 39918, 202, history.getValues(i++, null)); + assertEntry(106105, 216, 39916, 200, history.getValues(i++, null)); assertEquals(history.size(), i); // Slice from middle should be untouched history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS, TIME_B + HOUR_IN_MILLIS); i = 0; - assertEntry(3821, 22, 4525, 26, history.getValues(i++, null)); - assertEntry(3820, 22, 4524, 26, history.getValues(i++, null)); - assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); - assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); + assertEntry(3821, 23, 4525, 26, history.getValues(i++, null)); + assertEntry(3820, 21, 4524, 26, history.getValues(i++, null)); + assertEntry(91686, 159, 18576, 146, history.getValues(i++, null)); + assertEntry(91685, 159, 18574, 146, history.getValues(i++, null)); assertEquals(history.size(), i); } @@ -373,25 +373,25 @@ public class NetworkStatsCollectionTest { assertEntry(527797, 760, 78570, 651, history.getValues(i++, null)); // Cycle point; start data normalization assertEntry(7507, 0, 11763, 0, history.getValues(i++, null)); - assertEntry(7507, 0, 11763, 0, history.getValues(i++, null)); + assertEntry(7507, 0, 11762, 0, history.getValues(i++, null)); assertEntry(62309, 0, 12589, 0, history.getValues(i++, null)); assertEntry(62309, 0, 12588, 0, history.getValues(i++, null)); assertEntry(2669, 0, 3161, 0, history.getValues(i++, null)); assertEntry(2668, 0, 3160, 0, history.getValues(i++, null)); // Anchor point; end data normalization - assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); - assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); - assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); - assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); + assertEntry(91686, 159, 18576, 146, history.getValues(i++, null)); + assertEntry(91685, 159, 18574, 146, history.getValues(i++, null)); + assertEntry(8289, 36, 6864, 39, history.getValues(i++, null)); + assertEntry(8289, 34, 6862, 37, history.getValues(i++, null)); assertEntry(113914, 174, 18364, 157, history.getValues(i++, null)); assertEntry(113913, 173, 18364, 157, history.getValues(i++, null)); // Cycle point - assertEntry(11378, 49, 9261, 49, history.getValues(i++, null)); - assertEntry(11377, 48, 9261, 49, history.getValues(i++, null)); - assertEntry(201765, 328, 41808, 291, history.getValues(i++, null)); - assertEntry(201765, 328, 41807, 290, history.getValues(i++, null)); - assertEntry(106106, 218, 39917, 201, history.getValues(i++, null)); - assertEntry(106105, 217, 39917, 201, history.getValues(i++, null)); + assertEntry(11378, 49, 9261, 50, history.getValues(i++, null)); + assertEntry(11377, 48, 9261, 48, history.getValues(i++, null)); + assertEntry(201766, 328, 41808, 291, history.getValues(i++, null)); + assertEntry(201764, 328, 41807, 290, history.getValues(i++, null)); + assertEntry(106106, 219, 39918, 202, history.getValues(i++, null)); + assertEntry(106105, 216, 39916, 200, history.getValues(i++, null)); assertEquals(history.size(), i); // Slice from middle should be augmented @@ -399,8 +399,8 @@ public class NetworkStatsCollectionTest { TIME_B + HOUR_IN_MILLIS); i = 0; assertEntry(2669, 0, 3161, 0, history.getValues(i++, null)); assertEntry(2668, 0, 3160, 0, history.getValues(i++, null)); - assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); - assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); + assertEntry(91686, 159, 18576, 146, history.getValues(i++, null)); + assertEntry(91685, 159, 18574, 146, history.getValues(i++, null)); assertEquals(history.size(), i); } @@ -427,34 +427,34 @@ public class NetworkStatsCollectionTest { assertEntry(527798, 761, 78570, 652, history.getValues(i++, null)); assertEntry(527797, 760, 78570, 651, history.getValues(i++, null)); // Cycle point; start data normalization - assertEntry(15015, 0, 23526, 0, history.getValues(i++, null)); - assertEntry(15015, 0, 23526, 0, history.getValues(i++, null)); + assertEntry(15015, 0, 23527, 0, history.getValues(i++, null)); + assertEntry(15015, 0, 23524, 0, history.getValues(i++, null)); assertEntry(124619, 0, 25179, 0, history.getValues(i++, null)); assertEntry(124618, 0, 25177, 0, history.getValues(i++, null)); assertEntry(5338, 0, 6322, 0, history.getValues(i++, null)); assertEntry(5337, 0, 6320, 0, history.getValues(i++, null)); // Anchor point; end data normalization - assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); - assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); - assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); - assertEntry(8289, 35, 6863, 38, history.getValues(i++, null)); + assertEntry(91686, 159, 18576, 146, history.getValues(i++, null)); + assertEntry(91685, 159, 18574, 146, history.getValues(i++, null)); + assertEntry(8289, 36, 6864, 39, history.getValues(i++, null)); + assertEntry(8289, 34, 6862, 37, history.getValues(i++, null)); assertEntry(113914, 174, 18364, 157, history.getValues(i++, null)); assertEntry(113913, 173, 18364, 157, history.getValues(i++, null)); // Cycle point - assertEntry(11378, 49, 9261, 49, history.getValues(i++, null)); - assertEntry(11377, 48, 9261, 49, history.getValues(i++, null)); - assertEntry(201765, 328, 41808, 291, history.getValues(i++, null)); - assertEntry(201765, 328, 41807, 290, history.getValues(i++, null)); - assertEntry(106106, 218, 39917, 201, history.getValues(i++, null)); - assertEntry(106105, 217, 39917, 201, history.getValues(i++, null)); + assertEntry(11378, 49, 9261, 50, history.getValues(i++, null)); + assertEntry(11377, 48, 9261, 48, history.getValues(i++, null)); + assertEntry(201766, 328, 41808, 291, history.getValues(i++, null)); + assertEntry(201764, 328, 41807, 290, history.getValues(i++, null)); + assertEntry(106106, 219, 39918, 202, history.getValues(i++, null)); + assertEntry(106105, 216, 39916, 200, history.getValues(i++, null)); // Slice from middle should be augmented history = getHistory(collection, plan, TIME_B - HOUR_IN_MILLIS, TIME_B + HOUR_IN_MILLIS); i = 0; assertEntry(5338, 0, 6322, 0, history.getValues(i++, null)); assertEntry(5337, 0, 6320, 0, history.getValues(i++, null)); - assertEntry(91686, 159, 18575, 146, history.getValues(i++, null)); - assertEntry(91685, 159, 18575, 146, history.getValues(i++, null)); + assertEntry(91686, 159, 18576, 146, history.getValues(i++, null)); + assertEntry(91685, 159, 18574, 146, history.getValues(i++, null)); assertEquals(history.size(), i); } } diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index b346c92391..64c0221c58 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -42,6 +42,7 @@ import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; import static android.net.NetworkTemplate.buildTemplateMobileAll; +import static android.net.NetworkTemplate.buildTemplateMobileWithRatType; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; import static android.net.TrafficStats.MB_IN_BYTES; import static android.net.TrafficStats.UID_REMOVED; @@ -60,11 +61,13 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.AlarmManager; import android.app.usage.NetworkStatsManager; import android.content.Context; @@ -92,6 +95,8 @@ import android.os.Message; import android.os.Messenger; import android.os.PowerManager; import android.os.SimpleClock; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; import android.telephony.TelephonyManager; import androidx.test.InstrumentationRegistry; @@ -163,11 +168,14 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { private @Mock NetworkStatsSettings mSettings; private @Mock IBinder mBinder; private @Mock AlarmManager mAlarmManager; + private @Mock TelephonyManager mTelephonyManager; private HandlerThread mHandlerThread; private NetworkStatsService mService; private INetworkStatsSession mSession; private INetworkManagementEventObserver mNetworkObserver; + @Nullable + private PhoneStateListener mPhoneStateListener; private final Clock mClock = new SimpleClock(ZoneOffset.UTC) { @Override @@ -195,7 +203,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mHandlerThread = new HandlerThread("HandlerThread"); final NetworkStatsService.Dependencies deps = makeDependencies(); mService = new NetworkStatsService(mServiceContext, mNetManager, mAlarmManager, wakeLock, - mClock, mServiceContext.getSystemService(TelephonyManager.class), mSettings, + mClock, mTelephonyManager, mSettings, mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir), deps); mElapsedRealtime = 0L; @@ -216,6 +224,12 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { ArgumentCaptor.forClass(INetworkManagementEventObserver.class); verify(mNetManager).registerObserver(networkObserver.capture()); mNetworkObserver = networkObserver.getValue(); + + // Capture the phone state listener that created by service. + final ArgumentCaptor phoneStateListenerCaptor = + ArgumentCaptor.forClass(PhoneStateListener.class); + verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), anyInt()); + mPhoneStateListener = phoneStateListenerCaptor.getValue(); } @NonNull @@ -534,7 +548,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { } @Test - public void testUid3g4gCombinedByTemplate() throws Exception { + public void testUid3gWimaxCombinedByTemplate() throws Exception { // pretend that network comes online expectDefaultSettings(); NetworkState[] states = new NetworkState[] {buildMobile3gState(IMSI_1)}; @@ -558,10 +572,10 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { assertUidTotal(sTemplateImsi1, UID_RED, 1024L, 8L, 1024L, 8L, 5); - // now switch over to 4g network + // now switch over to wimax network incrementCurrentTime(HOUR_IN_MILLIS); expectDefaultSettings(); - states = new NetworkState[] {buildMobile4gState(TEST_IFACE2)}; + states = new NetworkState[] {buildWimaxState(TEST_IFACE2)}; expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) @@ -588,6 +602,89 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { assertUidTotal(sTemplateImsi1, UID_RED, 1536L, 12L, 1280L, 10L, 10); } + @Test + public void testMobileStatsByRatType() throws Exception { + final NetworkTemplate template3g = + buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS); + final NetworkTemplate template4g = + buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_LTE); + final NetworkTemplate template5g = + buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_NR); + final NetworkState[] states = new NetworkState[]{buildMobile3gState(IMSI_1)}; + + // 3G network comes online. + expectNetworkStatsSummary(buildEmptyStats()); + expectNetworkStatsUidDetail(buildEmptyStats()); + + setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS); + mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), + new VpnInfo[0]); + + // Create some traffic. + incrementCurrentTime(MINUTE_IN_MILLIS); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) + .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, + 12L, 18L, 14L, 1L, 0L))); + forcePollAndWaitForIdle(); + + // Verify 3g templates gets stats. + assertUidTotal(sTemplateImsi1, UID_RED, 12L, 18L, 14L, 1L, 0); + assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0); + assertUidTotal(template4g, UID_RED, 0L, 0L, 0L, 0L, 0); + assertUidTotal(template5g, UID_RED, 0L, 0L, 0L, 0L, 0); + + // 4G network comes online. + incrementCurrentTime(MINUTE_IN_MILLIS); + setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_LTE); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) + // Append more traffic on existing 3g stats entry. + .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, + 16L, 22L, 17L, 2L, 0L)) + // Add entry that is new on 4g. + .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, + 33L, 27L, 8L, 10L, 1L))); + forcePollAndWaitForIdle(); + + // Verify ALL_MOBILE template gets all. 3g template counters do not increase. + assertUidTotal(sTemplateImsi1, UID_RED, 49L, 49L, 25L, 12L, 1); + assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0); + // Verify 4g template counts appended stats on existing entry and newly created entry. + assertUidTotal(template4g, UID_RED, 4L + 33L, 4L + 27L, 3L + 8L, 1L + 10L, 1); + // Verify 5g template doesn't get anything since no traffic is generated on 5g. + assertUidTotal(template5g, UID_RED, 0L, 0L, 0L, 0L, 0); + + // 5g network comes online. + incrementCurrentTime(MINUTE_IN_MILLIS); + setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_NR); + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) + // Existing stats remains. + .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, + 16L, 22L, 17L, 2L, 0L)) + .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, + 33L, 27L, 8L, 10L, 1L)) + // Add some traffic on 5g. + .addEntry(new NetworkStats.Entry(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, + 5L, 13L, 31L, 9L, 2L))); + forcePollAndWaitForIdle(); + + // Verify ALL_MOBILE template gets all. + assertUidTotal(sTemplateImsi1, UID_RED, 54L, 62L, 56L, 21L, 3); + // 3g/4g template counters do not increase. + assertUidTotal(template3g, UID_RED, 12L, 18L, 14L, 1L, 0); + assertUidTotal(template4g, UID_RED, 4L + 33L, 4L + 27L, 3L + 8L, 1L + 10L, 1); + // Verify 5g template gets the 5g count. + assertUidTotal(template5g, UID_RED, 5L, 13L, 31L, 9L, 2); + } + + // TODO: support per IMSI state + private void setMobileRatTypeAndWaitForIdle(int ratType) { + final ServiceState mockSs = mock(ServiceState.class); + when(mockSs.getDataNetworkType()).thenReturn(ratType); + mPhoneStateListener.onServiceStateChanged(mockSs); + + HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT); + } + @Test public void testSummaryForAllUid() throws Exception { // pretend that network comes online @@ -1242,6 +1339,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { final NetworkCapabilities capabilities = new NetworkCapabilities(); capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !isMetered); capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true); + capabilities.addTransportType(NetworkCapabilities.TRANSPORT_WIFI); return new NetworkState(info, prop, capabilities, WIFI_NETWORK, null, TEST_SSID); } @@ -1259,10 +1357,11 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { final NetworkCapabilities capabilities = new NetworkCapabilities(); capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false); capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming); + capabilities.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); return new NetworkState(info, prop, capabilities, MOBILE_NETWORK, subscriberId, null); } - private static NetworkState buildMobile4gState(String iface) { + private static NetworkState buildWimaxState(@NonNull String iface) { final NetworkInfo info = new NetworkInfo(TYPE_WIMAX, 0, null, null); info.setDetailedState(DetailedState.CONNECTED, null, null); final LinkProperties prop = new LinkProperties(); From 0819fa72467308af459fd8f25bfb55633efac3a7 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Tue, 17 Mar 2020 15:26:02 +0000 Subject: [PATCH 104/229] Make LinkPropertiesTest backwards compatible LinkPropertiesTest must be backwards compatible with Q for CTS. In Q 4 fields were added: DhcpServerAddress, WakeOnLanSupported, CaptivePortalApiUrl, CaptivePortalData. The new test only tests these fields on R and above. testLinkPropertiesParcelable_Q still verifies that there are 14 fields on Q, so the 4 extra fields can be ignored. The changes use androidx.core.os.BuildCompat.isAtLeastR(), so androidx.core_core is added as a dependency to FrameworksNetCommonTests. Test: atest CtsNetTestCasesLatestSdk:android.net.LinkPropertiesTest on Q and R devices Bug: 150918852 Change-Id: I570efa4eb483a717d4204a18473d02653a69f46d Merged-In: I570efa4eb483a717d4204a18473d02653a69f46d (cherry picked from commit b4c981c7c683564dde0693fa05bd02618f7dcba3) --- tests/net/common/Android.bp | 1 + .../java/android/net/LinkPropertiesTest.java | 101 ++++++++++++------ 2 files changed, 72 insertions(+), 30 deletions(-) diff --git a/tests/net/common/Android.bp b/tests/net/common/Android.bp index e44d46088c..46d680fc45 100644 --- a/tests/net/common/Android.bp +++ b/tests/net/common/Android.bp @@ -20,6 +20,7 @@ java_library { name: "FrameworksNetCommonTests", srcs: ["java/**/*.java", "java/**/*.kt"], static_libs: [ + "androidx.core_core", "androidx.test.rules", "junit", "mockito-target-minus-junit4", diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java index 48b65e592f..2cbe48ce76 100644 --- a/tests/net/common/java/android/net/LinkPropertiesTest.java +++ b/tests/net/common/java/android/net/LinkPropertiesTest.java @@ -29,12 +29,19 @@ import static org.junit.Assert.fail; import android.net.LinkProperties.ProvisioningChange; import android.net.util.LinkPropertiesUtils.CompareResult; +import android.os.Build; import android.system.OsConstants; import android.util.ArraySet; +import androidx.core.os.BuildCompat; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.testutils.DevSdkIgnoreRule; +import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; + +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,6 +57,9 @@ import java.util.Set; @RunWith(AndroidJUnit4.class) @SmallTest public class LinkPropertiesTest { + @Rule + public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); + private static final InetAddress ADDRV4 = address("75.208.6.1"); private static final InetAddress ADDRV6 = address("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); private static final InetAddress DNS1 = address("75.208.7.1"); @@ -76,13 +86,23 @@ public class LinkPropertiesTest { private static final LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128); private static final LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64"); private static final Uri CAPPORT_API_URL = Uri.parse("https://test.example.com/capportapi"); - private static final CaptivePortalData CAPPORT_DATA = new CaptivePortalData.Builder() - .setVenueInfoUrl(Uri.parse("https://test.example.com/venue")).build(); + + // CaptivePortalData cannot be in a constant as it does not exist on Q. + // The test runner also crashes when scanning for tests if it is a return type. + private static Object getCaptivePortalData() { + return new CaptivePortalData.Builder() + .setVenueInfoUrl(Uri.parse("https://test.example.com/venue")).build(); + } private static InetAddress address(String addrString) { return InetAddresses.parseNumericAddress(addrString); } + private static boolean isAtLeastR() { + // BuildCompat.isAtLeastR is documented to return false on release SDKs (including R) + return Build.VERSION.SDK_INT > Build.VERSION_CODES.Q || BuildCompat.isAtLeastR(); + } + private void checkEmpty(final LinkProperties lp) { assertEquals(0, lp.getAllInterfaceNames().size()); assertEquals(0, lp.getAllAddresses().size()); @@ -98,14 +118,17 @@ public class LinkPropertiesTest { assertNull(lp.getHttpProxy()); assertNull(lp.getTcpBufferSizes()); assertNull(lp.getNat64Prefix()); - assertNull(lp.getDhcpServerAddress()); assertFalse(lp.isProvisioned()); assertFalse(lp.isIpv4Provisioned()); assertFalse(lp.isIpv6Provisioned()); assertFalse(lp.isPrivateDnsActive()); - assertFalse(lp.isWakeOnLanSupported()); - assertNull(lp.getCaptivePortalApiUrl()); - assertNull(lp.getCaptivePortalData()); + + if (isAtLeastR()) { + assertNull(lp.getDhcpServerAddress()); + assertFalse(lp.isWakeOnLanSupported()); + assertNull(lp.getCaptivePortalApiUrl()); + assertNull(lp.getCaptivePortalData()); + } } private LinkProperties makeTestObject() { @@ -127,10 +150,12 @@ public class LinkPropertiesTest { lp.setMtu(MTU); lp.setTcpBufferSizes(TCP_BUFFER_SIZES); lp.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96")); - lp.setDhcpServerAddress(DHCPSERVER); - lp.setWakeOnLanSupported(true); - lp.setCaptivePortalApiUrl(CAPPORT_API_URL); - lp.setCaptivePortalData(CAPPORT_DATA); + if (isAtLeastR()) { + lp.setDhcpServerAddress(DHCPSERVER); + lp.setWakeOnLanSupported(true); + lp.setCaptivePortalApiUrl(CAPPORT_API_URL); + lp.setCaptivePortalData((CaptivePortalData) getCaptivePortalData()); + } return lp; } @@ -169,14 +194,19 @@ public class LinkPropertiesTest { assertTrue(source.isIdenticalTcpBufferSizes(target)); assertTrue(target.isIdenticalTcpBufferSizes(source)); - assertTrue(source.isIdenticalWakeOnLan(target)); - assertTrue(target.isIdenticalWakeOnLan(source)); + if (isAtLeastR()) { + assertTrue(source.isIdenticalDhcpServerAddress(target)); + assertTrue(source.isIdenticalDhcpServerAddress(source)); - assertTrue(source.isIdenticalCaptivePortalApiUrl(target)); - assertTrue(target.isIdenticalCaptivePortalApiUrl(source)); + assertTrue(source.isIdenticalWakeOnLan(target)); + assertTrue(target.isIdenticalWakeOnLan(source)); - assertTrue(source.isIdenticalCaptivePortalData(target)); - assertTrue(target.isIdenticalCaptivePortalData(source)); + assertTrue(source.isIdenticalCaptivePortalApiUrl(target)); + assertTrue(target.isIdenticalCaptivePortalApiUrl(source)); + + assertTrue(source.isIdenticalCaptivePortalData(target)); + assertTrue(target.isIdenticalCaptivePortalData(source)); + } // Check result of equals(). assertTrue(source.equals(target)); @@ -943,8 +973,7 @@ public class LinkPropertiesTest { assertEquals(new ArraySet<>(expectRemoved), (new ArraySet<>(result.removed))); } - @Test - public void testLinkPropertiesParcelable() throws Exception { + private static LinkProperties makeLinkPropertiesForParceling() { LinkProperties source = new LinkProperties(); source.setInterfaceName(NAME); @@ -978,16 +1007,27 @@ public class LinkPropertiesTest { source.setNat64Prefix(new IpPrefix("2001:db8:1:2:64:64::/96")); - source.setWakeOnLanSupported(true); - source.setCaptivePortalApiUrl(CAPPORT_API_URL); - source.setCaptivePortalData(CAPPORT_DATA); - - source.setDhcpServerAddress((Inet4Address) GATEWAY1); - final LinkProperties stacked = new LinkProperties(); stacked.setInterfaceName("test-stacked"); source.addStackedLink(stacked); + return source; + } + + @Test @IgnoreAfter(Build.VERSION_CODES.Q) + public void testLinkPropertiesParcelable_Q() throws Exception { + final LinkProperties source = makeLinkPropertiesForParceling(); + assertParcelSane(source, 14 /* fieldCount */); + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testLinkPropertiesParcelable() throws Exception { + final LinkProperties source = makeLinkPropertiesForParceling(); + + source.setWakeOnLanSupported(true); + source.setCaptivePortalApiUrl(CAPPORT_API_URL); + source.setCaptivePortalData((CaptivePortalData) getCaptivePortalData()); + source.setDhcpServerAddress((Inet4Address) GATEWAY1); assertParcelSane(source.makeSensitiveFieldsParcelingCopy(), 18 /* fieldCount */); // Verify that without using a sensitiveFieldsParcelingCopy, sensitive fields are cleared. @@ -997,7 +1037,8 @@ public class LinkPropertiesTest { assertEquals(sanitized, parcelingRoundTrip(source)); } - @Test + // Parceling of the scope was broken until Q-QPR2 + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testLinkLocalDnsServerParceling() throws Exception { final String strAddress = "fe80::1%lo"; final LinkProperties lp = new LinkProperties(); @@ -1120,7 +1161,7 @@ public class LinkPropertiesTest { assertFalse(lp.isPrivateDnsActive()); } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testDhcpServerAddress() { final LinkProperties lp = makeTestObject(); assertEquals(DHCPSERVER, lp.getDhcpServerAddress()); @@ -1129,7 +1170,7 @@ public class LinkPropertiesTest { assertNull(lp.getDhcpServerAddress()); } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testWakeOnLanSupported() { final LinkProperties lp = makeTestObject(); assertTrue(lp.isWakeOnLanSupported()); @@ -1138,7 +1179,7 @@ public class LinkPropertiesTest { assertFalse(lp.isWakeOnLanSupported()); } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testCaptivePortalApiUrl() { final LinkProperties lp = makeTestObject(); assertEquals(CAPPORT_API_URL, lp.getCaptivePortalApiUrl()); @@ -1147,10 +1188,10 @@ public class LinkPropertiesTest { assertNull(lp.getCaptivePortalApiUrl()); } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testCaptivePortalData() { final LinkProperties lp = makeTestObject(); - assertEquals(CAPPORT_DATA, lp.getCaptivePortalData()); + assertEquals(getCaptivePortalData(), lp.getCaptivePortalData()); lp.clear(); assertNull(lp.getCaptivePortalData()); From fce6aad2beeb2b075c4ef7d775a787c0c6649640 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Tue, 17 Mar 2020 16:02:25 +0000 Subject: [PATCH 105/229] Move sensitive field parceling bool to constructor This addresses API review comments recommending to use a copy constructor with additional parameters instead of a dedicated method. makeSensitiveFieldsParcelingCopy becomes LinkProperties(base, true). Bug: 150877475 Test: atest FrameworksNetTests NetworkStackTests NetworkStackNextTests Merged-In: Ib145ca7f36dcbee6ef47d09862a181fc04a28f03 (cherry picked from commit bf091021d332804e875d7fd3424340e32b896cce) Change-Id: I98449430ca5b11f5a62ba43683663bd82650e817 --- core/java/android/net/LinkProperties.java | 30 ++++++++----------- .../android/server/ConnectivityService.java | 2 +- .../java/android/net/LinkPropertiesTest.java | 3 +- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 732ceb560c..fe3f91940e 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -167,7 +167,19 @@ public final class LinkProperties implements Parcelable { this(source, false /* parcelSensitiveFields */); } - private LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) { + /** + * Create a copy of a {@link LinkProperties} that may preserve fields that were set + * based on the permissions of the process that originally received it. + * + *

By default {@link LinkProperties} does not preserve such fields during parceling, as + * they should not be shared outside of the process that receives them without appropriate + * checks. + * @param parcelSensitiveFields Whether the sensitive fields should be kept when parceling + * @hide + */ + @SystemApi + @TestApi + public LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) { mParcelSensitiveFields = parcelSensitiveFields; if (source == null) return; mIfaceName = source.mIfaceName; @@ -1560,22 +1572,6 @@ public final class LinkProperties implements Parcelable { return mCaptivePortalData; } - /** - * Create a copy of this {@link LinkProperties} that will preserve fields that were set - * based on the permissions of the process that received this {@link LinkProperties}. - * - *

By default {@link LinkProperties} does not preserve such fields during parceling, as - * they should not be shared outside of the process that receives them without appropriate - * checks. - * @hide - */ - @SystemApi - @TestApi - @NonNull - public LinkProperties makeSensitiveFieldsParcelingCopy() { - return new LinkProperties(this, true /* parcelSensitiveFields */); - } - /** * Compares this {@code LinkProperties} instance against the target * LinkProperties in {@code obj}. Two LinkPropertieses are equal if diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index deae459e39..8e7cea5ad3 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1710,7 +1710,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } if (checkSettingsPermission(callerPid, callerUid)) { - return lp.makeSensitiveFieldsParcelingCopy(); + return new LinkProperties(lp, true /* parcelSensitiveFields */); } final LinkProperties newLp = new LinkProperties(lp); diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java index 2cbe48ce76..2b5720a47e 100644 --- a/tests/net/common/java/android/net/LinkPropertiesTest.java +++ b/tests/net/common/java/android/net/LinkPropertiesTest.java @@ -1028,7 +1028,8 @@ public class LinkPropertiesTest { source.setCaptivePortalApiUrl(CAPPORT_API_URL); source.setCaptivePortalData((CaptivePortalData) getCaptivePortalData()); source.setDhcpServerAddress((Inet4Address) GATEWAY1); - assertParcelSane(source.makeSensitiveFieldsParcelingCopy(), 18 /* fieldCount */); + assertParcelSane(new LinkProperties(source, true /* parcelSensitiveFields */), + 18 /* fieldCount */); // Verify that without using a sensitiveFieldsParcelingCopy, sensitive fields are cleared. final LinkProperties sanitized = new LinkProperties(source); From 41c2272a19dfe6bc8da5334ffe730aae65fad507 Mon Sep 17 00:00:00 2001 From: Lucas Lin Date: Wed, 18 Mar 2020 04:50:58 +0000 Subject: [PATCH 106/229] Add version check to prevent test fail on Android Q Include androidx.core_core for androidx.core.os.BuildCompat. Bug: 151293251 Test: atest CtsNetTestCasesLatestSdk:android.net.NetworkCapabilitiesTest Change-Id: I8356aed1bdf2646671d045e10c9d0c8115c10ca5 Merged-In: I73ef7eececec757a6e9683b231bf73fcd8d49f8d --- .../android/net/NetworkCapabilitiesTest.java | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index efea91ab91..9fe1883010 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -48,9 +48,11 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.os.Build; import android.test.suitebuilder.annotation.SmallTest; import android.util.ArraySet; +import androidx.core.os.BuildCompat; import androidx.test.runner.AndroidJUnit4; import org.junit.Test; @@ -64,6 +66,13 @@ public class NetworkCapabilitiesTest { private static final String TEST_SSID = "TEST_SSID"; private static final String DIFFERENT_TEST_SSID = "DIFFERENT_TEST_SSID"; + private boolean isAtLeastR() { + // BuildCompat.isAtLeastR() is used to check the Android version before releasing Android R. + // Build.VERSION.SDK_INT > Build.VERSION_CODES.Q is used to check the Android version after + // releasing Android R. + return BuildCompat.isAtLeastR() || Build.VERSION.SDK_INT > Build.VERSION_CODES.Q; + } + @Test public void testMaybeMarkCapabilitiesRestricted() { // verify EIMS is restricted @@ -269,25 +278,36 @@ public class NetworkCapabilitiesTest { .setUids(uids) .addCapability(NET_CAPABILITY_EIMS) .addCapability(NET_CAPABILITY_NOT_METERED); - netCap.setOwnerUid(123); + if (isAtLeastR()) { + netCap.setOwnerUid(123); + } assertParcelingIsLossless(netCap); netCap.setSSID(TEST_SSID); - assertParcelSane(netCap, 15); + testParcelSane(netCap); } @Test public void testParcelNetworkCapabilitiesWithRequestorUidAndPackageName() { final NetworkCapabilities netCap = new NetworkCapabilities() .addCapability(NET_CAPABILITY_INTERNET) - .setRequestorUid(9304) - .setRequestorPackageName("com.android.test") .addCapability(NET_CAPABILITY_EIMS) .addCapability(NET_CAPABILITY_NOT_METERED); + if (isAtLeastR()) { + netCap.setRequestorPackageName("com.android.test"); + netCap.setRequestorUid(9304); + } assertParcelingIsLossless(netCap); netCap.setSSID(TEST_SSID); - assertParcelSane(netCap, 15); + testParcelSane(netCap); } + private void testParcelSane(NetworkCapabilities cap) { + if (isAtLeastR()) { + assertParcelSane(cap, 15); + } else { + assertParcelSane(cap, 11); + } + } @Test public void testOemPaid() { From aa5dfd816aecae9fea2afe51c965d530a42d63e8 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Wed, 18 Mar 2020 18:31:39 +0900 Subject: [PATCH 107/229] Remove usage of Context.NETWORK_STACK_SERVICE The NetworkStack.getService() API should be used instead. Bug: 151243982 Test: atest FrameworksNetTests TetheringTests Manual tethering test Change-Id: I7855090bffbe895c8349ad4903b8f2eb55515f0b --- tests/net/java/com/android/server/ConnectivityServiceTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 8c0c36b89b..5c5e22525f 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -428,7 +428,6 @@ public class ConnectivityServiceTest { public Object getSystemService(String name) { if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm; if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager; - if (Context.NETWORK_STACK_SERVICE.equals(name)) return mNetworkStack; if (Context.USER_SERVICE.equals(name)) return mUserManager; if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager; if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager; From 84c3f44278a580c621cde382d6eb02d6d25ae46a Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Wed, 18 Mar 2020 10:01:45 +0000 Subject: [PATCH 108/229] Fix flaky ConnectivityServiceTest#testNetworkFactoryUnregister Test: atest ConnectivityServiceTest#testNetworkFactoryUnregister \ --geneate-new-metrics 100 Bug: 151792032 Change-Id: I1ee7a26186885d3a79a32ec9e45f5bcd656a6680 Merged-In: I1ee7a26186885d3a79a32ec9e45f5bcd656a6680 Merged-In: Iece9e8ad5c51170cd404ac995d0005392d37fe0c (cherry picked from commit 31c26cdbeb35a6fd6a53a1c25cce6d36b825bf41) --- tests/net/java/com/android/server/ConnectivityServiceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index c21772a5d1..44216e804f 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -2464,8 +2464,8 @@ public class ConnectivityServiceTest { final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(), mServiceContext, "testFactory", filter); // Register the factory and don't be surprised when the default request arrives. - testFactory.register(); testFactory.expectAddRequestsWithScores(0); + testFactory.register(); testFactory.waitForNetworkRequests(1); testFactory.setScoreFilter(42); From 6ccc8aa265ff62e57374dff081fec927f633dc4e Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Wed, 18 Mar 2020 07:52:25 +0000 Subject: [PATCH 109/229] mtu: Add MTU parameter to Routes - Change route to update existing route - MTU parameter added to AddRoute Bug: 142892223 Test: unit test Change-Id: I2164808ef628eb7c12e875f0bde7f5151bf6a5b5 Merged-In: Ie339d0cee5be12c2232a4631fed61219a0facc64 (cherry picked from commit e521f07e8b03102f1b510a3fb401993513d9c127) --- core/java/android/net/LinkProperties.java | 36 +++++-- core/java/android/net/RouteInfo.java | 20 ++++ .../android/server/ConnectivityService.java | 67 +++++++++++-- .../server/ConnectivityServiceTest.java | 95 ++++++++++++++++++- 4 files changed, 196 insertions(+), 22 deletions(-) diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 732ceb560c..02e9b5061f 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -674,17 +674,29 @@ public final class LinkProperties implements Parcelable { route.getDestination(), route.getGateway(), mIfaceName, - route.getType()); + route.getType(), + route.getMtu()); + } + + private int findRouteIndexByDestination(RouteInfo route) { + for (int i = 0; i < mRoutes.size(); i++) { + if (mRoutes.get(i).isSameDestinationAs(route)) { + return i; + } + } + return -1; } /** - * Adds a {@link RouteInfo} to this {@code LinkProperties}, if not present. If the - * {@link RouteInfo} had an interface name set and that differs from the interface set for this - * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown. The proper + * Adds a {@link RouteInfo} to this {@code LinkProperties}, if a {@link RouteInfo} + * with the same destination exists with different properties (e.g., different MTU), + * it will be updated. If the {@link RouteInfo} had an interface name set and + * that differs from the interface set for this {@code LinkProperties} an + * {@link IllegalArgumentException} will be thrown. The proper * course is to add either un-named or properly named {@link RouteInfo}. * * @param route A {@link RouteInfo} to add to this object. - * @return {@code false} if the route was already present, {@code true} if it was added. + * @return {@code true} was added or updated, false otherwise. */ public boolean addRoute(@NonNull RouteInfo route) { String routeIface = route.getInterface(); @@ -694,11 +706,20 @@ public final class LinkProperties implements Parcelable { + " vs. " + mIfaceName); } route = routeWithInterface(route); - if (!mRoutes.contains(route)) { + + int i = findRouteIndexByDestination(route); + if (i == -1) { + // Route was not present. Add it. mRoutes.add(route); return true; + } else if (mRoutes.get(i).equals(route)) { + // Route was present and has same properties. Do nothing. + return false; + } else { + // Route was present and has different properties. Update it. + mRoutes.set(i, route); + return true; } - return false; } /** @@ -706,6 +727,7 @@ public final class LinkProperties implements Parcelable { * specify an interface and the interface must match the interface of this * {@code LinkProperties}, or it will not be removed. * + * @param route A {@link RouteInfo} specifying the route to remove. * @return {@code true} if the route was removed, {@code false} if it was not present. * * @hide diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index 2b9e9fe81b..fec2df412a 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -526,6 +526,26 @@ public final class RouteInfo implements Parcelable { mType == target.getType() && mMtu == target.getMtu(); } + /** + * Compares this RouteInfo object against the specified object and indicates if the + * destinations of both routes are equal. + * @return {@code true} if the route destinations are equal, {@code false} otherwise. + * + * @hide + */ + public boolean isSameDestinationAs(@Nullable Object obj) { + if (this == obj) return true; + + if (!(obj instanceof RouteInfo)) return false; + + RouteInfo target = (RouteInfo) obj; + + if (Objects.equals(mDestination, target.getDestination())) { + return true; + } + return false; + } + /** * Returns a hashcode for this RouteInfo object. */ diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index deae459e39..ecf0309e4c 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -110,6 +110,7 @@ import android.net.NetworkWatchlistManager; import android.net.PrivateDnsConfigParcel; import android.net.ProxyInfo; import android.net.RouteInfo; +import android.net.RouteInfoParcel; import android.net.SocketKeepalive; import android.net.TetheringManager; import android.net.UidRange; @@ -120,6 +121,7 @@ import android.net.metrics.IpConnectivityLog; import android.net.metrics.NetworkEvent; import android.net.netlink.InetDiagMessage; import android.net.shared.PrivateDnsConfig; +import android.net.util.LinkPropertiesUtils.CompareOrUpdateResult; import android.net.util.LinkPropertiesUtils.CompareResult; import android.net.util.MultinetworkPolicyTracker; import android.net.util.NetdService; @@ -232,6 +234,7 @@ import java.util.SortedSet; import java.util.StringJoiner; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; /** * @hide @@ -5951,15 +5954,49 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + // TODO: move to frameworks/libs/net. + private RouteInfoParcel convertRouteInfo(RouteInfo route) { + final String nextHop; + + switch (route.getType()) { + case RouteInfo.RTN_UNICAST: + if (route.hasGateway()) { + nextHop = route.getGateway().getHostAddress(); + } else { + nextHop = INetd.NEXTHOP_NONE; + } + break; + case RouteInfo.RTN_UNREACHABLE: + nextHop = INetd.NEXTHOP_UNREACHABLE; + break; + case RouteInfo.RTN_THROW: + nextHop = INetd.NEXTHOP_THROW; + break; + default: + nextHop = INetd.NEXTHOP_NONE; + break; + } + + final RouteInfoParcel rip = new RouteInfoParcel(); + rip.ifName = route.getInterface(); + rip.destination = route.getDestination().toString(); + rip.nextHop = nextHop; + rip.mtu = route.getMtu(); + + return rip; + } + /** * Have netd update routes from oldLp to newLp. * @return true if routes changed between oldLp and newLp */ private boolean updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId) { - // Compare the route diff to determine which routes should be added and removed. - CompareResult routeDiff = new CompareResult<>( + Function getDestination = (r) -> r.getDestination(); + // compare the route diff to determine which routes have been updated + CompareOrUpdateResult routeDiff = new CompareOrUpdateResult<>( oldLp != null ? oldLp.getAllRoutes() : null, - newLp != null ? newLp.getAllRoutes() : null); + newLp != null ? newLp.getAllRoutes() : null, + getDestination); // add routes before removing old in case it helps with continuous connectivity @@ -5968,10 +6005,10 @@ public class ConnectivityService extends IConnectivityManager.Stub if (route.hasGateway()) continue; if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId); try { - mNMS.addRoute(netId, route); + mNetd.networkAddRouteParcel(netId, convertRouteInfo(route)); } catch (Exception e) { if ((route.getDestination().getAddress() instanceof Inet4Address) || VDBG) { - loge("Exception in addRoute for non-gateway: " + e); + loge("Exception in networkAddRouteParcel for non-gateway: " + e); } } } @@ -5979,10 +6016,10 @@ public class ConnectivityService extends IConnectivityManager.Stub if (!route.hasGateway()) continue; if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId); try { - mNMS.addRoute(netId, route); + mNetd.networkAddRouteParcel(netId, convertRouteInfo(route)); } catch (Exception e) { if ((route.getGateway() instanceof Inet4Address) || VDBG) { - loge("Exception in addRoute for gateway: " + e); + loge("Exception in networkAddRouteParcel for gateway: " + e); } } } @@ -5990,12 +6027,22 @@ public class ConnectivityService extends IConnectivityManager.Stub for (RouteInfo route : routeDiff.removed) { if (VDBG || DDBG) log("Removing Route [" + route + "] from network " + netId); try { - mNMS.removeRoute(netId, route); + mNetd.networkRemoveRouteParcel(netId, convertRouteInfo(route)); } catch (Exception e) { - loge("Exception in removeRoute: " + e); + loge("Exception in networkRemoveRouteParcel: " + e); } } - return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty(); + + for (RouteInfo route : routeDiff.updated) { + if (VDBG || DDBG) log("Updating Route [" + route + "] from network " + netId); + try { + mNetd.networkUpdateRouteParcel(netId, convertRouteInfo(route)); + } catch (Exception e) { + loge("Exception in networkUpdateRouteParcel: " + e); + } + } + return !routeDiff.added.isEmpty() || !routeDiff.removed.isEmpty() + || !routeDiff.updated.isEmpty(); } private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index c21772a5d1..8440259cbf 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -175,6 +175,7 @@ import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.ResolverParamsParcel; import android.net.RouteInfo; +import android.net.RouteInfoParcel; import android.net.SocketKeepalive; import android.net.UidRange; import android.net.Uri; @@ -6064,6 +6065,7 @@ public class ConnectivityServiceTest { verify(mBatteryStatsService).noteNetworkInterfaceType(stackedLp.getInterfaceName(), TYPE_MOBILE); } + reset(mMockNetd); // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked // linkproperties are cleaned up. @@ -6115,7 +6117,6 @@ public class ConnectivityServiceTest { networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kNat64Prefix.toString()); - // Clat iface comes up. Expect stacked link to be added. clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true); networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, @@ -6701,17 +6702,45 @@ public class ConnectivityServiceTest { } } + private void assertRouteInfoParcelMatches(RouteInfo route, RouteInfoParcel parcel) { + assertEquals(route.getDestination().toString(), parcel.destination); + assertEquals(route.getInterface(), parcel.ifName); + assertEquals(route.getMtu(), parcel.mtu); + + switch (route.getType()) { + case RouteInfo.RTN_UNICAST: + if (route.hasGateway()) { + assertEquals(route.getGateway().getHostAddress(), parcel.nextHop); + } else { + assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop); + } + break; + case RouteInfo.RTN_UNREACHABLE: + assertEquals(INetd.NEXTHOP_UNREACHABLE, parcel.nextHop); + break; + case RouteInfo.RTN_THROW: + assertEquals(INetd.NEXTHOP_THROW, parcel.nextHop); + break; + default: + assertEquals(INetd.NEXTHOP_NONE, parcel.nextHop); + break; + } + } + private void assertRoutesAdded(int netId, RouteInfo... routes) throws Exception { - InOrder inOrder = inOrder(mNetworkManagementService); + ArgumentCaptor captor = ArgumentCaptor.forClass(RouteInfoParcel.class); + verify(mMockNetd, times(routes.length)).networkAddRouteParcel(eq(netId), captor.capture()); for (int i = 0; i < routes.length; i++) { - inOrder.verify(mNetworkManagementService).addRoute(eq(netId), eq(routes[i])); + assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i)); } } private void assertRoutesRemoved(int netId, RouteInfo... routes) throws Exception { - InOrder inOrder = inOrder(mNetworkManagementService); + ArgumentCaptor captor = ArgumentCaptor.forClass(RouteInfoParcel.class); + verify(mMockNetd, times(routes.length)).networkRemoveRouteParcel(eq(netId), + captor.capture()); for (int i = 0; i < routes.length; i++) { - inOrder.verify(mNetworkManagementService).removeRoute(eq(netId), eq(routes[i])); + assertRouteInfoParcelMatches(routes[i], captor.getAllValues().get(i)); } } @@ -6977,4 +7006,60 @@ public class ConnectivityServiceTest { verify(mConnectivityDiagnosticsCallback) .onNetworkConnectivityReported(eq(n), eq(noConnectivity)); } + + @Test + public void testRouteAddDeleteUpdate() throws Exception { + final NetworkRequest request = new NetworkRequest.Builder().build(); + final TestNetworkCallback networkCallback = new TestNetworkCallback(); + mCm.registerNetworkCallback(request, networkCallback); + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + reset(mMockNetd); + mCellNetworkAgent.connect(false); + networkCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); + final int netId = mCellNetworkAgent.getNetwork().netId; + + final String iface = "rmnet_data0"; + final InetAddress gateway = InetAddress.getByName("fe80::5678"); + RouteInfo direct = RouteInfo.makeHostRoute(gateway, iface); + RouteInfo rio1 = new RouteInfo(new IpPrefix("2001:db8:1::/48"), gateway, iface); + RouteInfo rio2 = new RouteInfo(new IpPrefix("2001:db8:2::/48"), gateway, iface); + RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, gateway, iface); + RouteInfo defaultWithMtu = new RouteInfo(null, gateway, iface, RouteInfo.RTN_UNICAST, + 1280 /* mtu */); + + // Send LinkProperties and check that we ask netd to add routes. + LinkProperties lp = new LinkProperties(); + lp.setInterfaceName(iface); + lp.addRoute(direct); + lp.addRoute(rio1); + lp.addRoute(defaultRoute); + mCellNetworkAgent.sendLinkProperties(lp); + networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, x -> x.getRoutes().size() == 3); + + assertRoutesAdded(netId, direct, rio1, defaultRoute); + reset(mMockNetd); + + // Send updated LinkProperties and check that we ask netd to add, remove, update routes. + assertTrue(lp.getRoutes().contains(defaultRoute)); + lp.removeRoute(rio1); + lp.addRoute(rio2); + lp.addRoute(defaultWithMtu); + // Ensure adding the same route with a different MTU replaces the previous route. + assertFalse(lp.getRoutes().contains(defaultRoute)); + assertTrue(lp.getRoutes().contains(defaultWithMtu)); + + mCellNetworkAgent.sendLinkProperties(lp); + networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, + x -> x.getRoutes().contains(rio2)); + + assertRoutesRemoved(netId, rio1); + assertRoutesAdded(netId, rio2); + + ArgumentCaptor captor = ArgumentCaptor.forClass(RouteInfoParcel.class); + verify(mMockNetd).networkUpdateRouteParcel(eq(netId), captor.capture()); + assertRouteInfoParcelMatches(defaultWithMtu, captor.getValue()); + + + mCm.unregisterNetworkCallback(networkCallback); + } } From 46a0db809f3873b7f9098d8cfb5dfa1ca9dbb315 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Mon, 16 Mar 2020 18:15:28 -0700 Subject: [PATCH 110/229] Change NetworkCapabilities administrator UIDs to be stored as int[]. NetworkCapabilities#mAdministratorUids is used to track the UIDs that are administrators of the given Network. This value was previously stored as List. However, general Android API Council guidelines recommend using Arrays for primitive values. In order to be consistent with the guidelines, updating the field to use an Array. Bug: 147903575 Test: atest FrameworksNetTests Change-Id: I2652a5b0f276b8944454af5cb4b1383a3e054cfa --- .../java/android/net/NetworkCapabilities.java | 32 ++++++++----------- .../android/server/ConnectivityService.java | 11 ++++--- .../android/server/TestNetworkService.java | 11 +------ .../server/ConnectivityServiceTest.java | 8 ++--- 4 files changed, 25 insertions(+), 37 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 116e343ff2..7d8df6a8ff 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -37,9 +37,7 @@ import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.Arrays; import java.util.Objects; import java.util.Set; import java.util.StringJoiner; @@ -96,7 +94,7 @@ public final class NetworkCapabilities implements Parcelable { mTransportInfo = null; mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED; mUids = null; - mAdministratorUids.clear(); + mAdministratorUids = new int[0]; mOwnerUid = Process.INVALID_UID; mSSID = null; mPrivateDnsBroken = false; @@ -884,10 +882,10 @@ public final class NetworkCapabilities implements Parcelable { * empty unless the destination is 1) the System Server, or 2) Telephony. In either case, the * receiving entity must have the ACCESS_FINE_LOCATION permission and target R+. */ - private final List mAdministratorUids = new ArrayList<>(); + private int[] mAdministratorUids = new int[0]; /** - * Sets the list of UIDs that are administrators of this network. + * Sets the int[] of UIDs that are administrators of this network. * *

UIDs included in administratorUids gain administrator privileges over this Network. * Examples of UIDs that should be included in administratorUids are: @@ -907,23 +905,21 @@ public final class NetworkCapabilities implements Parcelable { */ @NonNull @SystemApi - public NetworkCapabilities setAdministratorUids( - @NonNull final List administratorUids) { - mAdministratorUids.clear(); - mAdministratorUids.addAll(administratorUids); + public NetworkCapabilities setAdministratorUids(@NonNull final int[] administratorUids) { + mAdministratorUids = Arrays.copyOf(administratorUids, administratorUids.length); return this; } /** - * Retrieves the list of UIDs that are administrators of this Network. + * Retrieves the UIDs that are administrators of this Network. * - * @return the List of UIDs that are administrators of this Network + * @return the int[] of UIDs that are administrators of this Network * @hide */ @NonNull @SystemApi - public List getAdministratorUids() { - return Collections.unmodifiableList(mAdministratorUids); + public int[] getAdministratorUids() { + return Arrays.copyOf(mAdministratorUids, mAdministratorUids.length); } /** @@ -1584,7 +1580,7 @@ public final class NetworkCapabilities implements Parcelable { dest.writeArraySet(mUids); dest.writeString(mSSID); dest.writeBoolean(mPrivateDnsBroken); - dest.writeList(mAdministratorUids); + dest.writeIntArray(mAdministratorUids); dest.writeInt(mOwnerUid); dest.writeInt(mRequestorUid); dest.writeString(mRequestorPackageName); @@ -1608,7 +1604,7 @@ public final class NetworkCapabilities implements Parcelable { null /* ClassLoader, null for default */); netCap.mSSID = in.readString(); netCap.mPrivateDnsBroken = in.readBoolean(); - netCap.setAdministratorUids(in.readArrayList(null)); + netCap.setAdministratorUids(in.createIntArray()); netCap.mOwnerUid = in.readInt(); netCap.mRequestorUid = in.readInt(); netCap.mRequestorPackageName = in.readString(); @@ -1665,8 +1661,8 @@ public final class NetworkCapabilities implements Parcelable { sb.append(" OwnerUid: ").append(mOwnerUid); } - if (!mAdministratorUids.isEmpty()) { - sb.append(" AdministratorUids: ").append(mAdministratorUids); + if (mAdministratorUids.length == 0) { + sb.append(" AdministratorUids: ").append(Arrays.toString(mAdministratorUids)); } if (null != mSSID) { diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index deae459e39..b89b1eb9c8 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1666,7 +1666,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (newNc.getNetworkSpecifier() != null) { newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact()); } - newNc.setAdministratorUids(Collections.EMPTY_LIST); + newNc.setAdministratorUids(new int[0]); return newNc; } @@ -1727,7 +1727,7 @@ public class ConnectivityService extends IConnectivityManager.Stub nc.setSingleUid(callerUid); } nc.setRequestorUidAndPackageName(callerUid, callerPackageName); - nc.setAdministratorUids(Collections.EMPTY_LIST); + nc.setAdministratorUids(new int[0]); // Clear owner UID; this can never come from an app. nc.setOwnerUid(INVALID_UID); @@ -7864,7 +7864,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private void clearNetworkCapabilitiesUids(@NonNull NetworkCapabilities nc) { nc.setUids(null); - nc.setAdministratorUids(Collections.EMPTY_LIST); + nc.setAdministratorUids(new int[0]); nc.setOwnerUid(Process.INVALID_UID); } @@ -7911,8 +7911,9 @@ public class ConnectivityService extends IConnectivityManager.Stub } // Administrator UIDs also contains the Owner UID - if (nai.networkCapabilities.getAdministratorUids().contains(callbackUid)) { - return true; + final int[] administratorUids = nai.networkCapabilities.getAdministratorUids(); + for (final int uid : administratorUids) { + if (uid == callbackUid) return true; } return false; diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index f772a4a5a3..81a1372eb1 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -53,7 +53,6 @@ import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.ArrayList; -import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; @@ -250,7 +249,7 @@ class TestNetworkService extends ITestNetworkManager.Stub { nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); nc.setNetworkSpecifier(new StringNetworkSpecifier(iface)); - nc.setAdministratorUids(intArrayToList(administratorUids)); + nc.setAdministratorUids(administratorUids); if (!isMetered) { nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); } @@ -293,14 +292,6 @@ class TestNetworkService extends ITestNetworkManager.Stub { return new TestNetworkAgent(looper, context, ni, nc, lp, callingUid, binder); } - private List intArrayToList(@NonNull int[] array) { - final List list = new ArrayList<>(array.length); - for (final int i : array) { - list.add(i); - } - return list; - } - /** * Sets up a Network with extremely limited privileges, guarded by the MANAGE_TEST_NETWORKS * permission. diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index c21772a5d1..a5a4fa56ad 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6851,7 +6851,7 @@ public class ConnectivityServiceTest { @Test public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception { final NetworkCapabilities nc = new NetworkCapabilities(); - nc.setAdministratorUids(Arrays.asList(Process.myUid())); + nc.setAdministratorUids(new int[] {Process.myUid()}); final NetworkAgentInfo naiWithUid = new NetworkAgentInfo( null, null, null, null, null, nc, 0, mServiceContext, null, null, @@ -6873,7 +6873,7 @@ public class ConnectivityServiceTest { public void testCheckConnectivityDiagnosticsPermissionsFails() throws Exception { final NetworkCapabilities nc = new NetworkCapabilities(); nc.setOwnerUid(Process.myUid()); - nc.setAdministratorUids(Arrays.asList(Process.myUid())); + nc.setAdministratorUids(new int[] {Process.myUid()}); final NetworkAgentInfo naiWithUid = new NetworkAgentInfo( null, null, null, null, null, nc, 0, mServiceContext, null, null, @@ -6926,7 +6926,7 @@ public class ConnectivityServiceTest { argThat(report -> { final NetworkCapabilities nc = report.getNetworkCapabilities(); return nc.getUids() == null - && nc.getAdministratorUids().isEmpty() + && nc.getAdministratorUids().length == 0 && nc.getOwnerUid() == Process.INVALID_UID; })); } @@ -6947,7 +6947,7 @@ public class ConnectivityServiceTest { argThat(report -> { final NetworkCapabilities nc = report.getNetworkCapabilities(); return nc.getUids() == null - && nc.getAdministratorUids().isEmpty() + && nc.getAdministratorUids().length == 0 && nc.getOwnerUid() == Process.INVALID_UID; })); } From 7e6e807bec67ddead3c484c3f4d1d94fd8346da9 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 2 Jan 2020 19:35:59 +0800 Subject: [PATCH 111/229] [SM07] Make combine subtype configurable from Settings Note that enabling/disabling would not take effect until device reboot. This will be addressed in follow-up patch. Test: 1. atest NetworkStatsServieTest SettingsBackupTest 2. adb shell settings put global netstats_combine_subtype_enabled 1|0 Bug: 146415925 Change-Id: Ic94da540afa479ed18f1b6fbda4ae3216c37476b Merged-In: Ic94da540afa479ed18f1b6fbda4ae3216c37476b (cherry picked from commit c4f77ac90bf2e48a655ad19b162fe74a23bf3fb0) --- .../net/java/com/android/server/net/NetworkStatsServiceTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index 64c0221c58..6e6331312e 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -1294,6 +1294,7 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { when(mSettings.getPollInterval()).thenReturn(HOUR_IN_MILLIS); when(mSettings.getPollDelay()).thenReturn(0L); when(mSettings.getSampleEnabled()).thenReturn(true); + when(mSettings.getCombineSubtypeEnabled()).thenReturn(false); final Config config = new Config(bucketDuration, deleteAge, deleteAge); when(mSettings.getDevConfig()).thenReturn(config); From 92e995d9cdbb64adadd0fa7abc736804970e8f58 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 25 Feb 2020 21:36:33 +0800 Subject: [PATCH 112/229] [SM08] Add NetworkTemplate unit test for fetching mobile data usage Test: atest NetworkTemplateTest Bug: 129082217 Change-Id: I7eaca623adf93f9b8d53c2e5857ecae90ea572ab Merged-In: I7eaca623adf93f9b8d53c2e5857ecae90ea572ab (cherry picked from commit 4670baace6c8dafe3a30330596c333d6b2389e4d) --- .../java/android/net/NetworkTemplateTest.kt | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 tests/net/java/android/net/NetworkTemplateTest.kt diff --git a/tests/net/java/android/net/NetworkTemplateTest.kt b/tests/net/java/android/net/NetworkTemplateTest.kt new file mode 100644 index 0000000000..5dd0fda4da --- /dev/null +++ b/tests/net/java/android/net/NetworkTemplateTest.kt @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2020 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.content.Context +import android.net.ConnectivityManager.TYPE_MOBILE +import android.net.ConnectivityManager.TYPE_WIFI +import android.net.NetworkIdentity.SUBTYPE_COMBINED +import android.net.NetworkIdentity.buildNetworkIdentity +import android.net.NetworkStats.DEFAULT_NETWORK_ALL +import android.net.NetworkStats.METERED_ALL +import android.net.NetworkStats.ROAMING_ALL +import android.net.NetworkTemplate.MATCH_MOBILE +import android.net.NetworkTemplate.MATCH_WIFI +import android.net.NetworkTemplate.NETWORK_TYPE_ALL +import android.net.NetworkTemplate.buildTemplateMobileWithRatType +import android.telephony.TelephonyManager +import com.android.testutils.assertParcelSane +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.Mockito.doReturn +import org.mockito.Mockito.mock +import org.mockito.MockitoAnnotations +import kotlin.test.assertFalse +import kotlin.test.assertNotEquals +import kotlin.test.assertTrue + +private const val TEST_IMSI1 = "imsi1" +private const val TEST_IMSI2 = "imsi2" +private const val TEST_SSID1 = "ssid1" + +@RunWith(JUnit4::class) +class NetworkTemplateTest { + private val mockContext = mock(Context::class.java) + + private fun buildMobileNetworkState(subscriberId: String): NetworkState = + buildNetworkState(TYPE_MOBILE, subscriberId = subscriberId) + private fun buildWifiNetworkState(ssid: String): NetworkState = + buildNetworkState(TYPE_WIFI, ssid = ssid) + + private fun buildNetworkState( + type: Int, + subscriberId: String? = null, + ssid: String? = null + ): NetworkState { + val info = mock(NetworkInfo::class.java) + doReturn(type).`when`(info).type + doReturn(NetworkInfo.State.CONNECTED).`when`(info).state + val lp = LinkProperties() + val caps = NetworkCapabilities().apply { + setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false) + setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true) + } + return NetworkState(info, lp, caps, mock(Network::class.java), subscriberId, ssid) + } + + private fun NetworkTemplate.assertMatches(ident: NetworkIdentity) = + assertTrue(matches(ident), "$this does not match $ident") + + private fun NetworkTemplate.assertDoesNotMatch(ident: NetworkIdentity) = + assertFalse(matches(ident), "$this should match $ident") + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + } + + @Test + fun testRatTypeGroupMatches() { + val stateMobile = buildMobileNetworkState(TEST_IMSI1) + // Build UMTS template that matches mobile identities with RAT in the same + // group with any IMSI. See {@link NetworkTemplate#getCollapsedRatType}. + val templateUmts = buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UMTS) + // Build normal template that matches mobile identities with any RAT and IMSI. + val templateAll = buildTemplateMobileWithRatType(null, NETWORK_TYPE_ALL) + // Build template with UNKNOWN RAT that matches mobile identities with RAT that + // cannot be determined. + val templateUnknown = + buildTemplateMobileWithRatType(null, TelephonyManager.NETWORK_TYPE_UNKNOWN) + + val identUmts = buildNetworkIdentity( + mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_UMTS) + val identHsdpa = buildNetworkIdentity( + mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_HSDPA) + val identLte = buildNetworkIdentity( + mockContext, stateMobile, false, TelephonyManager.NETWORK_TYPE_LTE) + val identCombined = buildNetworkIdentity( + mockContext, stateMobile, false, SUBTYPE_COMBINED) + val identImsi2 = buildNetworkIdentity(mockContext, buildMobileNetworkState(TEST_IMSI2), + false, TelephonyManager.NETWORK_TYPE_UMTS) + val identWifi = buildNetworkIdentity( + mockContext, buildWifiNetworkState(TEST_SSID1), true, 0) + + // Assert that identity with the same RAT matches. + templateUmts.assertMatches(identUmts) + templateAll.assertMatches(identUmts) + templateUnknown.assertDoesNotMatch(identUmts) + // Assert that identity with the RAT within the same group matches. + templateUmts.assertMatches(identHsdpa) + templateAll.assertMatches(identHsdpa) + templateUnknown.assertDoesNotMatch(identHsdpa) + // Assert that identity with the RAT out of the same group only matches template with + // NETWORK_TYPE_ALL. + templateUmts.assertDoesNotMatch(identLte) + templateAll.assertMatches(identLte) + templateUnknown.assertDoesNotMatch(identLte) + // Assert that identity with combined RAT only matches with template with NETWORK_TYPE_ALL + // and NETWORK_TYPE_UNKNOWN. + templateUmts.assertDoesNotMatch(identCombined) + templateAll.assertMatches(identCombined) + templateUnknown.assertMatches(identCombined) + // Assert that identity with different IMSI matches. + templateUmts.assertMatches(identImsi2) + templateAll.assertMatches(identImsi2) + templateUnknown.assertDoesNotMatch(identImsi2) + // Assert that wifi identity does not match. + templateUmts.assertDoesNotMatch(identWifi) + templateAll.assertDoesNotMatch(identWifi) + templateUnknown.assertDoesNotMatch(identWifi) + } + + @Test + fun testParcelUnparcel() { + val templateMobile = NetworkTemplate(MATCH_MOBILE, TEST_IMSI1, null, null, METERED_ALL, + ROAMING_ALL, DEFAULT_NETWORK_ALL, TelephonyManager.NETWORK_TYPE_LTE) + val templateWifi = NetworkTemplate(MATCH_WIFI, null, null, TEST_SSID1, METERED_ALL, + ROAMING_ALL, DEFAULT_NETWORK_ALL, 0) + assertParcelSane(templateMobile, 8) + assertParcelSane(templateWifi, 8) + } + + // Verify NETWORK_TYPE_ALL does not conflict with TelephonyManager#NETWORK_TYPE_* constants. + @Test + fun testNetworkTypeAll() { + for (ratType in TelephonyManager.getAllNetworkTypes()) { + assertNotEquals(NETWORK_TYPE_ALL, ratType) + } + } +} From 410236b92e009c8b17a02daaef11adee6eee9dec Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 18 Mar 2020 19:24:31 +0800 Subject: [PATCH 113/229] API review: access field by method - InvalidPacketException, public field should be a method so add getter to get error code. - KeepalivePacketData, public fields should be methods so add getter for fields. Bug: 151322799 Test: atest FrameworksNetTests atest FrameworksWifiTests atest FrameworksTelephonyTests: some failure in CarrierAppUtilsTest Change-Id: Id01e6135193716cc21bba11da529bf1507a954f7 --- .../android/net/InvalidPacketException.java | 9 +++- .../java/android/net/KeepalivePacketData.java | 49 ++++++++++++++----- .../android/net/NattKeepalivePacketData.java | 22 +++++---- .../server/connectivity/KeepaliveTracker.java | 10 ++-- .../net/TcpKeepalivePacketDataTest.java | 8 +-- 5 files changed, 66 insertions(+), 32 deletions(-) diff --git a/core/java/android/net/InvalidPacketException.java b/core/java/android/net/InvalidPacketException.java index 909998d456..b3b0f11a77 100644 --- a/core/java/android/net/InvalidPacketException.java +++ b/core/java/android/net/InvalidPacketException.java @@ -28,7 +28,7 @@ import java.lang.annotation.RetentionPolicy; */ @SystemApi public class InvalidPacketException extends Exception { - public final int error; + private final int mError; // Must match SocketKeepalive#ERROR_INVALID_IP_ADDRESS. /** Invalid IP address. */ @@ -56,6 +56,11 @@ public class InvalidPacketException extends Exception { * See the error code for details. */ public InvalidPacketException(@ErrorCode final int error) { - this.error = error; + this.mError = error; + } + + /** Get error code. */ + public int getError() { + return mError; } } diff --git a/core/java/android/net/KeepalivePacketData.java b/core/java/android/net/KeepalivePacketData.java index 6c0ba2f63a..e21cb44f72 100644 --- a/core/java/android/net/KeepalivePacketData.java +++ b/core/java/android/net/KeepalivePacketData.java @@ -19,6 +19,7 @@ package android.net; import static android.net.InvalidPacketException.ERROR_INVALID_IP_ADDRESS; import static android.net.InvalidPacketException.ERROR_INVALID_PORT; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.SystemApi; import android.net.util.IpUtils; @@ -37,17 +38,17 @@ public class KeepalivePacketData { /** Source IP address */ @NonNull - public final InetAddress srcAddress; + private final InetAddress mSrcAddress; /** Destination IP address */ @NonNull - public final InetAddress dstAddress; + private final InetAddress mDstAddress; /** Source port */ - public final int srcPort; + private final int mSrcPort; /** Destination port */ - public final int dstPort; + private final int mDstPort; /** Packet data. A raw byte string of packet data, not including the link-layer header. */ private final byte[] mPacket; @@ -60,13 +61,14 @@ public class KeepalivePacketData { /** * A holding class for data necessary to build a keepalive packet. */ - protected KeepalivePacketData(@NonNull InetAddress srcAddress, int srcPort, - @NonNull InetAddress dstAddress, int dstPort, - @NonNull byte[] data) throws InvalidPacketException { - this.srcAddress = srcAddress; - this.dstAddress = dstAddress; - this.srcPort = srcPort; - this.dstPort = dstPort; + protected KeepalivePacketData(@NonNull InetAddress srcAddress, + @IntRange(from = 0, to = 65535) int srcPort, @NonNull InetAddress dstAddress, + @IntRange(from = 0, to = 65535) int dstPort, + @NonNull byte[] data) throws InvalidPacketException { + this.mSrcAddress = srcAddress; + this.mDstAddress = dstAddress; + this.mSrcPort = srcPort; + this.mDstPort = dstPort; this.mPacket = data; // Check we have two IP addresses of the same family. @@ -83,6 +85,31 @@ public class KeepalivePacketData { } } + /** Get source IP address. */ + @NonNull + public InetAddress getSrcAddress() { + return mSrcAddress; + } + + /** Get destination IP address. */ + @NonNull + public InetAddress getDstAddress() { + return mDstAddress; + } + + /** Get source port number. */ + public int getSrcPort() { + return mSrcPort; + } + + /** Get destination port number. */ + public int getDstPort() { + return mDstPort; + } + + /** + * Returns a byte array of the given packet data. + */ @NonNull public byte[] getPacket() { return mPacket.clone(); diff --git a/core/java/android/net/NattKeepalivePacketData.java b/core/java/android/net/NattKeepalivePacketData.java index 29da4952da..22288b6205 100644 --- a/core/java/android/net/NattKeepalivePacketData.java +++ b/core/java/android/net/NattKeepalivePacketData.java @@ -94,10 +94,10 @@ public final class NattKeepalivePacketData extends KeepalivePacketData implement /** Write to parcel */ public void writeToParcel(@NonNull Parcel out, int flags) { - out.writeString(srcAddress.getHostAddress()); - out.writeString(dstAddress.getHostAddress()); - out.writeInt(srcPort); - out.writeInt(dstPort); + out.writeString(getSrcAddress().getHostAddress()); + out.writeString(getDstAddress().getHostAddress()); + out.writeInt(getSrcPort()); + out.writeInt(getDstPort()); } /** Parcelable Creator */ @@ -115,7 +115,7 @@ public final class NattKeepalivePacketData extends KeepalivePacketData implement dstAddress, dstPort); } catch (InvalidPacketException e) { throw new IllegalArgumentException( - "Invalid NAT-T keepalive data: " + e.error); + "Invalid NAT-T keepalive data: " + e.getError()); } } @@ -128,14 +128,16 @@ public final class NattKeepalivePacketData extends KeepalivePacketData implement public boolean equals(@Nullable final Object o) { if (!(o instanceof NattKeepalivePacketData)) return false; final NattKeepalivePacketData other = (NattKeepalivePacketData) o; - return this.srcAddress.equals(other.srcAddress) - && this.dstAddress.equals(other.dstAddress) - && this.srcPort == other.srcPort - && this.dstPort == other.dstPort; + final InetAddress srcAddress = getSrcAddress(); + final InetAddress dstAddress = getDstAddress(); + return srcAddress.equals(other.getSrcAddress()) + && dstAddress.equals(other.getDstAddress()) + && getSrcPort() == other.getSrcPort() + && getDstPort() == other.getDstPort(); } @Override public int hashCode() { - return Objects.hash(srcAddress, dstAddress, srcPort, dstPort); + return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort()); } } diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 5059a4861a..7c8fb5aefd 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -220,9 +220,9 @@ public class KeepaliveTracker { + " network=" + mNai.network + " startedState=" + startedStateString(mStartedState) + " " - + IpUtils.addressAndPortToString(mPacket.srcAddress, mPacket.srcPort) + + IpUtils.addressAndPortToString(mPacket.getSrcAddress(), mPacket.getSrcPort()) + "->" - + IpUtils.addressAndPortToString(mPacket.dstAddress, mPacket.dstPort) + + IpUtils.addressAndPortToString(mPacket.getDstAddress(), mPacket.getDstPort()) + " interval=" + mInterval + " uid=" + mUid + " pid=" + mPid + " privileged=" + mPrivileged + " packetData=" + HexDump.toHexString(mPacket.getPacket()) @@ -250,7 +250,7 @@ public class KeepaliveTracker { private int checkSourceAddress() { // Check that we have the source address. for (InetAddress address : mNai.linkProperties.getAddresses()) { - if (address.equals(mPacket.srcAddress)) { + if (address.equals(mPacket.getSrcAddress())) { return SUCCESS; } } @@ -619,7 +619,7 @@ public class KeepaliveTracker { packet = NattKeepalivePacketData.nattKeepalivePacket( srcAddress, srcPort, dstAddress, NATT_PORT); } catch (InvalidPacketException e) { - notifyErrorCallback(cb, e.error); + notifyErrorCallback(cb, e.getError()); return; } KeepaliveInfo ki = null; @@ -662,7 +662,7 @@ public class KeepaliveTracker { notifyErrorCallback(cb, e.error); return; } catch (InvalidPacketException e) { - notifyErrorCallback(cb, e.error); + notifyErrorCallback(cb, e.getError()); return; } KeepaliveInfo ki = null; diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java index e632aafde7..cea8c5713a 100644 --- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java +++ b/tests/net/java/android/net/TcpKeepalivePacketDataTest.java @@ -66,10 +66,10 @@ public final class TcpKeepalivePacketDataTest { fail("InvalidPacketException: " + e); } - assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.srcAddress); - assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.dstAddress); - assertEquals(testInfo.srcPort, resultData.srcPort); - assertEquals(testInfo.dstPort, resultData.dstPort); + assertEquals(InetAddress.getByAddress(testInfo.srcAddress), resultData.getSrcAddress()); + assertEquals(InetAddress.getByAddress(testInfo.dstAddress), resultData.getDstAddress()); + assertEquals(testInfo.srcPort, resultData.getSrcPort()); + assertEquals(testInfo.dstPort, resultData.getDstPort()); assertEquals(testInfo.seq, resultData.tcpSeq); assertEquals(testInfo.ack, resultData.tcpAck); assertEquals(testInfo.rcvWnd, resultData.tcpWnd); From 5637fa73e388fa60bf77aa2d7179edd1f750ec03 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Thu, 19 Mar 2020 02:48:22 +0000 Subject: [PATCH 114/229] Kill ConnectivityManager.CONNECTIVITY_ACTION_SUPL CONNECTIVITY_ACTION_SUPL is marked as a "temporary hack" and has never been public. Remove this intent definition since no one is receiving this intent and should use network callback to know the connection change. Bug: 109636544 Test: atest FrameworksNetTests Change-Id: Ie9e5127742beba04f1c191e894e8a29fe1e704bb Merged-In: Ie9e5127742beba04f1c191e894e8a29fe1e704bb (cherry picked from aosp/1224697) --- .../java/android/net/ConnectivityManager.java | 97 +------------------ .../android/server/ConnectivityService.java | 11 +-- .../server/ConnectivityServiceTest.java | 46 ++------- 3 files changed, 14 insertions(+), 140 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 81735ac8f6..99813c0988 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -144,16 +144,6 @@ public class ConnectivityManager { @Deprecated public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; - /** - * A temporary hack until SUPL system can get off the legacy APIS. - * They do too many network requests and the long list of apps listening - * and waking due to the CONNECTIVITY_ACTION broadcast makes it expensive. - * Use this broadcast intent instead for SUPL requests. - * @hide - */ - public static final String CONNECTIVITY_ACTION_SUPL = - "android.net.conn.CONNECTIVITY_CHANGE_SUPL"; - /** * The device has connected to a network that has presented a captive * portal, which is blocking Internet connectivity. The user was presented @@ -1517,84 +1507,6 @@ public class ConnectivityManager { return null; } - /** - * Guess what the network request was trying to say so that the resulting - * network is accessible via the legacy (deprecated) API such as - * requestRouteToHost. - * - * This means we should try to be fairly precise about transport and - * capability but ignore things such as networkSpecifier. - * If the request has more than one transport or capability it doesn't - * match the old legacy requests (they selected only single transport/capability) - * so this function cannot map the request to a single legacy type and - * the resulting network will not be available to the legacy APIs. - * - * This code is only called from the requestNetwork API (L and above). - * - * Setting a legacy type causes CONNECTIVITY_ACTION broadcasts, which are expensive - * because they wake up lots of apps - see http://b/23350688 . So we currently only - * do this for SUPL requests, which are the only ones that we know need it. If - * omitting these broadcasts causes unacceptable app breakage, then for backwards - * compatibility we can send them: - * - * if (targetSdkVersion < Build.VERSION_CODES.M) && // legacy API unsupported >= M - * targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP)) // requestNetwork not present < L - * - * TODO - This should be removed when the legacy APIs are removed. - */ - private int inferLegacyTypeForNetworkCapabilities(NetworkCapabilities netCap) { - if (netCap == null) { - return TYPE_NONE; - } - - if (!netCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { - return TYPE_NONE; - } - - // Do this only for SUPL, until GnssLocationProvider is fixed. http://b/25876485 . - if (!netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) { - // NOTE: if this causes app breakage, we should not just comment out this early return; - // instead, we should make this early return conditional on the requesting app's target - // SDK version, as described in the comment above. - return TYPE_NONE; - } - - String type = null; - int result = TYPE_NONE; - - if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) { - type = "enableCBS"; - result = TYPE_MOBILE_CBS; - } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) { - type = "enableIMS"; - result = TYPE_MOBILE_IMS; - } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) { - type = "enableFOTA"; - result = TYPE_MOBILE_FOTA; - } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) { - type = "enableDUN"; - result = TYPE_MOBILE_DUN; - } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) { - type = "enableSUPL"; - result = TYPE_MOBILE_SUPL; - // back out this hack for mms as they no longer need this and it's causing - // device slowdowns - b/23350688 (note, supl still needs this) - //} else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) { - // type = "enableMMS"; - // result = TYPE_MOBILE_MMS; - } else if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { - type = "enableHIPRI"; - result = TYPE_MOBILE_HIPRI; - } - if (type != null) { - NetworkCapabilities testCap = networkCapabilitiesForFeature(TYPE_MOBILE, type); - if (testCap.equalsNetCapabilities(netCap) && testCap.equalsTransportTypes(netCap)) { - return result; - } - } - return TYPE_NONE; - } - private int legacyTypeForNetworkCapabilities(NetworkCapabilities netCap) { if (netCap == null) return TYPE_NONE; if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) { @@ -3893,9 +3805,8 @@ public class ConnectivityManager { */ public void requestNetwork(@NonNull NetworkRequest request, @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { - int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities); CallbackHandler cbHandler = new CallbackHandler(handler); - requestNetwork(request, networkCallback, 0, legacyType, cbHandler); + requestNetwork(request, networkCallback, 0, TYPE_NONE, cbHandler); } /** @@ -3928,8 +3839,7 @@ public class ConnectivityManager { public void requestNetwork(@NonNull NetworkRequest request, @NonNull NetworkCallback networkCallback, int timeoutMs) { checkTimeout(timeoutMs); - int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities); - requestNetwork(request, networkCallback, timeoutMs, legacyType, getDefaultHandler()); + requestNetwork(request, networkCallback, timeoutMs, TYPE_NONE, getDefaultHandler()); } /** @@ -3954,9 +3864,8 @@ public class ConnectivityManager { public void requestNetwork(@NonNull NetworkRequest request, @NonNull NetworkCallback networkCallback, @NonNull Handler handler, int timeoutMs) { checkTimeout(timeoutMs); - int legacyType = inferLegacyTypeForNetworkCapabilities(request.networkCapabilities); CallbackHandler cbHandler = new CallbackHandler(handler); - requestNetwork(request, networkCallback, timeoutMs, legacyType, cbHandler); + requestNetwork(request, networkCallback, timeoutMs, TYPE_NONE, cbHandler); } /** diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 4309b849d4..91dd1d59c6 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2240,14 +2240,9 @@ public class ConnectivityService extends IConnectivityManager.Stub if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) { final NetworkInfo ni = intent.getParcelableExtra( ConnectivityManager.EXTRA_NETWORK_INFO); - if (ni.getType() == ConnectivityManager.TYPE_MOBILE_SUPL) { - intent.setAction(ConnectivityManager.CONNECTIVITY_ACTION_SUPL); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - } else { - BroadcastOptions opts = BroadcastOptions.makeBasic(); - opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M); - options = opts.toBundle(); - } + final BroadcastOptions opts = BroadcastOptions.makeBasic(); + opts.setMaxManifestReceiverApiLevel(Build.VERSION_CODES.M); + options = opts.toBundle(); final IBatteryStats bs = mDeps.getBatteryStatsService(); try { bs.noteConnectivityChanged(intent.getIntExtra( diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index f7ad09ca36..4bfb51bca2 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -25,7 +25,6 @@ import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.net.ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; -import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_SUPL; import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO; import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE; import static android.net.ConnectivityManager.NETID_UNSET; @@ -1374,7 +1373,6 @@ public class ConnectivityServiceTest { @NonNull final Predicate filter) { final ConditionVariable cv = new ConditionVariable(); final IntentFilter intentFilter = new IntentFilter(CONNECTIVITY_ACTION); - intentFilter.addAction(CONNECTIVITY_ACTION_SUPL); final BroadcastReceiver receiver = new BroadcastReceiver() { private int remaining = count; public void onReceive(Context context, Intent intent) { @@ -1422,56 +1420,28 @@ public class ConnectivityServiceTest { final NetworkRequest legacyRequest = new NetworkRequest(legacyCaps, TYPE_MOBILE_SUPL, ConnectivityManager.REQUEST_ID_UNSET, NetworkRequest.Type.REQUEST); - // Send request and check that the legacy broadcast for SUPL is sent correctly. + // File request, withdraw it and make sure no broadcast is sent + final ConditionVariable cv2 = registerConnectivityBroadcast(1); final TestNetworkCallback callback = new TestNetworkCallback(); - final ConditionVariable cv2 = registerConnectivityBroadcastThat(1, - intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL); mCm.requestNetwork(legacyRequest, callback); callback.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); - waitFor(cv2); - - // File another request, withdraw it and make sure no broadcast is sent - final ConditionVariable cv3 = registerConnectivityBroadcast(1); - final TestNetworkCallback callback2 = new TestNetworkCallback(); - mCm.requestNetwork(legacyRequest, callback2); - callback2.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); - mCm.unregisterNetworkCallback(callback2); - assertFalse(cv3.block(800)); // 800ms long enough to at least flake if this is sent + mCm.unregisterNetworkCallback(callback); + assertFalse(cv2.block(800)); // 800ms long enough to at least flake if this is sent // As the broadcast did not fire, the receiver was not unregistered. Do this now. mServiceContext.clearRegisteredReceivers(); - // Withdraw the request and check that the broadcast for disconnection is sent. - final ConditionVariable cv4 = registerConnectivityBroadcastThat(1, intent -> - !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected() - && intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL); - mCm.unregisterNetworkCallback(callback); - waitFor(cv4); - - // Re-file the request and expect the connected broadcast again - final ConditionVariable cv5 = registerConnectivityBroadcastThat(1, - intent -> intent.getIntExtra(EXTRA_NETWORK_TYPE, -1) == TYPE_MOBILE_SUPL); - final TestNetworkCallback callback3 = new TestNetworkCallback(); - mCm.requestNetwork(legacyRequest, callback3); - callback3.expectCallback(CallbackEntry.AVAILABLE, mCellNetworkAgent); - waitFor(cv5); - - // Disconnect the network and expect two disconnected broadcasts, one for SUPL and one - // for mobile. Use a small hack to check that both have been sent, but the order is - // not contractual. + // Disconnect the network and expect mobile disconnected broadcast. Use a small hack to + // check that has been sent. final AtomicBoolean vanillaAction = new AtomicBoolean(false); - final AtomicBoolean suplAction = new AtomicBoolean(false); - final ConditionVariable cv6 = registerConnectivityBroadcastThat(2, intent -> { + final ConditionVariable cv3 = registerConnectivityBroadcastThat(1, intent -> { if (intent.getAction().equals(CONNECTIVITY_ACTION)) { vanillaAction.set(true); - } else if (intent.getAction().equals(CONNECTIVITY_ACTION_SUPL)) { - suplAction.set(true); } return !((NetworkInfo) intent.getExtra(EXTRA_NETWORK_INFO, -1)).isConnected(); }); mCellNetworkAgent.disconnect(); - waitFor(cv6); + waitFor(cv3); assertTrue(vanillaAction.get()); - assertTrue(suplAction.get()); } @Test From ed55c7ad03423042bc6243c19e8f0935c8c420f0 Mon Sep 17 00:00:00 2001 From: markchien Date: Wed, 18 Mar 2020 08:43:07 +0800 Subject: [PATCH 115/229] Expose netId by adding getter API Bug: 151156820 Test: m atest TetetheringTests Change-Id: Ieb1483c146aa2f7d8f251157e6e81d71c44ae899 (cherry picked from commit 8831c4b54178753013d568c0b76bbf7487db8122) --- core/java/android/net/Network.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java index 6f5471baa7..f807a4968d 100644 --- a/core/java/android/net/Network.java +++ b/core/java/android/net/Network.java @@ -64,7 +64,7 @@ public class Network implements Parcelable { * The unique id of the network. * @hide */ - @SystemApi + @UnsupportedAppUsage public final int netId; // Objects used to perform per-network operations such as getSocketFactory @@ -169,6 +169,17 @@ public class Network implements Parcelable { return new Network(netId, true); } + /** + * Get the unique id of the network. + * + * @hide + */ + @TestApi + @SystemApi + public int getNetId() { + return netId; + } + /** * Returns a netid marked with the Private DNS bypass flag. * From 4129ed1f13eadd12e0a66d4f31773ac1061add9f Mon Sep 17 00:00:00 2001 From: markchien Date: Thu, 19 Mar 2020 13:37:43 +0800 Subject: [PATCH 116/229] TetheringManager API clean up Per API review: - @IntDef defined on the type integer parameter - have getters on each parameter that is set in the TetheringRequest.Builder - new added API should not be deprecated Below APIs is moved from system-current to module-lib-current that only plafrom code(e.g. ConnectivityManager and Settings) can use them. TetheringRequest. onTetherableInterfaceRegexpsChanged, TetheringInterfaceRegexps: Only platform code can use them because interfaces by regular expressions are a mechanism which is planning to be deprecated. Also rename some constants for easier to understand. Bug: 149858697 Bug: 151243337 Test: m doc-comment-check-docs atest TetheringTests Change-Id: Idd041f0fbeca411ea23e49786a50dd7feb77ef45 --- .../java/android/net/ConnectivityManager.java | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 81735ac8f6..7850d9ed6f 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2575,13 +2575,13 @@ public class ConnectivityManager { } @Override - public void onTetheringFailed(final int resultCode) { + public void onTetheringFailed(final int error) { callback.onTetheringFailed(); } }; final TetheringRequest request = new TetheringRequest.Builder(type) - .setSilentProvisioning(!showProvisioningUi).build(); + .setShouldShowEntitlementUi(showProvisioningUi).build(); mTetheringManager.startTethering(request, executor, tetheringCallback); } @@ -2801,11 +2801,12 @@ public class ConnectivityManager { public static final int TETHER_ERROR_UNAVAIL_IFACE = TetheringManager.TETHER_ERROR_UNAVAIL_IFACE; /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_MASTER_ERROR}. + * @deprecated Use {@link TetheringManager#TETHER_ERROR_INTERNAL_ERROR}. * {@hide} */ @Deprecated - public static final int TETHER_ERROR_MASTER_ERROR = TetheringManager.TETHER_ERROR_MASTER_ERROR; + public static final int TETHER_ERROR_MASTER_ERROR = + TetheringManager.TETHER_ERROR_INTERNAL_ERROR; /** * @deprecated Use {@link TetheringManager#TETHER_ERROR_TETHER_IFACE_ERROR}. * {@hide} @@ -2821,19 +2822,19 @@ public class ConnectivityManager { public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR; /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_ENABLE_NAT_ERROR}. + * @deprecated Use {@link TetheringManager#TETHER_ERROR_ENABLE_FORWARDING_ERROR}. * {@hide} */ @Deprecated public static final int TETHER_ERROR_ENABLE_NAT_ERROR = - TetheringManager.TETHER_ERROR_ENABLE_NAT_ERROR; + TetheringManager.TETHER_ERROR_ENABLE_FORWARDING_ERROR; /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_DISABLE_NAT_ERROR}. + * @deprecated Use {@link TetheringManager#TETHER_ERROR_DISABLE_FORWARDING_ERROR}. * {@hide} */ @Deprecated public static final int TETHER_ERROR_DISABLE_NAT_ERROR = - TetheringManager.TETHER_ERROR_DISABLE_NAT_ERROR; + TetheringManager.TETHER_ERROR_DISABLE_FORWARDING_ERROR; /** * @deprecated Use {@link TetheringManager#TETHER_ERROR_IFACE_CFG_ERROR}. * {@hide} @@ -2842,13 +2843,13 @@ public class ConnectivityManager { public static final int TETHER_ERROR_IFACE_CFG_ERROR = TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR; /** - * @deprecated Use {@link TetheringManager#TETHER_ERROR_PROVISION_FAILED}. + * @deprecated Use {@link TetheringManager#TETHER_ERROR_PROVISIONING_FAILED}. * {@hide} */ @SystemApi @Deprecated public static final int TETHER_ERROR_PROVISION_FAILED = - TetheringManager.TETHER_ERROR_PROVISION_FAILED; + TetheringManager.TETHER_ERROR_PROVISIONING_FAILED; /** * @deprecated Use {@link TetheringManager#TETHER_ERROR_DHCPSERVER_ERROR}. * {@hide} @@ -2880,7 +2881,14 @@ public class ConnectivityManager { @UnsupportedAppUsage @Deprecated public int getLastTetherError(String iface) { - return mTetheringManager.getLastTetherError(iface); + int error = mTetheringManager.getLastTetherError(iface); + if (error == TetheringManager.TETHER_ERROR_UNKNOWN_TYPE) { + // TETHER_ERROR_UNKNOWN_TYPE was introduced with TetheringManager and has never been + // returned by ConnectivityManager. Convert it to the legacy TETHER_ERROR_UNKNOWN_IFACE + // instead. + error = TetheringManager.TETHER_ERROR_UNKNOWN_IFACE; + } + return error; } /** @hide */ From 38ef330e46375578ba7f5d5e1c39c1c76fa2e6d1 Mon Sep 17 00:00:00 2001 From: markchien Date: Wed, 18 Mar 2020 21:16:15 +0800 Subject: [PATCH 117/229] Move NetworkCallback to last parameter for new exposed requestNetwork Bug: 151243698 Test: atest TetheringTests Change-Id: I87ef1d451eefa6998b9793c4eacabae978376d24 --- .../java/android/net/ConnectivityManager.java | 30 +++++++++++-------- .../android/server/ConnectivityService.java | 3 ++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 99813c0988..b8f5890b32 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3685,29 +3685,29 @@ public class ConnectivityManager { /** * Helper function to request a network with a particular legacy type. * - * @deprecated This is temporarily public for tethering to backwards compatibility that uses - * the NetworkRequest API to request networks with legacy type and relies on - * CONNECTIVITY_ACTION broadcasts instead of NetworkCallbacks. New caller should use + * This API is only for use in internal system code that requests networks with legacy type and + * relies on CONNECTIVITY_ACTION broadcasts instead of NetworkCallbacks. New caller should use * {@link #requestNetwork(NetworkRequest, NetworkCallback, Handler)} instead. * - * TODO: update said system code to rely on NetworkCallbacks and make this method private. - * @param request {@link NetworkRequest} describing this request. - * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note - * the callback must not be shared - it uniquely specifies this request. * @param timeoutMs The time in milliseconds to attempt looking for a suitable network * before {@link NetworkCallback#onUnavailable()} is called. The timeout must * be a positive value (i.e. >0). * @param legacyType to specify the network type(#TYPE_*). * @param handler {@link Handler} to specify the thread upon which the callback will be invoked. + * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note + * the callback must not be shared - it uniquely specifies this request. * * @hide */ @SystemApi - @Deprecated + @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void requestNetwork(@NonNull NetworkRequest request, - @NonNull NetworkCallback networkCallback, int timeoutMs, int legacyType, - @NonNull Handler handler) { + int timeoutMs, int legacyType, @NonNull Handler handler, + @NonNull NetworkCallback networkCallback) { + if (legacyType == TYPE_NONE) { + throw new IllegalArgumentException("TYPE_NONE is meaningless legacy type"); + } CallbackHandler cbHandler = new CallbackHandler(handler); NetworkCapabilities nc = request.networkCapabilities; sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, legacyType, cbHandler); @@ -3806,7 +3806,8 @@ public class ConnectivityManager { public void requestNetwork(@NonNull NetworkRequest request, @NonNull NetworkCallback networkCallback, @NonNull Handler handler) { CallbackHandler cbHandler = new CallbackHandler(handler); - requestNetwork(request, networkCallback, 0, TYPE_NONE, cbHandler); + NetworkCapabilities nc = request.networkCapabilities; + sendRequestForNetwork(nc, networkCallback, 0, REQUEST, TYPE_NONE, cbHandler); } /** @@ -3839,7 +3840,9 @@ public class ConnectivityManager { public void requestNetwork(@NonNull NetworkRequest request, @NonNull NetworkCallback networkCallback, int timeoutMs) { checkTimeout(timeoutMs); - requestNetwork(request, networkCallback, timeoutMs, TYPE_NONE, getDefaultHandler()); + NetworkCapabilities nc = request.networkCapabilities; + sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, TYPE_NONE, + getDefaultHandler()); } /** @@ -3865,7 +3868,8 @@ public class ConnectivityManager { @NonNull NetworkCallback networkCallback, @NonNull Handler handler, int timeoutMs) { checkTimeout(timeoutMs); CallbackHandler cbHandler = new CallbackHandler(handler); - requestNetwork(request, networkCallback, timeoutMs, TYPE_NONE, cbHandler); + NetworkCapabilities nc = request.networkCapabilities; + sendRequestForNetwork(nc, networkCallback, timeoutMs, REQUEST, TYPE_NONE, cbHandler); } /** diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 91dd1d59c6..75e073ac36 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5400,6 +5400,9 @@ public class ConnectivityService extends IConnectivityManager.Stub public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, int timeoutMs, IBinder binder, int legacyType, @NonNull String callingPackageName) { + if (legacyType != TYPE_NONE && !checkNetworkStackPermission()) { + throw new SecurityException("Insufficient permissions to specify legacy type"); + } final int callingUid = Binder.getCallingUid(); final NetworkRequest.Type type = (networkCapabilities == null) ? NetworkRequest.Type.TRACK_DEFAULT From 4574935dca1523ca87094055f0a0fe3bb15eae04 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 19 Mar 2020 11:46:55 +0000 Subject: [PATCH 118/229] Make Ethernet interfaces more testable. This CL adds a setIncludeTestInterfaces method to EthernetManager that, when called, causes the Ethernet service to recognize and manage test interfaces created by TestNetworkManager. Bug: 150644681 Test: Tested by EthernetTetheringTest in same topic Change-Id: I86eef7a93267f800dbfc8eafd307effa76a344ca Merged-In: I86eef7a93267f800dbfc8eafd307effa76a344ca (cherry picked from commit 3410fb0aa92bbd4f9d7dc031e89f6f528ff34245) --- core/java/android/net/TestNetworkManager.java | 12 ++++++++++++ .../java/com/android/server/TestNetworkService.java | 5 +++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/TestNetworkManager.java b/core/java/android/net/TestNetworkManager.java index c3284df397..a0a563b370 100644 --- a/core/java/android/net/TestNetworkManager.java +++ b/core/java/android/net/TestNetworkManager.java @@ -30,6 +30,18 @@ import com.android.internal.util.Preconditions; */ @TestApi public class TestNetworkManager { + /** + * Prefix for tun interfaces created by this class. + * @hide + */ + public static final String TEST_TUN_PREFIX = "testtun"; + + /** + * Prefix for tap interfaces created by this class. + * @hide + */ + public static final String TEST_TAP_PREFIX = "testtap"; + @NonNull private static final String TAG = TestNetworkManager.class.getSimpleName(); @NonNull private final ITestNetworkManager mService; diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index 81a1372eb1..0ea73460e1 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -16,6 +16,9 @@ package com.android.server; +import static android.net.TestNetworkManager.TEST_TAP_PREFIX; +import static android.net.TestNetworkManager.TEST_TUN_PREFIX; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -60,8 +63,6 @@ import java.util.concurrent.atomic.AtomicInteger; class TestNetworkService extends ITestNetworkManager.Stub { @NonNull private static final String TAG = TestNetworkService.class.getSimpleName(); @NonNull private static final String TEST_NETWORK_TYPE = "TEST_NETWORK"; - @NonNull private static final String TEST_TUN_PREFIX = "testtun"; - @NonNull private static final String TEST_TAP_PREFIX = "testtap"; @NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger(); @NonNull private final Context mContext; From d7d24015a54c8be7dc65d333a8f0612e0115b6e6 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 18 Mar 2020 15:58:50 +0900 Subject: [PATCH 119/229] Create a builder for NetworkCapabilities. Bug: 151322799 Test: FrameworksWifiTests Change-Id: I06eb97e50d5583579b3c26d1365d2dbaec8bfc99 --- .../java/android/net/NetworkCapabilities.java | 407 ++++++++++++++++-- .../android/server/ConnectivityService.java | 4 +- .../NetworkNotificationManager.java | 12 +- .../android/net/NetworkCapabilitiesTest.java | 6 +- 4 files changed, 377 insertions(+), 52 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 7d8df6a8ff..fcfcebdf08 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -19,6 +19,7 @@ package android.net; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; @@ -32,6 +33,7 @@ import android.util.ArraySet; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.BitUtils; import com.android.internal.util.Preconditions; @@ -86,6 +88,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Completely clears the contents of this object, removing even the capabilities that are set * by default when the object is constructed. + * @hide */ public void clearAll() { mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0; @@ -413,11 +416,12 @@ public final class NetworkCapabilities implements Parcelable { /** * Adds the given capability to this {@code NetworkCapability} instance. - * Multiple capabilities may be applied sequentially. Note that when searching - * for a network to satisfy a request, all capabilities requested must be satisfied. + * Note that when searching for a network to satisfy a request, all capabilities + * requested must be satisfied. * * @param capability the capability to be added. * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide */ public @NonNull NetworkCapabilities addCapability(@NetCapability int capability) { // If the given capability was previously added to the list of unwanted capabilities @@ -432,9 +436,9 @@ public final class NetworkCapabilities implements Parcelable { /** * Adds the given capability to the list of unwanted capabilities of this - * {@code NetworkCapability} instance. Multiple unwanted capabilities may be applied - * sequentially. Note that when searching for a network to satisfy a request, the network - * must not contain any capability from unwanted capability list. + * {@code NetworkCapability} instance. Note that when searching for a network to + * satisfy a request, the network must not contain any capability from unwanted capability + * list. *

* If the capability was previously added to the list of required capabilities (for * example, it was there by default or added using {@link #addCapability(int)} method), then @@ -454,6 +458,7 @@ public final class NetworkCapabilities implements Parcelable { * * @param capability the capability to be removed. * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide */ public @NonNull NetworkCapabilities removeCapability(@NetCapability int capability) { // Note that this method removes capabilities that were added via addCapability(int), @@ -468,7 +473,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Sets (or clears) the given capability on this {@link NetworkCapabilities} * instance. - * + * @hide */ public @NonNull NetworkCapabilities setCapability(@NetCapability int capability, boolean value) { @@ -728,7 +733,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Adds the given transport type to this {@code NetworkCapability} instance. - * Multiple transports may be applied sequentially. Note that when searching + * Multiple transports may be applied. Note that when searching * for a network to satisfy a request, any listed in the request will satisfy the request. * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network @@ -737,6 +742,7 @@ public final class NetworkCapabilities implements Parcelable { * * @param transportType the transport type to be added. * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide */ public @NonNull NetworkCapabilities addTransportType(@Transport int transportType) { checkValidTransportType(transportType); @@ -849,6 +855,7 @@ public final class NetworkCapabilities implements Parcelable { /** * Set the UID of the owner app. + * @hide */ public @NonNull NetworkCapabilities setOwnerUid(final int uid) { mOwnerUid = uid; @@ -866,6 +873,8 @@ public final class NetworkCapabilities implements Parcelable { *

  • The user's location toggle is on * * + * Instances of NetworkCapabilities sent to apps without the appropriate permissions will + * have this field cleared out. */ public int getOwnerUid() { return mOwnerUid; @@ -904,7 +913,6 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @NonNull - @SystemApi public NetworkCapabilities setAdministratorUids(@NonNull final int[] administratorUids) { mAdministratorUids = Arrays.copyOf(administratorUids, administratorUids.length); return this; @@ -918,6 +926,7 @@ public final class NetworkCapabilities implements Parcelable { */ @NonNull @SystemApi + @TestApi public int[] getAdministratorUids() { return Arrays.copyOf(mAdministratorUids, mAdministratorUids.length); } @@ -940,15 +949,10 @@ public final class NetworkCapabilities implements Parcelable { * Sets the upstream bandwidth for this network in Kbps. This always only refers to * the estimated first hop transport bandwidth. *

    - * Note that when used to request a network, this specifies the minimum acceptable. - * When received as the state of an existing network this specifies the typical - * first hop bandwidth expected. This is never measured, but rather is inferred - * from technology type and other link parameters. It could be used to differentiate - * between very slow 1xRTT cellular links and other faster networks or even between - * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between - * fast backhauls and slow backhauls. + * {@see Builder#setLinkUpstreamBandwidthKbps} * * @param upKbps the estimated first hop upstream (device to network) bandwidth. + * @hide */ public @NonNull NetworkCapabilities setLinkUpstreamBandwidthKbps(int upKbps) { mLinkUpBandwidthKbps = upKbps; @@ -969,15 +973,10 @@ public final class NetworkCapabilities implements Parcelable { * Sets the downstream bandwidth for this network in Kbps. This always only refers to * the estimated first hop transport bandwidth. *

    - * Note that when used to request a network, this specifies the minimum acceptable. - * When received as the state of an existing network this specifies the typical - * first hop bandwidth expected. This is never measured, but rather is inferred - * from technology type and other link parameters. It could be used to differentiate - * between very slow 1xRTT cellular links and other faster networks or even between - * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between - * fast backhauls and slow backhauls. + * {@see Builder#setLinkUpstreamBandwidthKbps} * * @param downKbps the estimated first hop downstream (network to device) bandwidth. + * @hide */ public @NonNull NetworkCapabilities setLinkDownstreamBandwidthKbps(int downKbps) { mLinkDownBandwidthKbps = downKbps; @@ -1036,6 +1035,7 @@ public final class NetworkCapabilities implements Parcelable { * @param networkSpecifier A concrete, parcelable framework class that extends * NetworkSpecifier. * @return This NetworkCapabilities instance, to facilitate chaining. + * @hide */ public @NonNull NetworkCapabilities setNetworkSpecifier( @NonNull NetworkSpecifier networkSpecifier) { @@ -1057,7 +1057,6 @@ public final class NetworkCapabilities implements Parcelable { * @return This NetworkCapabilities instance, to facilitate chaining. * @hide */ - @SystemApi public @NonNull NetworkCapabilities setTransportInfo(@NonNull TransportInfo transportInfo) { mTransportInfo = transportInfo; return this; @@ -1067,7 +1066,7 @@ public final class NetworkCapabilities implements Parcelable { * Gets the optional bearer specific network specifier. May be {@code null} if not set. * * @return The optional {@link NetworkSpecifier} specifying the bearer specific network - * specifier or {@code null}. See {@link #setNetworkSpecifier}. + * specifier or {@code null}. */ public @Nullable NetworkSpecifier getNetworkSpecifier() { return mNetworkSpecifier; @@ -1137,6 +1136,7 @@ public final class NetworkCapabilities implements Parcelable { * effect when requesting a callback. * * @param signalStrength the bearer-specific signal strength. + * @hide */ public @NonNull NetworkCapabilities setSignalStrength(int signalStrength) { mSignalStrength = signalStrength; @@ -1363,7 +1363,6 @@ public final class NetworkCapabilities implements Parcelable { * Sets the SSID of this network. * @hide */ - @SystemApi public @NonNull NetworkCapabilities setSSID(@Nullable String ssid) { mSSID = ssid; return this; @@ -1374,7 +1373,8 @@ public final class NetworkCapabilities implements Parcelable { * @hide */ @SystemApi - public @Nullable String getSSID() { + @TestApi + public @Nullable String getSsid() { return mSSID; } @@ -1854,25 +1854,32 @@ public final class NetworkCapabilities implements Parcelable { } /** - * Set the uid of the app making the request. + * Set the UID of the app making the request. * - * Note: This works only for {@link NetworkAgent} instances. Any capabilities passed in - * via the public {@link ConnectivityManager} API's will have this field overwritten. + * For instances of NetworkCapabilities representing a request, sets the + * UID of the app making the request. For a network created by the system, + * sets the UID of the only app whose requests can match this network. + * This can be set to {@link Process#INVALID_UID} if there is no such app, + * or if this instance of NetworkCapabilities is about to be sent to a + * party that should not learn about this. * * @param uid UID of the app. * @hide */ - @SystemApi public @NonNull NetworkCapabilities setRequestorUid(int uid) { mRequestorUid = uid; return this; } /** - * @return the uid of the app making the request. + * Returns the UID of the app making the request. * - * Note: This could return {@link Process#INVALID_UID} if the {@link NetworkRequest} - * object was not obtained from {@link ConnectivityManager}. + * For a NetworkRequest being made by an app, contains the app's UID. For a network + * created by the system, contains the UID of the only app whose requests can match + * this network, or {@link Process#INVALID_UID} if none or if the + * caller does not have permission to learn about this. + * + * @return the uid of the app making the request. * @hide */ public int getRequestorUid() { @@ -1882,23 +1889,29 @@ public final class NetworkCapabilities implements Parcelable { /** * Set the package name of the app making the request. * - * Note: This works only for {@link NetworkAgent} instances. Any capabilities passed in - * via the public {@link ConnectivityManager} API's will have this field overwritten. + * For instances of NetworkCapabilities representing a request, sets the + * package name of the app making the request. For a network created by the system, + * sets the package name of the only app whose requests can match this network. + * This can be set to null if there is no such app, or if this instance of + * NetworkCapabilities is about to be sent to a party that should not learn about this. * * @param packageName package name of the app. * @hide */ - @SystemApi public @NonNull NetworkCapabilities setRequestorPackageName(@NonNull String packageName) { mRequestorPackageName = packageName; return this; } /** - * @return the package name of the app making the request. + * Returns the package name of the app making the request. * - * Note: This could return {@code null} if the {@link NetworkRequest} object was not obtained - * from {@link ConnectivityManager}. + * For a NetworkRequest being made by an app, contains the app's package name. For a + * network created by the system, contains the package name of the only app whose + * requests can match this network, or null if none or if the caller does not have + * permission to learn about this. + * + * @return the package name of the app making the request. * @hide */ @Nullable @@ -1907,9 +1920,9 @@ public final class NetworkCapabilities implements Parcelable { } /** - * Set the uid and package name of the app making the request. + * Set the uid and package name of the app causing this network to exist. * - * Note: This is intended to be only invoked from within connectivitiy service. + * {@see #setRequestorUid} and {@link #setRequestorPackageName} * * @param uid UID of the app. * @param packageName package name of the app. @@ -1968,4 +1981,316 @@ public final class NetworkCapabilities implements Parcelable { return mRequestorUid == nc.mRequestorUid && TextUtils.equals(mRequestorPackageName, nc.mRequestorPackageName); } + + /** + * Builder class for NetworkCapabilities. + * + * This class is mainly for for {@link NetworkAgent} instances to use. Many fields in + * the built class require holding a signature permission to use - mostly + * {@link android.Manifest.permission.NETWORK_FACTORY}, but refer to the specific + * description of each setter. As this class lives entirely in app space it does not + * enforce these restrictions itself but the system server clears out the relevant + * fields when receiving a NetworkCapabilities object from a caller without the + * appropriate permission. + * + * Apps don't use this builder directly. Instead, they use {@link NetworkRequest} via + * its builder object. + * + * @hide + */ + @SystemApi + @TestApi + public static class Builder { + private final NetworkCapabilities mCaps; + + /** + * Creates a new Builder to construct NetworkCapabilities objects. + */ + public Builder() { + mCaps = new NetworkCapabilities(); + } + + /** + * Creates a new Builder of NetworkCapabilities from an existing instance. + */ + public Builder(@NonNull final NetworkCapabilities nc) { + Objects.requireNonNull(nc); + mCaps = new NetworkCapabilities(nc); + } + + /** + * Adds the given transport type. + * + * Multiple transports may be added. Note that when searching for a network to satisfy a + * request, satisfying any of the transports listed in the request will satisfy the request. + * For example {@code TRANSPORT_WIFI} and {@code TRANSPORT_ETHERNET} added to a + * {@code NetworkCapabilities} would cause either a Wi-Fi network or an Ethernet network + * to be selected. This is logically different than + * {@code NetworkCapabilities.NET_CAPABILITY_*}. + * + * @param transportType the transport type to be added or removed. + * @return this builder + */ + @NonNull + public Builder addTransportType(@Transport int transportType) { + checkValidTransportType(transportType); + mCaps.addTransportType(transportType); + return this; + } + + /** + * Removes the given transport type. + * + * {@see #addTransportType}. + * + * @param transportType the transport type to be added or removed. + * @return this builder + */ + @NonNull + public Builder removeTransportType(@Transport int transportType) { + checkValidTransportType(transportType); + mCaps.removeTransportType(transportType); + return this; + } + + /** + * Adds the given capability. + * + * @param capability the capability + * @return this builder + */ + @NonNull + public Builder addCapability(@NetCapability final int capability) { + mCaps.setCapability(capability, true); + return this; + } + + /** + * Removes the given capability. + * + * @param capability the capability + * @return this builder + */ + @NonNull + public Builder removeCapability(@NetCapability final int capability) { + mCaps.setCapability(capability, false); + return this; + } + + /** + * Sets the owner UID. + * + * The default value is {@link Process#INVALID_UID}. Pass this value to reset. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source. + * + * @param ownerUid the owner UID + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setOwnerUid(final int ownerUid) { + mCaps.setOwnerUid(ownerUid); + return this; + } + + /** + * Sets the list of UIDs that are administrators of this network. + * + *

    UIDs included in administratorUids gain administrator privileges over this + * Network. Examples of UIDs that should be included in administratorUids are: + *

      + *
    • Carrier apps with privileges for the relevant subscription + *
    • Active VPN apps + *
    • Other application groups with a particular Network-related role + *
    + * + *

    In general, user-supplied networks (such as WiFi networks) do not have + * administrators. + * + *

    An app is granted owner privileges over Networks that it supplies. The owner + * UID MUST always be included in administratorUids. + * + * The default value is the empty array. Pass an empty array to reset. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source, such as an app using reflection to call this or + * mutate the member in the built object. + * + * @param administratorUids the UIDs to be set as administrators of this Network. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setAdministratorUids(@NonNull final int[] administratorUids) { + Objects.requireNonNull(administratorUids); + mCaps.setAdministratorUids(administratorUids); + return this; + } + + /** + * Sets the upstream bandwidth of the link. + * + * Sets the upstream bandwidth for this network in Kbps. This always only refers to + * the estimated first hop transport bandwidth. + *

    + * Note that when used to request a network, this specifies the minimum acceptable. + * When received as the state of an existing network this specifies the typical + * first hop bandwidth expected. This is never measured, but rather is inferred + * from technology type and other link parameters. It could be used to differentiate + * between very slow 1xRTT cellular links and other faster networks or even between + * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between + * fast backhauls and slow backhauls. + * + * @param upKbps the estimated first hop upstream (device to network) bandwidth. + * @return this builder + */ + @NonNull + public Builder setLinkUpstreamBandwidthKbps(final int upKbps) { + mCaps.setLinkUpstreamBandwidthKbps(upKbps); + return this; + } + + /** + * Sets the downstream bandwidth for this network in Kbps. This always only refers to + * the estimated first hop transport bandwidth. + *

    + * Note that when used to request a network, this specifies the minimum acceptable. + * When received as the state of an existing network this specifies the typical + * first hop bandwidth expected. This is never measured, but rather is inferred + * from technology type and other link parameters. It could be used to differentiate + * between very slow 1xRTT cellular links and other faster networks or even between + * 802.11b vs 802.11AC wifi technologies. It should not be used to differentiate between + * fast backhauls and slow backhauls. + * + * @param downKbps the estimated first hop downstream (network to device) bandwidth. + * @return this builder + */ + @NonNull + public Builder setLinkDownstreamBandwidthKbps(final int downKbps) { + mCaps.setLinkDownstreamBandwidthKbps(downKbps); + return this; + } + + /** + * Sets the optional bearer specific network specifier. + * This has no meaning if a single transport is also not specified, so calling + * this without a single transport set will generate an exception, as will + * subsequently adding or removing transports after this is set. + *

    + * + * @param specifier a concrete, parcelable framework class that extends NetworkSpecifier, + * or null to clear it. + * @return this builder + */ + @NonNull + public Builder setNetworkSpecifier(@Nullable final NetworkSpecifier specifier) { + mCaps.setNetworkSpecifier(specifier); + return this; + } + + /** + * Sets the optional transport specific information. + * + * @param info A concrete, parcelable framework class that extends {@link TransportInfo}, + * or null to clear it. + * @return this builder + */ + @NonNull + public Builder setTransportInfo(@Nullable final TransportInfo info) { + mCaps.setTransportInfo(info); + return this; + } + + /** + * Sets the signal strength. This is a signed integer, with higher values indicating a + * stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the + * same RSSI units reported by wifi code. + *

    + * Note that when used to register a network callback, this specifies the minimum + * acceptable signal strength. When received as the state of an existing network it + * specifies the current value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means + * no value when received and has no effect when requesting a callback. + * + * Note: for security the system will throw if it receives a NetworkRequest where + * the underlying NetworkCapabilities has this member set from a source that does + * not hold the {@link android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP} + * permission. Apps with this permission can use this indirectly through + * {@link android.net.NetworkRequest}. + * + * @param signalStrength the bearer-specific signal strength. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP) + public Builder setSignalStrength(final int signalStrength) { + mCaps.setSignalStrength(signalStrength); + return this; + } + + /** + * Sets the SSID of this network. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source, like an app using reflection to set this. + * + * @param ssid the SSID, or null to clear it. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setSsid(@Nullable final String ssid) { + mCaps.setSSID(ssid); + return this; + } + + /** + * Set the uid of the app causing this network to exist. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source. + * + * @param uid UID of the app. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setRequestorUid(final int uid) { + mCaps.setRequestorUid(uid); + return this; + } + + /** + * Set the package name of the app causing this network to exist. + * + * Note: for security the system will clear out this field when received from a + * non-privileged source. + * + * @param packageName package name of the app, or null to clear it. + * @return this builder + */ + @NonNull + @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) + public Builder setRequestorPackageName(@Nullable final String packageName) { + mCaps.setRequestorPackageName(packageName); + return this; + } + + /** + * Builds the instance of the capabilities. + * + * @return the built instance of NetworkCapabilities. + */ + @NonNull + public NetworkCapabilities build() { + if (mCaps.getOwnerUid() != Process.INVALID_UID) { + if (!ArrayUtils.contains(mCaps.getAdministratorUids(), mCaps.getOwnerUid())) { + throw new IllegalStateException("The owner UID must be included in " + + " administrator UIDs."); + } + } + return new NetworkCapabilities(mCaps); + } + } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index b89b1eb9c8..f769a11b01 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5333,7 +5333,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // specific SSID/SignalStrength, or the calling app has permission to do so. private void ensureSufficientPermissionsForRequest(NetworkCapabilities nc, int callerPid, int callerUid, String callerPackageName) { - if (null != nc.getSSID() && !checkSettingsPermission(callerPid, callerUid)) { + if (null != nc.getSsid() && !checkSettingsPermission(callerPid, callerUid)) { throw new SecurityException("Insufficient permissions to request a specific SSID"); } @@ -5793,7 +5793,7 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); final String extraInfo = networkInfo.getExtraInfo(); final String name = TextUtils.isEmpty(extraInfo) - ? nai.networkCapabilities.getSSID() : extraInfo; + ? nai.networkCapabilities.getSsid() : extraInfo; if (DBG) log("registerNetworkAgent " + nai); final long token = Binder.clearCallingIdentity(); try { diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java index 0925de8f95..34b0aa2464 100644 --- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java +++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java @@ -150,7 +150,7 @@ public class NetworkNotificationManager { if (nai != null) { transportType = approximateTransportType(nai); final String extraInfo = nai.networkInfo.getExtraInfo(); - name = TextUtils.isEmpty(extraInfo) ? nai.networkCapabilities.getSSID() : extraInfo; + name = TextUtils.isEmpty(extraInfo) ? nai.networkCapabilities.getSsid() : extraInfo; // Only notify for Internet-capable networks. if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)) return; } else { @@ -183,14 +183,14 @@ public class NetworkNotificationManager { int icon = getIcon(transportType); if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.PRIVATE_DNS_BROKEN) { if (transportType == TRANSPORT_CELLULAR) { title = r.getString(R.string.mobile_no_internet); } else if (transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); } else { title = r.getString(R.string.other_networks_no_internet); } @@ -198,19 +198,19 @@ public class NetworkNotificationManager { } else if (notifyType == NotificationType.PARTIAL_CONNECTIVITY && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.network_partial_connectivity, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); details = r.getString(R.string.network_partial_connectivity_detailed); } else if (notifyType == NotificationType.LOST_INTERNET && transportType == TRANSPORT_WIFI) { title = r.getString(R.string.wifi_no_internet, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); details = r.getString(R.string.wifi_no_internet_detailed); } else if (notifyType == NotificationType.SIGN_IN) { switch (transportType) { case TRANSPORT_WIFI: title = r.getString(R.string.wifi_available_sign_in, 0); details = r.getString(R.string.network_available_sign_in_detailed, - WifiInfo.sanitizeSsid(nai.networkCapabilities.getSSID())); + WifiInfo.sanitizeSsid(nai.networkCapabilities.getSsid())); break; case TRANSPORT_CELLULAR: title = r.getString(R.string.network_available_sign_in, 0); diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index efea91ab91..f10da2dc00 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -443,7 +443,7 @@ public class NetworkCapabilitiesTest { nc1.setSSID(TEST_SSID); nc2.combineCapabilities(nc1); - assertTrue(TEST_SSID.equals(nc2.getSSID())); + assertTrue(TEST_SSID.equals(nc2.getSsid())); // Because they now have the same SSID, the following call should not throw nc2.combineCapabilities(nc1); @@ -581,12 +581,12 @@ public class NetworkCapabilitiesTest { // from nc2. assertFalse(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING)); - assertTrue(TEST_SSID.equals(nc2.getSSID())); + assertTrue(TEST_SSID.equals(nc2.getSsid())); nc1.setSSID(DIFFERENT_TEST_SSID); nc2.set(nc1); assertEquals(nc1, nc2); - assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSSID())); + assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSsid())); nc1.setUids(uidRange(10, 13)); nc2.set(nc1); // Overwrites, as opposed to combineCapabilities From cf7bb0ee0634dbcce05d11e7f8b91383663cd964 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Wed, 18 Mar 2020 21:11:29 +0000 Subject: [PATCH 120/229] Restrict VPN Diagnostics callbacks to underlying networks. ConnectivityDiagnosticsCallbacks should only be invoked for the underlying networks declared by active VPNs. This encourages VPN apps to declare their underlying networks. The previous permission model for VPNs allowed active VPNs to receive callbacks on any network. Bug: 148903617 Test: atest FrameworksNetTests Change-Id: Ic08cdd2e2532580fda0fd3034e2bdff27e0ff84b Merged-In: Ic08cdd2e2532580fda0fd3034e2bdff27e0ff84b (cherry picked from commit e1f0c56f74593d3781bfa4ee4871a5efbabe303c) --- .../android/server/ConnectivityService.java | 9 ++++-- .../server/ConnectivityServiceTest.java | 28 +++++++++++++++++-- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 4d504e7423..84f144eda7 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -7949,10 +7949,13 @@ public class ConnectivityService extends IConnectivityManager.Stub return false; } + final Network[] underlyingNetworks; synchronized (mVpns) { - if (getVpnIfOwner(callbackUid) != null) { - return true; - } + final Vpn vpn = getVpnIfOwner(callbackUid); + underlyingNetworks = (vpn == null) ? null : vpn.getUnderlyingNetworks(); + } + if (underlyingNetworks != null) { + if (Arrays.asList(underlyingNetworks).contains(nai.network)) return true; } // Administrator UIDs also contains the Owner UID diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 4bfb51bca2..2f86d2ceda 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -307,6 +307,8 @@ public class ConnectivityServiceTest { private static final long TIMESTAMP = 1234L; + private static final int NET_ID = 110; + private static final String CLAT_PREFIX = "v4-"; private static final String MOBILE_IFNAME = "test_rmnet_data0"; private static final String WIFI_IFNAME = "test_wlan0"; @@ -1015,6 +1017,7 @@ public class ConnectivityServiceTest { private int mVpnType = VpnManager.TYPE_VPN_SERVICE; private VpnInfo mVpnInfo; + private Network[] mUnderlyingNetworks; public MockVpn(int userId) { super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService, @@ -1104,9 +1107,21 @@ public class ConnectivityServiceTest { return super.getVpnInfo(); } - private void setVpnInfo(VpnInfo vpnInfo) { + private synchronized void setVpnInfo(VpnInfo vpnInfo) { mVpnInfo = vpnInfo; } + + @Override + public synchronized Network[] getUnderlyingNetworks() { + if (mUnderlyingNetworks != null) return mUnderlyingNetworks; + + return super.getUnderlyingNetworks(); + } + + /** Don't override behavior for {@link Vpn#setUnderlyingNetworks}. */ + private synchronized void overrideUnderlyingNetworks(Network[] underlyingNetworks) { + mUnderlyingNetworks = underlyingNetworks; + } } private void mockVpn(int uid) { @@ -6824,9 +6839,10 @@ public class ConnectivityServiceTest { @Test public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception { + final Network network = new Network(NET_ID); final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( - null, null, null, null, null, new NetworkCapabilities(), 0, + null, null, network, null, null, new NetworkCapabilities(), 0, mServiceContext, null, null, mService, null, null, null, 0); setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, @@ -6839,11 +6855,19 @@ public class ConnectivityServiceTest { info.ownerUid = Process.myUid(); info.vpnIface = "interface"; mMockVpn.setVpnInfo(info); + mMockVpn.overrideUnderlyingNetworks(new Network[] {network}); assertTrue( "Active VPN permission not applied", mService.checkConnectivityDiagnosticsPermissions( Process.myPid(), Process.myUid(), naiWithoutUid, mContext.getOpPackageName())); + + mMockVpn.overrideUnderlyingNetworks(null); + assertFalse( + "VPN shouldn't receive callback on non-underlying network", + mService.checkConnectivityDiagnosticsPermissions( + Process.myPid(), Process.myUid(), naiWithoutUid, + mContext.getOpPackageName())); } @Test From 21105c9771d1f65db9b3de5a40cbe5d62e196277 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Mon, 16 Mar 2020 20:37:44 +0000 Subject: [PATCH 121/229] Clean up unit testing for ConnectivityDiagnostics. Connectivity Diagnostics included an unnecessary try-catch for verifying that the permissions check for invoking ConnectivityDiagnosticsCallbacks doesn't throw when the uid and package name do not match. Bug: 149119324 Test: atest FrameworksNetTests Change-Id: Ie302b1f4f437e819fdd15ec28adb0b56750c2c53 Merged-In: Ie302b1f4f437e819fdd15ec28adb0b56750c2c53 (cherry picked from commit 66b5e081b785a3b7e2a032342d4d424905581cf9) --- .../android/server/ConnectivityServiceTest.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 2f86d2ceda..83399b8076 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6810,15 +6810,11 @@ public class ConnectivityServiceTest { mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); - try { - assertFalse( - "Mismatched uid/package name should not pass the location permission check", - mService.checkConnectivityDiagnosticsPermissions( - Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid, - mContext.getOpPackageName())); - } catch (SecurityException e) { - fail("checkConnectivityDiagnosticsPermissions shouldn't surface a SecurityException"); - } + assertFalse( + "Mismatched uid/package name should not pass the location permission check", + mService.checkConnectivityDiagnosticsPermissions( + Process.myPid() + 1, Process.myUid() + 1, naiWithoutUid, + mContext.getOpPackageName())); } @Test From cbd7b6b1dd29f091d223f38adb6201d5ea49f268 Mon Sep 17 00:00:00 2001 From: Treehugger Robot Date: Tue, 24 Mar 2020 06:53:37 +0000 Subject: [PATCH 122/229] Fix addRoute replace default route unexpectedly In aosp/1203789, if two routes are with the same destination, it will be replaced instead of added when calling addRoute. This breaks scenarios which rely on the ability to add multiple default routes, such as multiple IPv6 default routes learned via address autoconfiguration. This change treats the route is an update if the destination and nexthop are the same, but different in other properties. Test: atest OffloadControllerTest#testSetUpstreamLinkPropertiesWorking Test: atest LinkPropertiesUtilsTest#testLinkPropertiesIdenticalEqual Test: atest ConnectivityServiceTest#testStackedLinkProperties Test: atest ConnectivityServiceTest#testRouteAddDeleteUpdate (only directly related tests are listed) Fix: 152170074 Fix: 151911339 Bug: 142892223 Change-Id: I7153ec9866f14a109ba8155c905e5d9e4f85eb64 Merged-In: I7153ec9866f14a109ba8155c905e5d9e4f85eb64 (cherry picked from commit 11aa9cb44aee289329b306cfc51a73cfe1456b61) --- core/java/android/net/LinkProperties.java | 16 +++++----- core/java/android/net/RouteInfo.java | 31 +++++++++++-------- .../android/server/ConnectivityService.java | 11 +++---- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 2c356e43d9..7ff954bdc1 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -690,9 +690,9 @@ public final class LinkProperties implements Parcelable { route.getMtu()); } - private int findRouteIndexByDestination(RouteInfo route) { + private int findRouteIndexByRouteKey(RouteInfo route) { for (int i = 0; i < mRoutes.size(); i++) { - if (mRoutes.get(i).isSameDestinationAs(route)) { + if (mRoutes.get(i).getRouteKey().equals(route.getRouteKey())) { return i; } } @@ -701,11 +701,11 @@ public final class LinkProperties implements Parcelable { /** * Adds a {@link RouteInfo} to this {@code LinkProperties}, if a {@link RouteInfo} - * with the same destination exists with different properties (e.g., different MTU), - * it will be updated. If the {@link RouteInfo} had an interface name set and - * that differs from the interface set for this {@code LinkProperties} an - * {@link IllegalArgumentException} will be thrown. The proper - * course is to add either un-named or properly named {@link RouteInfo}. + * with the same {@link RouteInfo.RouteKey} with different properties + * (e.g., different MTU), it will be updated. If the {@link RouteInfo} had an + * interface name set and that differs from the interface set for this + * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown. + * The proper course is to add either un-named or properly named {@link RouteInfo}. * * @param route A {@link RouteInfo} to add to this object. * @return {@code true} was added or updated, false otherwise. @@ -719,7 +719,7 @@ public final class LinkProperties implements Parcelable { } route = routeWithInterface(route); - int i = findRouteIndexByDestination(route); + int i = findRouteIndexByRouteKey(route); if (i == -1) { // Route was not present. Add it. mRoutes.add(route); diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index fec2df412a..dbdaa4c2da 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -26,6 +26,7 @@ import android.net.util.NetUtils; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.util.Pair; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -527,23 +528,27 @@ public final class RouteInfo implements Parcelable { } /** - * Compares this RouteInfo object against the specified object and indicates if the - * destinations of both routes are equal. - * @return {@code true} if the route destinations are equal, {@code false} otherwise. + * A helper class that contains the destination and the gateway in a {@code RouteInfo}, + * used by {@link ConnectivityService#updateRoutes} or + * {@link LinkProperties#addRoute} to calculate the list to be updated. * * @hide */ - public boolean isSameDestinationAs(@Nullable Object obj) { - if (this == obj) return true; - - if (!(obj instanceof RouteInfo)) return false; - - RouteInfo target = (RouteInfo) obj; - - if (Objects.equals(mDestination, target.getDestination())) { - return true; + public static class RouteKey extends Pair { + RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway) { + super(destination, gateway); } - return false; + } + + /** + * Get {@code RouteKey} of this {@code RouteInfo}. + * @return a {@code RouteKey} object. + * + * @hide + */ + @NonNull + public RouteKey getRouteKey() { + return new RouteKey(mDestination, mGateway); } /** diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 4d504e7423..ec84ae73d6 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -234,7 +234,6 @@ import java.util.SortedSet; import java.util.StringJoiner; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; /** * @hide @@ -5989,12 +5988,12 @@ public class ConnectivityService extends IConnectivityManager.Stub * @return true if routes changed between oldLp and newLp */ private boolean updateRoutes(LinkProperties newLp, LinkProperties oldLp, int netId) { - Function getDestination = (r) -> r.getDestination(); // compare the route diff to determine which routes have been updated - CompareOrUpdateResult routeDiff = new CompareOrUpdateResult<>( - oldLp != null ? oldLp.getAllRoutes() : null, - newLp != null ? newLp.getAllRoutes() : null, - getDestination); + final CompareOrUpdateResult routeDiff = + new CompareOrUpdateResult<>( + oldLp != null ? oldLp.getAllRoutes() : null, + newLp != null ? newLp.getAllRoutes() : null, + (r) -> r.getRouteKey()); // add routes before removing old in case it helps with continuous connectivity From 88cef1a2425873c9fcb90bcc4acbba3ef4582888 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Tue, 24 Mar 2020 19:00:09 +0800 Subject: [PATCH 123/229] Fix NetworkCapabilitiesTest fail on Q device The getSSID() has changed to getSsid() in Android R, adding isAtLeastR() to prevent NetworkCapabilitiesTest fail on Android Q. Bug: 151322799 Test: Run "atest CtsNetTestCasesLatestSdk:NetworkCapabilitiesTest" on Android Q & R device. Change-Id: I602ae32dae1ad29fe3293c541fa6d2cef01b81d3 --- .../java/android/net/NetworkCapabilitiesTest.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index b2e8c378d9..916c339811 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -463,7 +463,9 @@ public class NetworkCapabilitiesTest { nc1.setSSID(TEST_SSID); nc2.combineCapabilities(nc1); - assertTrue(TEST_SSID.equals(nc2.getSsid())); + if (isAtLeastR()) { + assertTrue(TEST_SSID.equals(nc2.getSsid())); + } // Because they now have the same SSID, the following call should not throw nc2.combineCapabilities(nc1); @@ -601,12 +603,16 @@ public class NetworkCapabilitiesTest { // from nc2. assertFalse(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING)); - assertTrue(TEST_SSID.equals(nc2.getSsid())); + if (isAtLeastR()) { + assertTrue(TEST_SSID.equals(nc2.getSsid())); + } nc1.setSSID(DIFFERENT_TEST_SSID); nc2.set(nc1); assertEquals(nc1, nc2); - assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSsid())); + if (isAtLeastR()) { + assertTrue(DIFFERENT_TEST_SSID.equals(nc2.getSsid())); + } nc1.setUids(uidRange(10, 13)); nc2.set(nc1); // Overwrites, as opposed to combineCapabilities From 4b1aada0aa3340877cd276b02a5fffb566a67d45 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Wed, 25 Mar 2020 13:36:38 +0800 Subject: [PATCH 124/229] API review: make exception class and Builder final - InvalidPacketException exception class should be final - NetworkCapabilities.Builder should be final Bug: 152203926 Test: atest FrameworksNetTests Change-Id: If9b799151aff6d41c9bcd8bb86c65a58e46bad73 --- core/java/android/net/InvalidPacketException.java | 2 +- core/java/android/net/NetworkCapabilities.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/InvalidPacketException.java b/core/java/android/net/InvalidPacketException.java index b3b0f11a77..1873d778c0 100644 --- a/core/java/android/net/InvalidPacketException.java +++ b/core/java/android/net/InvalidPacketException.java @@ -27,7 +27,7 @@ import java.lang.annotation.RetentionPolicy; * @hide */ @SystemApi -public class InvalidPacketException extends Exception { +public final class InvalidPacketException extends Exception { private final int mError; // Must match SocketKeepalive#ERROR_INVALID_IP_ADDRESS. diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index fcfcebdf08..05d7860ff8 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -2000,7 +2000,7 @@ public final class NetworkCapabilities implements Parcelable { */ @SystemApi @TestApi - public static class Builder { + public static final class Builder { private final NetworkCapabilities mCaps; /** From d6e8d4ab712d854f03908435af27db83e9861c01 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Wed, 25 Mar 2020 05:50:51 +0000 Subject: [PATCH 125/229] Automatically set IPsec tunnel interface as up This change makes IPsec tunnel interfaces automatically get brought up once they are created. Originally this was considered to be an additional safety check, as they would not be start routing traffic until explicitly brought up. However, in the intervening time, the NetworkManagementController now requires the NETWORK_STACK permission to set an interface as up. Additionally, that call is a hidden API, and thus not usable for use cases such as IWLAN. Bug: 149348618 Test: FrameworksNetTests, CtsNetTestCases passing. Change-Id: I55b63a748463a388e1e2991d2d5d6b3023545e60 Merged-In: I55b63a748463a388e1e2991d2d5d6b3023545e60 (cherry picked from commit 7c5704d177a903034ae1b6ae4800cc3b8457977a) --- .../android/server/IpSecServiceParameterizedTest.java | 6 +++++- .../server/IpSecServiceRefcountedResourceTest.java | 4 +++- .../net/java/com/android/server/IpSecServiceTest.java | 11 +++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 71b72b84de..23098ec067 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -46,6 +46,7 @@ import android.net.LinkAddress; import android.net.Network; import android.net.NetworkUtils; import android.os.Binder; +import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.system.Os; import android.test.mock.MockContext; @@ -135,6 +136,7 @@ public class IpSecServiceParameterizedTest { }; INetd mMockNetd; + INetworkManagementService mNetworkManager; PackageManager mMockPkgMgr; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; @@ -160,9 +162,10 @@ public class IpSecServiceParameterizedTest { @Before public void setUp() throws Exception { mMockNetd = mock(INetd.class); + mNetworkManager = mock(INetworkManagementService.class); mMockPkgMgr = mock(PackageManager.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); + mIpSecService = new IpSecService(mMockContext, mNetworkManager, mMockIpSecSrvConfig); // Injecting mock netd when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); @@ -609,6 +612,7 @@ public class IpSecServiceParameterizedTest { anyInt(), anyInt(), anyInt()); + verify(mNetworkManager).setInterfaceUp(createTunnelResp.interfaceName); } @Test diff --git a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java index 22a2c94fc1..788e4efe09 100644 --- a/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceRefcountedResourceTest.java @@ -31,6 +31,7 @@ import static org.mockito.Mockito.verify; import android.content.Context; import android.os.Binder; import android.os.IBinder; +import android.os.INetworkManagementService; import android.os.RemoteException; import androidx.test.filters.SmallTest; @@ -61,7 +62,8 @@ public class IpSecServiceRefcountedResourceTest { public void setUp() throws Exception { mMockContext = mock(Context.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); + mIpSecService = new IpSecService( + mMockContext, mock(INetworkManagementService.class), mMockIpSecSrvConfig); } private void assertResourceState( diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java index 4a35015044..536e98327e 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceTest.java @@ -42,6 +42,7 @@ import android.net.IpSecManager; import android.net.IpSecSpiResponse; import android.net.IpSecUdpEncapResponse; import android.os.Binder; +import android.os.INetworkManagementService; import android.os.ParcelFileDescriptor; import android.os.Process; import android.system.ErrnoException; @@ -115,6 +116,7 @@ public class IpSecServiceTest { } Context mMockContext; + INetworkManagementService mMockNetworkManager; INetd mMockNetd; IpSecService.IpSecServiceConfiguration mMockIpSecSrvConfig; IpSecService mIpSecService; @@ -122,9 +124,10 @@ public class IpSecServiceTest { @Before public void setUp() throws Exception { mMockContext = mock(Context.class); + mMockNetworkManager = mock(INetworkManagementService.class); mMockNetd = mock(INetd.class); mMockIpSecSrvConfig = mock(IpSecService.IpSecServiceConfiguration.class); - mIpSecService = new IpSecService(mMockContext, mMockIpSecSrvConfig); + mIpSecService = new IpSecService(mMockContext, mMockNetworkManager, mMockIpSecSrvConfig); // Injecting mock netd when(mMockIpSecSrvConfig.getNetdInstance()).thenReturn(mMockNetd); @@ -132,7 +135,7 @@ public class IpSecServiceTest { @Test public void testIpSecServiceCreate() throws InterruptedException { - IpSecService ipSecSrv = IpSecService.create(mMockContext); + IpSecService ipSecSrv = IpSecService.create(mMockContext, mMockNetworkManager); assertNotNull(ipSecSrv); } @@ -604,8 +607,8 @@ public class IpSecServiceTest { @Test public void testOpenUdpEncapSocketTagsSocket() throws Exception { IpSecService.UidFdTagger mockTagger = mock(IpSecService.UidFdTagger.class); - IpSecService testIpSecService = - new IpSecService(mMockContext, mMockIpSecSrvConfig, mockTagger); + IpSecService testIpSecService = new IpSecService( + mMockContext, mMockNetworkManager, mMockIpSecSrvConfig, mockTagger); IpSecUdpEncapResponse udpEncapResp = testIpSecService.openUdpEncapsulationSocket(0, new Binder()); From d22cb127b974d698b3a2220f9528e065fb082b21 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 25 Mar 2020 10:33:55 +0000 Subject: [PATCH 126/229] Allow MANAGE_TEST_NETWORKS to register limited agents This puts in force some restrictions against test networks, and in exchange relaxes the restrictions around registering a network agent that provides a test network. Test networks can only ever have transport TEST, and have only a few capabilities available to them. This is useful in particular to test CTS. See aosp/1253423 for first, basic usage of this capability. Test: IpSecManagerTunnelTest Test: new CTS aosp/1253423 Bug: 139268426 Change-Id: Ibd162792a7ab02fcbb06130f21a825a386678c05 (cherry picked from commit 2c129e97cca2234ee6dd079a9c07df0c530d8b36) --- .../java/android/net/NetworkCapabilities.java | 29 +++++++++++++++++++ .../android/server/ConnectivityService.java | 23 +++++++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 05d7860ff8..af9414c566 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -414,6 +414,20 @@ public final class NetworkCapabilities implements Parcelable { | (1 << NET_CAPABILITY_FOREGROUND) | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY); + /** + * Capabilities that are allowed for test networks. This list must be set so that it is safe + * for an unprivileged user to create a network with these capabilities via shell. As such, + * it must never contain capabilities that are generally useful to the system, such as + * INTERNET, IMS, SUPL, etc. + */ + private static final long TEST_NETWORKS_ALLOWED_CAPABILITIES = + (1 << NET_CAPABILITY_NOT_METERED) + | (1 << NET_CAPABILITY_NOT_RESTRICTED) + | (1 << NET_CAPABILITY_NOT_VPN) + | (1 << NET_CAPABILITY_NOT_ROAMING) + | (1 << NET_CAPABILITY_NOT_CONGESTED) + | (1 << NET_CAPABILITY_NOT_SUSPENDED); + /** * Adds the given capability to this {@code NetworkCapability} instance. * Note that when searching for a network to satisfy a request, all capabilities @@ -645,6 +659,21 @@ public final class NetworkCapabilities implements Parcelable { } } + /** + * Test networks have strong restrictions on what capabilities they can have. Enforce these + * restrictions. + * @hide + */ + public void restrictCapabilitesForTestNetwork() { + final long originalCapabilities = mNetworkCapabilities; + final NetworkSpecifier originalSpecifier = mNetworkSpecifier; + clearAll(); + // Reset the transports to only contain TRANSPORT_TEST. + mTransportTypes = (1 << TRANSPORT_TEST); + mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES; + mNetworkSpecifier = originalSpecifier; + } + /** * Representing the transport type. Apps should generally not care about transport. A * request for a fast internet connection could be satisfied by a number of different diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index ec84ae73d6..76a8e1474a 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -40,6 +40,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN; import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkPolicyManager.RULE_NONE; import static android.net.NetworkPolicyManager.uidRulesToString; @@ -50,6 +51,7 @@ import static android.system.OsConstants.IPPROTO_UDP; import static java.util.Map.Entry; +import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppOpsManager; @@ -2702,10 +2704,18 @@ public class ConnectivityService extends IConnectivityManager.Stub switch (msg.what) { case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: { - final NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj; + NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj; if (networkCapabilities.hasConnectivityManagedCapability()) { Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability."); } + if (networkCapabilities.hasTransport(TRANSPORT_TEST)) { + // Make sure the original object is not mutated. NetworkAgent normally + // makes a copy of the capabilities when sending the message through + // the Messenger, but if this ever changes, not making a defensive copy + // here will give attack vectors to clients using this code path. + networkCapabilities = new NetworkCapabilities(networkCapabilities); + networkCapabilities.restrictCapabilitesForTestNetwork(); + } updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities); break; } @@ -5778,7 +5788,16 @@ public class ConnectivityService extends IConnectivityManager.Stub public Network registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) { - enforceNetworkFactoryPermission(); + if (networkCapabilities.hasTransport(TRANSPORT_TEST)) { + enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS); + // Strictly, sanitizing here is unnecessary as the capabilities will be sanitized in + // the call to mixInCapabilities below anyway, but sanitizing here means the NAI never + // sees capabilities that may be malicious, which might prevent mistakes in the future. + networkCapabilities = new NetworkCapabilities(networkCapabilities); + networkCapabilities.restrictCapabilitesForTestNetwork(); + } else { + enforceNetworkFactoryPermission(); + } LinkProperties lp = new LinkProperties(linkProperties); lp.ensureDirectlyConnectedRoutes(); From 68d0e42789c51b030b1496d202ea82b4c4e8bb61 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Tue, 24 Mar 2020 23:16:35 +0900 Subject: [PATCH 127/229] Update the NetworkAgent API for council comments Bug: 152238712 Test: FrameworksNetTests NetworkStackTests Change-Id: I9a2691f783f4449348c3f767568e05620f0b9df5 --- core/java/android/net/NetworkAgent.java | 135 ++++++++++++++++----- core/java/android/net/NetworkRequest.java | 2 - core/java/android/net/SocketKeepalive.java | 10 ++ 3 files changed, 118 insertions(+), 29 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 5c754a1b97..8119df9217 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -16,6 +16,8 @@ package android.net; +import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -32,18 +34,52 @@ import android.util.Log; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; /** - * A Utility class for handling for communicating between bearer-specific + * A utility class for handling for communicating between bearer-specific * code and ConnectivityService. * + * An agent manages the life cycle of a network. A network starts its + * life cycle when {@link register} is called on NetworkAgent. The network + * is then connecting. When full L3 connectivity has been established, + * the agent shoud call {@link setConnected} to inform the system that + * this network is ready to use. When the network disconnects its life + * ends and the agent should call {@link unregister}, at which point the + * system will clean up and free resources. + * Any reconnection becomes a new logical network, so after a network + * is disconnected the agent cannot be used any more. Network providers + * should create a new NetworkAgent instance to handle new connections. + * * A bearer may have more than one NetworkAgent if it can simultaneously * support separate networks (IMS / Internet / MMS Apns on cellular, or * perhaps connections with different SSID or P2P for Wi-Fi). * + * This class supports methods to start and stop sending keepalive packets. + * Keepalive packets are typically sent at periodic intervals over a network + * with NAT when there is no other traffic to avoid the network forcefully + * closing the connection. NetworkAgents that manage technologies that + * have hardware support for keepalive should implement the related + * methods to save battery life. NetworkAgent that cannot get support + * without waking up the CPU should not, as this would be prohibitive in + * terms of battery - these agents should simply not override the related + * methods, which results in the implementation returning + * {@link SocketKeepalive.ERROR_UNSUPPORTED} as appropriate. + * + * Keepalive packets need to be sent at relatively frequent intervals + * (a few seconds to a few minutes). As the contents of keepalive packets + * depend on the current network status, hardware needs to be configured + * to send them and has a limited amount of memory to do so. The HAL + * formalizes this as slots that an implementation can configure to send + * the correct packets. Devices typically have a small number of slots + * per radio technology, and the specific number of slots for each + * technology is specified in configuration files. + * {@see SocketKeepalive} for details. + * * @hide */ @SystemApi @@ -65,7 +101,7 @@ public abstract class NetworkAgent { private final String LOG_TAG; private static final boolean DBG = true; private static final boolean VDBG = false; - private final ArrayListmPreConnectedQueue = new ArrayList(); + private final ArrayList mPreConnectedQueue = new ArrayList(); private volatile long mLastBwRefreshTime = 0; private static final long BW_REFRESH_MIN_WIN_MS = 500; private boolean mBandwidthUpdateScheduled = false; @@ -74,6 +110,8 @@ public abstract class NetworkAgent { // into the internal API of ConnectivityService. @NonNull private NetworkInfo mNetworkInfo; + @NonNull + private final Object mRegisterLock = new Object(); /** * The ID of the {@link NetworkProvider} that created this object, or @@ -158,6 +196,14 @@ public abstract class NetworkAgent { */ public static final int VALIDATION_STATUS_NOT_VALID = 2; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "VALIDATION_STATUS_" }, value = { + VALIDATION_STATUS_VALID, + VALIDATION_STATUS_NOT_VALID + }) + public @interface ValidationStatus {} + // TODO: remove. /** @hide */ public static final int VALID_NETWORK = 1; @@ -202,7 +248,7 @@ public abstract class NetworkAgent { * Sent by ConnectivityService to the NetworkAgent to request that the specified packet be sent * periodically on the given interval. * - * arg1 = the slot number of the keepalive to start + * arg1 = the hardware slot number of the keepalive to start * arg2 = interval in seconds * obj = KeepalivePacketData object describing the data to be sent * @@ -214,7 +260,7 @@ public abstract class NetworkAgent { /** * Requests that the specified keepalive packet be stopped. * - * arg1 = slot number of the keepalive to stop. + * arg1 = hardware slot number of the keepalive to stop. * * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. * @hide @@ -229,7 +275,7 @@ public abstract class NetworkAgent { * This is also sent by KeepaliveTracker to the app's {@link SocketKeepalive}, * so that the app's {@link SocketKeepalive.Callback} methods can be called. * - * arg1 = slot number of the keepalive + * arg1 = hardware slot number of the keepalive * arg2 = error code * @hide */ @@ -259,7 +305,7 @@ public abstract class NetworkAgent { * remote site will send ACK packets in response to the keepalive packets, the firmware also * needs to be configured to properly filter the ACKs to prevent the system from waking up. * This does not happen with UDP, so this message is TCP-specific. - * arg1 = slot number of the keepalive to filter for. + * arg1 = hardware slot number of the keepalive to filter for. * obj = the keepalive packet to send repeatedly. * @hide */ @@ -268,7 +314,7 @@ public abstract class NetworkAgent { /** * Sent by the KeepaliveTracker to NetworkAgent to remove a packet filter. See * {@link #CMD_ADD_KEEPALIVE_PACKET_FILTER}. - * arg1 = slot number of the keepalive packet filter to remove. + * arg1 = hardware slot number of the keepalive packet filter to remove. * @hide */ public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; @@ -441,7 +487,15 @@ public abstract class NetworkAgent { + (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") + redirectUrl); } - onValidationStatus(msg.arg1 /* status */, redirectUrl); + Uri uri = null; + try { + if (null != redirectUrl) { + uri = Uri.parse(redirectUrl); + } + } catch (Exception e) { + Log.wtf(LOG_TAG, "Surprising URI : " + redirectUrl, e); + } + onValidationStatus(msg.arg1 /* status */, uri); break; } case CMD_SAVE_ACCEPT_UNVALIDATED: { @@ -489,19 +543,29 @@ public abstract class NetworkAgent { /** * Register this network agent with ConnectivityService. + * + * This method can only be called once per network agent. + * * @return the Network associated with this network agent (which can also be obtained later * by calling getNetwork() on this agent). + * @throws IllegalStateException thrown by the system server if this network agent is + * already registered. */ @NonNull public Network register() { if (VDBG) log("Registering NetworkAgent"); final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context .getSystemService(Context.CONNECTIVITY_SERVICE); - mNetwork = cm.registerNetworkAgent(new Messenger(mHandler), - new NetworkInfo(mInitialConfiguration.info), - mInitialConfiguration.properties, mInitialConfiguration.capabilities, - mInitialConfiguration.score, mInitialConfiguration.config, providerId); - mInitialConfiguration = null; // All this memory can now be GC'd + synchronized (mRegisterLock) { + if (mNetwork != null) { + throw new IllegalStateException("Agent already registered"); + } + mNetwork = cm.registerNetworkAgent(new Messenger(mHandler), + new NetworkInfo(mInitialConfiguration.info), + mInitialConfiguration.properties, mInitialConfiguration.capabilities, + mInitialConfiguration.score, mInitialConfiguration.config, providerId); + mInitialConfiguration = null; // All this memory can now be GC'd + } return mNetwork; } @@ -544,13 +608,14 @@ public abstract class NetworkAgent { * Must be called by the agent when the network's {@link LinkProperties} change. * @param linkProperties the new LinkProperties. */ - public void sendLinkProperties(@NonNull LinkProperties linkProperties) { + public final void sendLinkProperties(@NonNull LinkProperties linkProperties) { Objects.requireNonNull(linkProperties); queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties)); } /** * Inform ConnectivityService that this agent has now connected. + * Call {@link #unregister} to disconnect. */ public void setConnected() { if (mIsLegacy) { @@ -569,8 +634,7 @@ public abstract class NetworkAgent { */ public void unregister() { if (mIsLegacy) { - throw new UnsupportedOperationException( - "Legacy agents can't call unregister."); + throw new UnsupportedOperationException("Legacy agents can't call unregister."); } mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null); queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); @@ -626,7 +690,7 @@ public abstract class NetworkAgent { * @hide TODO: expose something better. */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - public void sendNetworkInfo(NetworkInfo networkInfo) { + public final void sendNetworkInfo(NetworkInfo networkInfo) { if (!mIsLegacy) { throw new UnsupportedOperationException("Only legacy agents can call sendNetworkInfo."); } @@ -637,7 +701,7 @@ public abstract class NetworkAgent { * Must be called by the agent when the network's {@link NetworkCapabilities} change. * @param networkCapabilities the new NetworkCapabilities. */ - public void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) { + public final void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) { Objects.requireNonNull(networkCapabilities); mBandwidthUpdatePending.set(false); mLastBwRefreshTime = System.currentTimeMillis(); @@ -647,9 +711,10 @@ public abstract class NetworkAgent { /** * Must be called by the agent to update the score of this network. - * @param score the new score. + * + * @param score the new score, between 0 and 99. */ - public void sendNetworkScore(int score) { + public final void sendNetworkScore(@IntRange(from = 0, to = 99) int score) { if (score < 0) { throw new IllegalArgumentException("Score must be >= 0"); } @@ -737,11 +802,11 @@ public abstract class NetworkAgent { * subsequent attempts to validate connectivity that fail. * * @param status one of {@code VALIDATION_STATUS_VALID} or {@code VALIDATION_STATUS_NOT_VALID}. - * @param redirectUrl If Internet connectivity is being redirected (e.g., on a captive portal), + * @param redirectUri If Internet connectivity is being redirected (e.g., on a captive portal), * this is the destination the probes are being redirected to, otherwise {@code null}. */ - public void onValidationStatus(int status, @Nullable String redirectUrl) { - networkStatus(status, redirectUrl); + public void onValidationStatus(@ValidationStatus int status, @Nullable Uri redirectUri) { + networkStatus(status, redirectUri.toString()); } /** @hide TODO delete once subclasses have moved to onValidationStatus */ protected void networkStatus(int status, String redirectUrl) { @@ -770,7 +835,12 @@ public abstract class NetworkAgent { * @param intervalSeconds the interval between packets * @param packet the packet to send. */ - public void onStartSocketKeepalive(int slot, int intervalSeconds, + // seconds is from SocketKeepalive.MIN_INTERVAL_SEC to MAX_INTERVAL_SEC, but these should + // not be exposed as constants because they may change in the future (API guideline 4.8) + // and should have getters if exposed at all. Getters can't be used in the annotation, + // so the values unfortunately need to be copied. + public void onStartSocketKeepalive(int slot, + @IntRange(from = 10, to = 3600) int intervalSeconds, @NonNull KeepalivePacketData packet) { Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot, intervalSeconds, packet); @@ -801,9 +871,11 @@ public abstract class NetworkAgent { * Must be called by the agent when a socket keepalive event occurs. * * @param slot the hardware slot on which the event occurred. - * @param event the event that occurred. + * @param event the event that occurred, as one of the SocketKeepalive.ERROR_* + * or SocketKeepalive.SUCCESS constants. */ - public void sendSocketKeepaliveEvent(int slot, int event) { + public final void sendSocketKeepaliveEvent(int slot, + @SocketKeepalive.KeepaliveEvent int event) { queueOrSendMessage(EVENT_SOCKET_KEEPALIVE, slot, event); } /** @hide TODO delete once callers have moved to sendSocketKeepaliveEvent */ @@ -845,9 +917,18 @@ public abstract class NetworkAgent { } /** - * Called by ConnectivityService to inform this network transport of signal strength thresholds + * Called by ConnectivityService to inform this network agent of signal strength thresholds * that when crossed should trigger a system wakeup and a NetworkCapabilities update. * + * When the system updates the list of thresholds that should wake up the CPU for a + * given agent it will call this method on the agent. The agent that implement this + * should implement it in hardware so as to ensure the CPU will be woken up on breach. + * Agents are expected to react to a breach by sending an updated NetworkCapabilities + * object with the appropriate signal strength to sendNetworkCapabilities. + * + * The specific units are bearer-dependent. See details on the units and requests in + * {@link NetworkCapabilities.Builder#setSignalStrength}. + * * @param thresholds the array of thresholds that should trigger wakeups. */ public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index 964f13f39e..798856d13b 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -473,9 +473,7 @@ public class NetworkRequest implements Parcelable { * * @param nc Capabilities that should satisfy this NetworkRequest. null capabilities do not * satisfy any request. - * @hide */ - @SystemApi public boolean satisfiedBy(@Nullable NetworkCapabilities nc) { return networkCapabilities.satisfiedByNetworkCapabilities(nc); } diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java index fc9a8f63c1..8ff8f4c48c 100644 --- a/core/java/android/net/SocketKeepalive.java +++ b/core/java/android/net/SocketKeepalive.java @@ -109,6 +109,16 @@ public abstract class SocketKeepalive implements AutoCloseable { }) public @interface ErrorCode {} + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + SUCCESS, + ERROR_INVALID_LENGTH, + ERROR_UNSUPPORTED, + ERROR_INSUFFICIENT_RESOURCES + }) + public @interface KeepaliveEvent {} + /** * The minimum interval in seconds between keepalive packet transmissions. * From 15a3adbdf3789269b9e91022ca4c3f99bef9dfda Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 25 Mar 2020 01:24:04 +0900 Subject: [PATCH 128/229] Update NetworkAgentConfig API for council comments Bug: 152238712 Test: FrameworksNetTests NetworkStackTests Change-Id: Idca9f243a5c955f4caa30921ee520e1a93b0d11a --- .../java/android/net/ConnectivityManager.java | 30 +++++++++++++++++++ core/java/android/net/NetworkAgentConfig.java | 3 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 2a323e5ec9..7332ede0b9 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -705,6 +705,36 @@ public class ConnectivityManager { @Deprecated public static final int TYPE_TEST = 18; // TODO: Remove this once NetworkTypes are unused. + /** + * @deprecated Use {@link NetworkCapabilities} instead. + * @hide + */ + @Deprecated + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "TYPE_" }, value = { + TYPE_NONE, + TYPE_MOBILE, + TYPE_WIFI, + TYPE_MOBILE_MMS, + TYPE_MOBILE_SUPL, + TYPE_MOBILE_DUN, + TYPE_MOBILE_HIPRI, + TYPE_WIMAX, + TYPE_BLUETOOTH, + TYPE_DUMMY, + TYPE_ETHERNET, + TYPE_MOBILE_FOTA, + TYPE_MOBILE_IMS, + TYPE_MOBILE_CBS, + TYPE_WIFI_P2P, + TYPE_MOBILE_IA, + TYPE_MOBILE_EMERGENCY, + TYPE_PROXY, + TYPE_VPN, + TYPE_TEST + }) + public @interface LegacyNetworkType {} + // Deprecated constants for return values of startUsingNetworkFeature. They used to live // in com.android.internal.telephony.PhoneConstants until they were made inaccessible. private static final int DEPRECATED_PHONE_CONSTANT_APN_ALREADY_ACTIVE = 0; diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java index ca9328a713..fee868a93b 100644 --- a/core/java/android/net/NetworkAgentConfig.java +++ b/core/java/android/net/NetworkAgentConfig.java @@ -155,6 +155,7 @@ public final class NetworkAgentConfig implements Parcelable { /** * @return the legacy type */ + @ConnectivityManager.LegacyNetworkType public int getLegacyType() { return legacyType; } @@ -206,7 +207,7 @@ public final class NetworkAgentConfig implements Parcelable { /** * Builder class to facilitate constructing {@link NetworkAgentConfig} objects. */ - public static class Builder { + public static final class Builder { private final NetworkAgentConfig mConfig = new NetworkAgentConfig(); /** From fd23dbbf07475954fa34b6f46c802a026b4e81b8 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 25 Mar 2020 02:09:26 +0900 Subject: [PATCH 129/229] Update the NetworkProvider API for council comments Bug: 152238712 Test: FrameworksNetTests NetworkStackTests Change-Id: I6b086572cfc72a0727f4510351cff0e74cbc4302 --- core/java/android/net/NetworkProvider.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/NetworkProvider.java b/core/java/android/net/NetworkProvider.java index 418d6915d4..75086cf82b 100644 --- a/core/java/android/net/NetworkProvider.java +++ b/core/java/android/net/NetworkProvider.java @@ -16,6 +16,7 @@ package android.net; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -33,8 +34,8 @@ import android.util.Log; * {@link NetworkAgent}s. The networks can then provide connectivity to apps and can be interacted * with via networking APIs such as {@link ConnectivityManager}. * - * Subclasses should implement {@link #onNetworkRequested} and {@link #onRequestWithdrawn} to - * receive {@link NetworkRequest}s sent by the system and by apps. A network that is not the + * Subclasses should implement {@link #onNetworkRequested} and {@link #onNetworkRequestWithdrawn} + * to receive {@link NetworkRequest}s sent by the system and by apps. A network that is not the * best (highest-scoring) network for any request is generally not used by the system, and torn * down. * @@ -77,7 +78,7 @@ public class NetworkProvider { * Constructs a new NetworkProvider. * * @param looper the Looper on which to run {@link #onNetworkRequested} and - * {@link #onRequestWithdrawn}. + * {@link #onNetworkRequestWithdrawn}. * @param name the name of the listener, used only for debugging. * * @hide @@ -94,7 +95,7 @@ public class NetworkProvider { onNetworkRequested((NetworkRequest) m.obj, m.arg1, m.arg2); break; case CMD_CANCEL_REQUEST: - onRequestWithdrawn((NetworkRequest) m.obj); + onNetworkRequestWithdrawn((NetworkRequest) m.obj); break; default: Log.e(mName, "Unhandled message: " + m.what); @@ -142,14 +143,15 @@ public class NetworkProvider { * @hide */ @SystemApi - public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {} + public void onNetworkRequested(@NonNull NetworkRequest request, + @IntRange(from = 0, to = 99) int score, int providerId) {} /** * Called when a NetworkRequest is withdrawn. * @hide */ @SystemApi - public void onRequestWithdrawn(@NonNull NetworkRequest request) {} + public void onNetworkRequestWithdrawn(@NonNull NetworkRequest request) {} /** * Asserts that no provider will ever be able to satisfy the specified request. The provider @@ -157,7 +159,7 @@ public class NetworkProvider { * satisfying this request, and that the request cannot be satisfied. The application filing the * request will receive an {@link NetworkCallback#onUnavailable()} callback. * - * @param request the request that cannot be fulfilled + * @param request the request that permanently cannot be fulfilled * @hide */ @SystemApi From 812e8cb87e72169b71cfa9d7759f0da92529f2e3 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 27 Mar 2020 15:00:38 +0900 Subject: [PATCH 130/229] Address further API council comments. Test: FrameworksNetTests NetworkStackTests Bug: 152238712 Change-Id: I8a785ae0e74e659c317deaaa28c203356c7766ed --- core/java/android/net/NetworkAgent.java | 31 ++++++++++++++-------- core/java/android/net/SocketKeepalive.java | 3 ++- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 8119df9217..fe90a84579 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -36,6 +36,7 @@ import com.android.internal.util.Protocol; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.time.Duration; import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; @@ -47,7 +48,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * An agent manages the life cycle of a network. A network starts its * life cycle when {@link register} is called on NetworkAgent. The network * is then connecting. When full L3 connectivity has been established, - * the agent shoud call {@link setConnected} to inform the system that + * the agent shoud call {@link markConnected} to inform the system that * this network is ready to use. When the network disconnects its life * ends and the agent should call {@link unregister}, at which point the * system will clean up and free resources. @@ -503,7 +504,8 @@ public abstract class NetworkAgent { break; } case CMD_START_SOCKET_KEEPALIVE: { - onStartSocketKeepalive(msg.arg1 /* slot */, msg.arg2 /* interval */, + onStartSocketKeepalive(msg.arg1 /* slot */, + Duration.ofSeconds(msg.arg2) /* interval */, (KeepalivePacketData) msg.obj /* packet */); break; } @@ -617,10 +619,10 @@ public abstract class NetworkAgent { * Inform ConnectivityService that this agent has now connected. * Call {@link #unregister} to disconnect. */ - public void setConnected() { + public void markConnected() { if (mIsLegacy) { throw new UnsupportedOperationException( - "Legacy agents can't call setConnected."); + "Legacy agents can't call markConnected."); } mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); @@ -798,8 +800,8 @@ public abstract class NetworkAgent { * {@code VALIDATION_STATUS_VALID} if Internet connectivity was validated, * {@code VALIDATION_STATUS_NOT_VALID} if Internet connectivity was not validated. * - * This may be called multiple times as network status changes, or if there are multiple - * subsequent attempts to validate connectivity that fail. + * This is guaranteed to be called again when the network status changes, but the system + * may also call this multiple times even if the status does not change. * * @param status one of {@code VALIDATION_STATUS_VALID} or {@code VALIDATION_STATUS_NOT_VALID}. * @param redirectUri If Internet connectivity is being redirected (e.g., on a captive portal), @@ -832,18 +834,25 @@ public abstract class NetworkAgent { * Requests that the network hardware send the specified packet at the specified interval. * * @param slot the hardware slot on which to start the keepalive. - * @param intervalSeconds the interval between packets + * @param interval the interval between packets, between 10 and 3600. Note that this API + * does not support sub-second precision and will round off the request. * @param packet the packet to send. */ // seconds is from SocketKeepalive.MIN_INTERVAL_SEC to MAX_INTERVAL_SEC, but these should // not be exposed as constants because they may change in the future (API guideline 4.8) // and should have getters if exposed at all. Getters can't be used in the annotation, // so the values unfortunately need to be copied. - public void onStartSocketKeepalive(int slot, - @IntRange(from = 10, to = 3600) int intervalSeconds, + public void onStartSocketKeepalive(int slot, @NonNull Duration interval, @NonNull KeepalivePacketData packet) { - Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot, intervalSeconds, - packet); + final long intervalSeconds = interval.getSeconds(); + if (intervalSeconds < SocketKeepalive.MIN_INTERVAL_SEC + || intervalSeconds > SocketKeepalive.MAX_INTERVAL_SEC) { + throw new IllegalArgumentException("Interval needs to be comprised between " + + SocketKeepalive.MIN_INTERVAL_SEC + " and " + SocketKeepalive.MAX_INTERVAL_SEC + + " but was " + intervalSeconds); + } + final Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot, + (int) intervalSeconds, packet); startSocketKeepalive(msg); msg.recycle(); } diff --git a/core/java/android/net/SocketKeepalive.java b/core/java/android/net/SocketKeepalive.java index 8ff8f4c48c..46aef10258 100644 --- a/core/java/android/net/SocketKeepalive.java +++ b/core/java/android/net/SocketKeepalive.java @@ -115,7 +115,8 @@ public abstract class SocketKeepalive implements AutoCloseable { SUCCESS, ERROR_INVALID_LENGTH, ERROR_UNSUPPORTED, - ERROR_INSUFFICIENT_RESOURCES + ERROR_INSUFFICIENT_RESOURCES, + ERROR_HARDWARE_UNSUPPORTED }) public @interface KeepaliveEvent {} From 51b8e287ad9964123217deeb8d78973476233874 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 27 Mar 2020 17:57:34 +0900 Subject: [PATCH 131/229] Rename satisfiedBy into canBeSatisfiedBy Test: FrameworksNetTests NetworkStackTests Bug: 152238712 Change-Id: I076876a6662bde143ef7d315ce3767acafff93c1 --- core/java/android/net/NetworkCapabilities.java | 2 +- core/java/android/net/NetworkRequest.java | 2 +- .../java/com/android/server/ConnectivityServiceTest.java | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index af9414c566..91ef911ef2 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -1122,7 +1122,7 @@ public final class NetworkCapabilities implements Parcelable { } private boolean satisfiedBySpecifier(NetworkCapabilities nc) { - return mNetworkSpecifier == null || mNetworkSpecifier.satisfiedBy(nc.mNetworkSpecifier) + return mNetworkSpecifier == null || mNetworkSpecifier.canBeSatisfiedBy(nc.mNetworkSpecifier) || nc.mNetworkSpecifier instanceof MatchAllNetworkSpecifier; } diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index 798856d13b..a6bd74a587 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -474,7 +474,7 @@ public class NetworkRequest implements Parcelable { * @param nc Capabilities that should satisfy this NetworkRequest. null capabilities do not * satisfy any request. */ - public boolean satisfiedBy(@Nullable NetworkCapabilities nc) { + public boolean canBeSatisfiedBy(@Nullable NetworkCapabilities nc) { return networkCapabilities.satisfiedByNetworkCapabilities(nc); } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 4bfb51bca2..83f4c9817d 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -2896,7 +2896,7 @@ public class ConnectivityServiceTest { class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements Parcelable { @Override - public boolean satisfiedBy(NetworkSpecifier other) { + public boolean canBeSatisfiedBy(NetworkSpecifier other) { return true; } @@ -2924,7 +2924,7 @@ public class ConnectivityServiceTest { } @Override - public boolean satisfiedBy(NetworkSpecifier other) { + public boolean canBeSatisfiedBy(NetworkSpecifier other) { if (other instanceof LocalStringNetworkSpecifier) { return TextUtils.equals(mString, ((LocalStringNetworkSpecifier) other).mString); @@ -3045,7 +3045,10 @@ public class ConnectivityServiceTest { }); class NonParcelableSpecifier extends NetworkSpecifier { - public boolean satisfiedBy(NetworkSpecifier other) { return false; } + @Override + public boolean canBeSatisfiedBy(NetworkSpecifier other) { + return false; + } }; class ParcelableSpecifier extends NonParcelableSpecifier implements Parcelable { @Override public int describeContents() { return 0; } From f4667b4925ffefe55a5f59b759f4705e57152ae4 Mon Sep 17 00:00:00 2001 From: Hall Liu Date: Thu, 26 Mar 2020 19:09:30 -0700 Subject: [PATCH 132/229] Add gating, logging for PhoneStateListener's limit Add gating via PlatformCompat and DeviceConfig and logging via PlatformCompat to the limit instituted on per-process listeners Fixes: 152074216 Test: atest CtsTelephonyHostCases Change-Id: I4d6681d90705b68c3349f4124e434a29b50fd3a2 --- tests/net/java/com/android/server/ConnectivityServiceTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 6985415a6a..3904b6f8b5 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -205,6 +205,7 @@ import android.os.UserManager; import android.provider.Settings; import android.security.KeyStore; import android.system.Os; +import android.telephony.TelephonyManager; import android.test.mock.MockContentResolver; import android.text.TextUtils; import android.util.ArraySet; @@ -345,6 +346,7 @@ public class ConnectivityServiceTest { @Mock IBinder mIBinder; @Mock LocationManager mLocationManager; @Mock AppOpsManager mAppOpsManager; + @Mock TelephonyManager mTelephonyManager; private ArgumentCaptor mResolverParamsParcelCaptor = ArgumentCaptor.forClass(ResolverParamsParcel.class); @@ -432,6 +434,7 @@ public class ConnectivityServiceTest { if (Context.ALARM_SERVICE.equals(name)) return mAlarmManager; if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager; if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager; + if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager; return super.getSystemService(name); } From 9904c69fa57ffaf4b557b2d0e6bb30d3db76459f Mon Sep 17 00:00:00 2001 From: Mark Chien Date: Fri, 27 Mar 2020 16:53:45 +0000 Subject: [PATCH 133/229] Unbreak testStartUsingNetworkFeature_enableHipri failure aosp/1261619 break legacy API that only supported for SDK which is smaller than android M, caller need to have network stack permission to request network with legacy type. Fix failure by whitelist permission check for the caller who built with order SDK(< M). Bug: 152229492 Test: atest CtsTetheringTest atest ConnectivityManagerLegacyTest# \ testStartUsingNetworkFeature_enableHipri Change-Id: I02504c0eed10ee4e08c8fbf032951022255ba5fa Merged-In: I367dff0429f26f266282300edc38637b55eece38 (cherry picked from commit b1c8acf0d6ba1fe35d8e81673d2c5c24fa2fea79) --- .../com/android/server/ConnectivityService.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 237a961fd3..5d350be5b0 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -63,6 +63,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.database.ContentObserver; import android.net.CaptivePortal; @@ -5405,12 +5406,25 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) { + final PackageManager pm = mContext.getPackageManager(); + final int userId = UserHandle.getCallingUserId(); + try { + final int callingVersion = pm.getApplicationInfoAsUser( + callingPackageName, 0 /* flags */, userId).targetSdkVersion; + if (callingVersion < version) return false; + } catch (PackageManager.NameNotFoundException e) { } + return true; + } + @Override public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities, Messenger messenger, int timeoutMs, IBinder binder, int legacyType, @NonNull String callingPackageName) { if (legacyType != TYPE_NONE && !checkNetworkStackPermission()) { - throw new SecurityException("Insufficient permissions to specify legacy type"); + if (checkUnsupportedStartingFrom(Build.VERSION_CODES.M, callingPackageName)) { + throw new SecurityException("Insufficient permissions to specify legacy type"); + } } final int callingUid = Binder.getCallingUid(); final NetworkRequest.Type type = (networkCapabilities == null) From ef40b406c5eed1783ee53b31d67717484bc8e727 Mon Sep 17 00:00:00 2001 From: Xiao Ma Date: Thu, 26 Mar 2020 01:36:53 +0000 Subject: [PATCH 134/229] Add CTS tests for ApfCapabilities static APIs. Add tests for getApfEtherTypeBlackList and getApfDrop8023Frames APIs. Bug: 150640397 Test: atest CtsNetTestCasesLatestSdk:android.net.apf.ApfCapabilitiesTest on both of Q and R devices. Change-Id: I11555934df4b27cbb6b7ddbb81022d8fb7c25e15 Merged-In: I11555934df4b27cbb6b7ddbb81022d8fb7c25e15 (cherry picked from commit 7d51a72487dba5b2747a9de12f50ba2087007264) --- .../android/net/apf/ApfCapabilitiesTest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java b/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java index f4f804aff0..84805442e5 100644 --- a/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java +++ b/tests/net/common/java/android/net/apf/ApfCapabilitiesTest.java @@ -21,17 +21,31 @@ import static com.android.testutils.ParcelUtilsKt.assertParcelSane; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import android.content.Context; + +import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Arrays; + @RunWith(AndroidJUnit4.class) @SmallTest public class ApfCapabilitiesTest { + private Context mContext; + + @Before + public void setUp() { + mContext = InstrumentationRegistry.getContext(); + } + @Test public void testConstructAndParcel() { final ApfCapabilities caps = new ApfCapabilities(123, 456, 789); @@ -59,4 +73,27 @@ public class ApfCapabilitiesTest { caps = new ApfCapabilities(4 /* apfVersionSupported */, 5, 6); assertTrue(caps.hasDataAccess()); } + + @Test + public void testGetApfDrop8023Frames() { + // Get com.android.internal.R.bool.config_apfDrop802_3Frames. The test cannot directly + // use R.bool.config_apfDrop802_3Frames because that is not a stable resource ID. + final int resId = mContext.getResources().getIdentifier("config_apfDrop802_3Frames", + "bool", "android"); + final boolean shouldDrop8023Frames = mContext.getResources().getBoolean(resId); + final boolean actual = ApfCapabilities.getApfDrop8023Frames(); + assertEquals(shouldDrop8023Frames, actual); + } + + @Test + public void testGetApfEtherTypeBlackList() { + // Get com.android.internal.R.array.config_apfEthTypeBlackList. The test cannot directly + // use R.array.config_apfEthTypeBlackList because that is not a stable resource ID. + final int resId = mContext.getResources().getIdentifier("config_apfEthTypeBlackList", + "array", "android"); + final int[] blacklistedEtherTypeArray = mContext.getResources().getIntArray(resId); + final int[] actual = ApfCapabilities.getApfEtherTypeBlackList(); + assertNotNull(actual); + assertTrue(Arrays.equals(blacklistedEtherTypeArray, actual)); + } } From 9f8773c32ed0791bbd8e677a5401095c53220184 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Wed, 18 Mar 2020 15:22:12 -0700 Subject: [PATCH 135/229] Clean up handling of NetworkCapabilities#administratorUids. Update ConnectivityService's check for administrator UIDs to use ArrayUtils to check for UID inclusion. Update the NetworkCapabilities annotation on the administrator UIDs field to clarify that it is NonNull. Bug: 147903575 Test: atest FrameworksNetTests Change-Id: Id630fe9d76aacdaf038fdaa5360f0327520ee0c3 Merged-In: Id630fe9d76aacdaf038fdaa5360f0327520ee0c3 (cherry picked from commit 898496365aa1f3601cdbb305004ad0de11ff6bfc) --- core/java/android/net/NetworkCapabilities.java | 2 +- .../core/java/com/android/server/ConnectivityService.java | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 91ef911ef2..4e4ff4a63a 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -920,7 +920,7 @@ public final class NetworkCapabilities implements Parcelable { * empty unless the destination is 1) the System Server, or 2) Telephony. In either case, the * receiving entity must have the ACCESS_FINE_LOCATION permission and target R+. */ - private int[] mAdministratorUids = new int[0]; + @NonNull private int[] mAdministratorUids = new int[0]; /** * Sets the int[] of UIDs that are administrators of this network. diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 5d350be5b0..d684f0c199 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -7992,11 +7992,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // Administrator UIDs also contains the Owner UID final int[] administratorUids = nai.networkCapabilities.getAdministratorUids(); - for (final int uid : administratorUids) { - if (uid == callbackUid) return true; - } - - return false; + return ArrayUtils.contains(administratorUids, callbackUid); } @Override From fe059d8c302d464f80113e2a9178e69ee5b65bc1 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Wed, 12 Feb 2020 14:50:58 -0800 Subject: [PATCH 136/229] Invoke onConnectivityReport on registering ConnectivityDiagnostics. This change updates the behavior for registering ConnectivityDiagnosticsCallbacks. Now, after a successful register() call, callbacks will receive cached ConnectivityReports for all matching, permissioned networks. This allows registrants to be updated with the network state for their networks without having to wait for the next network validation. Bug: 147849853 Test: atest FrameworksNetTests Change-Id: I924ba8fdcc847f453557021591bde38602fe089c Merged-In: I924ba8fdcc847f453557021591bde38602fe089c (cherry picked from commit 95ec0b206b759e1d26bc1dbb2255a515bb24358a) --- .../net/ConnectivityDiagnosticsManager.java | 3 +- .../android/server/ConnectivityService.java | 29 ++++++++++++++++ .../server/connectivity/NetworkAgentInfo.java | 28 +++++++++++++++ .../server/ConnectivityServiceTest.java | 34 +++++++++++++++++++ 4 files changed, 93 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java index 6f0a4f9744..aa35852f78 100644 --- a/core/java/android/net/ConnectivityDiagnosticsManager.java +++ b/core/java/android/net/ConnectivityDiagnosticsManager.java @@ -659,7 +659,8 @@ public class ConnectivityDiagnosticsManager { public abstract static class ConnectivityDiagnosticsCallback { /** * Called when the platform completes a data connectivity check. This will also be invoked - * upon registration with the latest report. + * immediately upon registration with the latest report, if a report has already been + * generated for this network. * *

    The Network specified in the ConnectivityReport may not be active any more when this * method is invoked. diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index d684f0c199..2b5f21a172 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -7855,6 +7855,34 @@ public class ConnectivityService extends IConnectivityManager.Stub cb.asBinder().linkToDeath(cbInfo, 0); } catch (RemoteException e) { cbInfo.binderDied(); + return; + } + + // Once registered, provide ConnectivityReports for matching Networks + final List matchingNetworks = new ArrayList<>(); + synchronized (mNetworkForNetId) { + for (int i = 0; i < mNetworkForNetId.size(); i++) { + final NetworkAgentInfo nai = mNetworkForNetId.valueAt(i); + if (nai.satisfies(nri.request)) { + matchingNetworks.add(nai); + } + } + } + for (final NetworkAgentInfo nai : matchingNetworks) { + final ConnectivityReport report = nai.getConnectivityReport(); + if (report == null) { + continue; + } + if (!checkConnectivityDiagnosticsPermissions( + nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) { + continue; + } + + try { + cb.onConnectivityReportAvailable(report); + } catch (RemoteException e) { + // Exception while sending the ConnectivityReport. Move on to the next network. + } } } @@ -7890,6 +7918,7 @@ public class ConnectivityService extends IConnectivityManager.Stub nai.linkProperties, networkCapabilities, extras); + nai.setConnectivityReport(report); final List results = getMatchingPermissionedCallbacks(nai); for (final IConnectivityDiagnosticsCallback cb : results) { diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 2f047157d4..d2086138a1 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -16,6 +16,7 @@ package com.android.server.connectivity; +import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import static android.net.NetworkCapabilities.transportNamesOf; import android.annotation.NonNull; @@ -243,6 +244,9 @@ public class NetworkAgentInfo implements Comparable { // How many of the satisfied requests are of type BACKGROUND_REQUEST. private int mNumBackgroundNetworkRequests = 0; + // The last ConnectivityReport made available for this network. + private ConnectivityReport mConnectivityReport; + public final Messenger messenger; public final AsyncChannel asyncChannel; @@ -621,6 +625,30 @@ public class NetworkAgentInfo implements Comparable { for (LingerTimer timer : mLingerTimers) { pw.println(timer); } } + /** + * Sets the most recent ConnectivityReport for this network. + * + *

    This should only be called from the ConnectivityService thread. + * + * @hide + */ + public void setConnectivityReport(@NonNull ConnectivityReport connectivityReport) { + mConnectivityReport = connectivityReport; + } + + /** + * Returns the most recent ConnectivityReport for this network, or null if none have been + * reported yet. + * + *

    This should only be called from the ConnectivityService thread. + * + * @hide + */ + @Nullable + public ConnectivityReport getConnectivityReport() { + return mConnectivityReport; + } + // TODO: Print shorter members first and only print the boolean variable which value is true // to improve readability. public String toString() { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 86d8a820e4..50b61fb40f 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -317,6 +317,8 @@ public class ConnectivityServiceTest { private static final String TEST_PACKAGE_NAME = "com.android.test.package"; private static final String[] EMPTY_STRING_ARRAY = new String[0]; + private static final String INTERFACE_NAME = "interface"; + private MockContext mServiceContext; private HandlerThread mCsHandlerThread; private ConnectivityService mService; @@ -6915,6 +6917,38 @@ public class ConnectivityServiceTest { mContext.getOpPackageName())); } + @Test + public void testRegisterConnectivityDiagnosticsCallbackCallsOnConnectivityReport() + throws Exception { + // Set up the Network, which leads to a ConnectivityReport being cached for the network. + final TestNetworkCallback callback = new TestNetworkCallback(); + mCm.registerDefaultNetworkCallback(callback); + final LinkProperties linkProperties = new LinkProperties(); + linkProperties.setInterfaceName(INTERFACE_NAME); + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, linkProperties); + mCellNetworkAgent.connect(true); + callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent); + callback.assertNoCallback(); + + final NetworkRequest request = new NetworkRequest.Builder().build(); + when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); + + mServiceContext.setPermission( + android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); + + mService.registerConnectivityDiagnosticsCallback( + mConnectivityDiagnosticsCallback, request, mContext.getPackageName()); + + // Block until all other events are done processing. + HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); + + verify(mConnectivityDiagnosticsCallback) + .onConnectivityReportAvailable(argThat(report -> { + return INTERFACE_NAME.equals(report.getLinkProperties().getInterfaceName()) + && report.getNetworkCapabilities().hasTransport(TRANSPORT_CELLULAR); + })); + } + private void setUpConnectivityDiagnosticsCallback() throws Exception { final NetworkRequest request = new NetworkRequest.Builder().build(); when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder); From aebda983d39cb83ac1d8280535f3956e3d51f701 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Wed, 4 Mar 2020 13:35:20 -0800 Subject: [PATCH 137/229] Decrement networkRequestPerUid when callbacks are unregistered. ConnectivityDiagnosticsCallbacks are tied to NetworkRequestInfo objects when registered with the platform. Each NetworkRequestInfo is tied to a specific uid, and ConnectivityService enforces a limit on the number of network requests that can be associated with each uid. When ConnectivityDiagnosticsCallbacks are unregistered from the platform, their NetworkRequestInfo is freed and the number of network requests per the user's uid should be decremented. Bug: 150802582 Test: atest android.net.cts.ConnectivityDiagnosticsManagerTest Change-Id: Ia5ed39c1d8e6221cd402be4f8baf69fa643a6113 Merged-In: Ia5ed39c1d8e6221cd402be4f8baf69fa643a6113 (cherry picked from commit 662076b1a7c0f064fa746fc7b8d3204c966c8e48) --- .../core/java/com/android/server/ConnectivityService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2b5f21a172..63f7cb3b7d 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -7902,6 +7902,11 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } + // Decrement the reference count for this NetworkRequestInfo. The reference count is + // incremented when the NetworkRequestInfo is created as part of + // enforceRequestCountLimit(). + decrementNetworkRequestPerUidCount(nri); + cb.asBinder().unlinkToDeath(mConnectivityDiagnosticsCallbacks.remove(cb), 0); } From b65e18e638fdd14ad1a2cfa88fa8ea3c8e22434f Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Thu, 5 Mar 2020 10:46:02 -0800 Subject: [PATCH 138/229] Use IBinder as key for ConnectivityDiagnostics storage in CS. This change updates ConnectivityService to use IBinder instances as keys when storing ConnectivityDiagnosticsCallbacks. When storing ConnectivityDiagnosticsCallbacks in ConnectivityService, the IConnectivityDiagnsoticsCallback is used as the key for ConnectivityService.mConnectivityDiagnosticsCallbacks. However, IConnectivityDiagnosticsCallback instances are received as different objects. This causes them to produce different hashCode() values, so attempts to remove an IConnectivityDiagnosticsCallback fail. Bug: 150867635 Test: atest FrameworksNetTests Change-Id: Ib99e68d5ae47fa27e12428f9a60a2c1204ac59a2 Merged-In: Ib99e68d5ae47fa27e12428f9a60a2c1204ac59a2 (cherry picked from commit c7c6a4ac12beb7c216076958612869426da06da0) --- .../android/server/ConnectivityService.java | 24 +++++++++++-------- .../server/ConnectivityServiceTest.java | 16 ++++--------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 63f7cb3b7d..e3f574f366 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -653,8 +653,8 @@ public class ConnectivityService extends IConnectivityManager.Stub final MultipathPolicyTracker mMultipathPolicyTracker; @VisibleForTesting - final Map - mConnectivityDiagnosticsCallbacks = new HashMap<>(); + final Map mConnectivityDiagnosticsCallbacks = + new HashMap<>(); /** * Implements support for the legacy "one network per network type" model. @@ -7835,11 +7835,12 @@ public class ConnectivityService extends IConnectivityManager.Stub ensureRunningOnConnectivityServiceThread(); final IConnectivityDiagnosticsCallback cb = cbInfo.mCb; + final IBinder iCb = cb.asBinder(); final NetworkRequestInfo nri = cbInfo.mRequestInfo; // This means that the client registered the same callback multiple times. Do // not override the previous entry, and exit silently. - if (mConnectivityDiagnosticsCallbacks.containsKey(cb)) { + if (mConnectivityDiagnosticsCallbacks.containsKey(iCb)) { if (VDBG) log("Diagnostics callback is already registered"); // Decrement the reference count for this NetworkRequestInfo. The reference count is @@ -7849,10 +7850,10 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } - mConnectivityDiagnosticsCallbacks.put(cb, cbInfo); + mConnectivityDiagnosticsCallbacks.put(iCb, cbInfo); try { - cb.asBinder().linkToDeath(cbInfo, 0); + iCb.linkToDeath(cbInfo, 0); } catch (RemoteException e) { cbInfo.binderDied(); return; @@ -7889,13 +7890,14 @@ public class ConnectivityService extends IConnectivityManager.Stub private void handleUnregisterConnectivityDiagnosticsCallback( @NonNull IConnectivityDiagnosticsCallback cb, int uid) { ensureRunningOnConnectivityServiceThread(); + final IBinder iCb = cb.asBinder(); - if (!mConnectivityDiagnosticsCallbacks.containsKey(cb)) { + if (!mConnectivityDiagnosticsCallbacks.containsKey(iCb)) { if (VDBG) log("Removing diagnostics callback that is not currently registered"); return; } - final NetworkRequestInfo nri = mConnectivityDiagnosticsCallbacks.get(cb).mRequestInfo; + final NetworkRequestInfo nri = mConnectivityDiagnosticsCallbacks.get(iCb).mRequestInfo; if (uid != nri.mUid) { if (VDBG) loge("Different uid than registrant attempting to unregister cb"); @@ -7907,7 +7909,9 @@ public class ConnectivityService extends IConnectivityManager.Stub // enforceRequestCountLimit(). decrementNetworkRequestPerUidCount(nri); - cb.asBinder().unlinkToDeath(mConnectivityDiagnosticsCallbacks.remove(cb), 0); + final ConnectivityDiagnosticsCallbackInfo cbInfo = + mConnectivityDiagnosticsCallbacks.remove(iCb); + iCb.unlinkToDeath(cbInfo, 0); } private void handleNetworkTestedWithExtras( @@ -7982,14 +7986,14 @@ public class ConnectivityService extends IConnectivityManager.Stub private List getMatchingPermissionedCallbacks( @NonNull NetworkAgentInfo nai) { final List results = new ArrayList<>(); - for (Entry entry : + for (Entry entry : mConnectivityDiagnosticsCallbacks.entrySet()) { final ConnectivityDiagnosticsCallbackInfo cbInfo = entry.getValue(); final NetworkRequestInfo nri = cbInfo.mRequestInfo; if (nai.satisfies(nri.request)) { if (checkConnectivityDiagnosticsPermissions( nri.mPid, nri.mUid, nai, cbInfo.mCallingPackageName)) { - results.add(entry.getKey()); + results.add(entry.getValue().mCb); } } } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 50b61fb40f..b02398d1f1 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6750,16 +6750,12 @@ public class ConnectivityServiceTest { verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt()); verify(mConnectivityDiagnosticsCallback).asBinder(); - assertTrue( - mService.mConnectivityDiagnosticsCallbacks.containsKey( - mConnectivityDiagnosticsCallback)); + assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder)); mService.unregisterConnectivityDiagnosticsCallback(mConnectivityDiagnosticsCallback); verify(mIBinder, timeout(TIMEOUT_MS)) .unlinkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt()); - assertFalse( - mService.mConnectivityDiagnosticsCallbacks.containsKey( - mConnectivityDiagnosticsCallback)); + assertFalse(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder)); verify(mConnectivityDiagnosticsCallback, atLeastOnce()).asBinder(); } @@ -6777,9 +6773,7 @@ public class ConnectivityServiceTest { verify(mIBinder).linkToDeath(any(ConnectivityDiagnosticsCallbackInfo.class), anyInt()); verify(mConnectivityDiagnosticsCallback).asBinder(); - assertTrue( - mService.mConnectivityDiagnosticsCallbacks.containsKey( - mConnectivityDiagnosticsCallback)); + assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder)); // Register the same callback again mService.registerConnectivityDiagnosticsCallback( @@ -6788,9 +6782,7 @@ public class ConnectivityServiceTest { // Block until all other events are done processing. HandlerUtilsKt.waitForIdle(mCsHandlerThread, TIMEOUT_MS); - assertTrue( - mService.mConnectivityDiagnosticsCallbacks.containsKey( - mConnectivityDiagnosticsCallback)); + assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder)); } @Test From 0d667c5508e2c54f6dc2d575c5653de08703c0a7 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 6 Feb 2020 18:31:19 +0900 Subject: [PATCH 139/229] Add combine() and equals() for NetworkCapabilities admin UIDs. NetworkCapabilities#mAdministratorUids should be checked for equality when combining NetworkCapabilities. Administrator UIDs should also be included in NetworkCapabilities equals() and hashCode(). Bug: 147903575 Test: FrameworksNetTests Change-Id: I803bdec80e27ee80d3a39844c5fb7aed584ab07d Merged-In: I803bdec80e27ee80d3a39844c5fb7aed584ab07d (cherry picked from commit 5fad8aa761336012bb228afc3b6f7d42fa274242) --- .../java/android/net/NetworkCapabilities.java | 65 +++++++++++++++++-- .../android/net/NetworkCapabilitiesTest.java | 21 ++++++ 2 files changed, 79 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 4e4ff4a63a..18bbb07da4 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -16,6 +16,8 @@ package android.net; +import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; + import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -118,7 +120,7 @@ public final class NetworkCapabilities implements Parcelable { mTransportInfo = nc.mTransportInfo; mSignalStrength = nc.mSignalStrength; setUids(nc.mUids); // Will make the defensive copy - setAdministratorUids(nc.mAdministratorUids); + setAdministratorUids(nc.getAdministratorUids()); mOwnerUid = nc.mOwnerUid; mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities; mSSID = nc.mSSID; @@ -919,6 +921,9 @@ public final class NetworkCapabilities implements Parcelable { *

    For NetworkCapability instances being sent from the System Server, this value MUST be * empty unless the destination is 1) the System Server, or 2) Telephony. In either case, the * receiving entity must have the ACCESS_FINE_LOCATION permission and target R+. + * + *

    When received from an app in a NetworkRequest this is always cleared out by the system + * server. This field is never used for matching NetworkRequests to NetworkAgents. */ @NonNull private int[] mAdministratorUids = new int[0]; @@ -927,10 +932,11 @@ public final class NetworkCapabilities implements Parcelable { * *

    UIDs included in administratorUids gain administrator privileges over this Network. * Examples of UIDs that should be included in administratorUids are: + * *

      - *
    • Carrier apps with privileges for the relevant subscription - *
    • Active VPN apps - *
    • Other application groups with a particular Network-related role + *
    • Carrier apps with privileges for the relevant subscription + *
    • Active VPN apps + *
    • Other application groups with a particular Network-related role *
    * *

    In general, user-supplied networks (such as WiFi networks) do not have an administrator. @@ -938,7 +944,10 @@ public final class NetworkCapabilities implements Parcelable { *

    An app is granted owner privileges over Networks that it supplies. The owner UID MUST * always be included in administratorUids. * + *

    The administrator UIDs are set by network agents. + * * @param administratorUids the UIDs to be set as administrators of this Network. + * @see #mAdministratorUids * @hide */ @NonNull @@ -950,7 +959,12 @@ public final class NetworkCapabilities implements Parcelable { /** * Retrieves the UIDs that are administrators of this Network. * + *

    This is only populated in NetworkCapabilities objects that come from network agents for + * networks that are managed by specific apps on the system, such as carrier privileged apps or + * wifi suggestion apps. This will include the network owner. + * * @return the int[] of UIDs that are administrators of this Network + * @see #mAdministratorUids * @hide */ @NonNull @@ -960,6 +974,40 @@ public final class NetworkCapabilities implements Parcelable { return Arrays.copyOf(mAdministratorUids, mAdministratorUids.length); } + /** + * Tests if the set of administrator UIDs of this network is the same as that of the passed one. + * + *

    The administrator UIDs must be in sorted order. + * + *

    nc is assumed non-null. Else, NPE. + * + * @hide + */ + @VisibleForTesting(visibility = PRIVATE) + public boolean equalsAdministratorUids(@NonNull final NetworkCapabilities nc) { + return Arrays.equals(mAdministratorUids, nc.mAdministratorUids); + } + + /** + * Combine the administrator UIDs of the capabilities. + * + *

    This is only legal if either of the administrators lists are empty, or if they are equal. + * Combining administrator UIDs is only possible for combining non-overlapping sets of UIDs. + * + *

    If both administrator lists are non-empty but not equal, they conflict with each other. In + * this case, it would not make sense to add them together. + */ + private void combineAdministratorUids(@NonNull final NetworkCapabilities nc) { + if (nc.mAdministratorUids.length == 0) return; + if (mAdministratorUids.length == 0) { + mAdministratorUids = Arrays.copyOf(nc.mAdministratorUids, nc.mAdministratorUids.length); + return; + } + if (!equalsAdministratorUids(nc)) { + throw new IllegalStateException("Can't combine two different administrator UID lists"); + } + } + /** * Value indicating that link bandwidth is unspecified. * @hide @@ -1455,6 +1503,7 @@ public final class NetworkCapabilities implements Parcelable { combineUids(nc); combineSSIDs(nc); combineRequestor(nc); + combineAdministratorUids(nc); } /** @@ -1568,7 +1617,8 @@ public final class NetworkCapabilities implements Parcelable { && equalsUids(that) && equalsSSID(that) && equalsPrivateDnsBroken(that) - && equalsRequestor(that); + && equalsRequestor(that) + && equalsAdministratorUids(that); } @Override @@ -1588,7 +1638,8 @@ public final class NetworkCapabilities implements Parcelable { + Objects.hashCode(mTransportInfo) * 41 + Objects.hashCode(mPrivateDnsBroken) * 43 + Objects.hashCode(mRequestorUid) * 47 - + Objects.hashCode(mRequestorPackageName) * 53; + + Objects.hashCode(mRequestorPackageName) * 53 + + Arrays.hashCode(mAdministratorUids) * 59; } @Override @@ -1609,7 +1660,7 @@ public final class NetworkCapabilities implements Parcelable { dest.writeArraySet(mUids); dest.writeString(mSSID); dest.writeBoolean(mPrivateDnsBroken); - dest.writeIntArray(mAdministratorUids); + dest.writeIntArray(getAdministratorUids()); dest.writeInt(mOwnerUid); dest.writeInt(mRequestorUid); dest.writeString(mRequestorPackageName); diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index 916c339811..db3372de16 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -58,6 +58,7 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.Arrays; import java.util.Set; @RunWith(AndroidJUnit4.class) @@ -280,6 +281,7 @@ public class NetworkCapabilitiesTest { .addCapability(NET_CAPABILITY_NOT_METERED); if (isAtLeastR()) { netCap.setOwnerUid(123); + netCap.setAdministratorUids(new int[] {5, 11}); } assertParcelingIsLossless(netCap); netCap.setSSID(TEST_SSID); @@ -491,6 +493,25 @@ public class NetworkCapabilitiesTest { assertFalse(nc2.appliesToUid(12)); assertTrue(nc1.appliesToUid(22)); assertTrue(nc2.appliesToUid(22)); + + final int[] adminUids = {3, 6, 12}; + nc1.setAdministratorUids(adminUids); + nc2.combineCapabilities(nc1); + assertTrue(nc2.equalsAdministratorUids(nc1)); + assertArrayEquals(nc2.getAdministratorUids(), adminUids); + + final int[] adminUidsOtherOrder = {3, 12, 6}; + nc1.setAdministratorUids(adminUids); + assertTrue(nc2.equalsAdministratorUids(nc1)); + + final int[] adminUids2 = {11, 1, 12, 3, 6}; + nc1.setAdministratorUids(adminUids2); + assertFalse(nc2.equalsAdministratorUids(nc1)); + assertFalse(Arrays.equals(nc2.getAdministratorUids(), adminUids2)); + try { + nc2.combineCapabilities(nc1); + fail("Shouldn't be able to combine different lists of admin UIDs"); + } catch (IllegalStateException expected) { } } @Test From 9c341963ac91b861f407ffec7a73e180de845bad Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Tue, 24 Mar 2020 11:53:30 -0700 Subject: [PATCH 140/229] Sort administrator UIDs for NetworkCapabilities. Administrator UIDs stored in NetworkCapabilities should be sorted. This allows for easier equals checks and hashCode computation. Additionally, duplicate UIDs should be prevented. Bug: 147903575 Test: atest FrameworksNetTests Change-Id: Ia5387ca2ce7c3fcbd04dc7fbff5266f7bcc71694 Merged-In: Ia5387ca2ce7c3fcbd04dc7fbff5266f7bcc71694 (cherry picked from commit 2091bd9059d1d24f8c6bd1cd345361f185cab1ea) --- core/java/android/net/NetworkCapabilities.java | 7 +++++++ .../android/net/NetworkCapabilitiesTest.java | 17 +++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 18bbb07da4..9ff7ebee6d 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -947,12 +947,19 @@ public final class NetworkCapabilities implements Parcelable { *

    The administrator UIDs are set by network agents. * * @param administratorUids the UIDs to be set as administrators of this Network. + * @throws IllegalArgumentException if duplicate UIDs are contained in administratorUids * @see #mAdministratorUids * @hide */ @NonNull public NetworkCapabilities setAdministratorUids(@NonNull final int[] administratorUids) { mAdministratorUids = Arrays.copyOf(administratorUids, administratorUids.length); + Arrays.sort(mAdministratorUids); + for (int i = 0; i < mAdministratorUids.length - 1; i++) { + if (mAdministratorUids[i] >= mAdministratorUids[i + 1]) { + throw new IllegalArgumentException("All administrator UIDs must be unique"); + } + } return this; } diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index db3372de16..316a83adf4 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -441,6 +441,23 @@ public class NetworkCapabilitiesTest { return range; } + @Test + public void testSetAdministratorUids() { + NetworkCapabilities nc = + new NetworkCapabilities().setAdministratorUids(new int[] {2, 1, 3}); + + assertArrayEquals(new int[] {1, 2, 3}, nc.getAdministratorUids()); + } + + @Test + public void testSetAdministratorUidsWithDuplicates() { + try { + new NetworkCapabilities().setAdministratorUids(new int[] {1, 1}); + fail("Expected IllegalArgumentException for duplicate uids"); + } catch (IllegalArgumentException expected) { + } + } + @Test public void testCombineCapabilities() { NetworkCapabilities nc1 = new NetworkCapabilities(); From 7d4ef210105e8068ee0e669b78aba4245eaef845 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Mon, 30 Mar 2020 12:03:21 -0700 Subject: [PATCH 141/229] Clarify comments for Connectivity Diagnostics reports. Clarify when ConnectivityDiagnosticsCallback#onConnectivityReportAvailable will be invoked. Clarify when NetworkAgentInfo#mConnectivityReport will be null vs non-null. Bug: 147849853 Test: atest FrameworksNetTests Change-Id: I748bd9ded72a34d89f13bd4362d6d4da62b910b8 Merged-In: I748bd9ded72a34d89f13bd4362d6d4da62b910b8 (cherry picked from commit 604dd40cf077f42c2d4b6ff80ff41d89cfbcacee) --- core/java/android/net/ConnectivityDiagnosticsManager.java | 4 ++-- .../com/android/server/connectivity/NetworkAgentInfo.java | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java index aa35852f78..9086d49231 100644 --- a/core/java/android/net/ConnectivityDiagnosticsManager.java +++ b/core/java/android/net/ConnectivityDiagnosticsManager.java @@ -659,8 +659,8 @@ public class ConnectivityDiagnosticsManager { public abstract static class ConnectivityDiagnosticsCallback { /** * Called when the platform completes a data connectivity check. This will also be invoked - * immediately upon registration with the latest report, if a report has already been - * generated for this network. + * immediately upon registration for each network matching the request with the latest + * report, if a report has already been generated for that network. * *

    The Network specified in the ConnectivityReport may not be active any more when this * method is invoked. diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index d2086138a1..15628f03ba 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -244,8 +244,9 @@ public class NetworkAgentInfo implements Comparable { // How many of the satisfied requests are of type BACKGROUND_REQUEST. private int mNumBackgroundNetworkRequests = 0; - // The last ConnectivityReport made available for this network. - private ConnectivityReport mConnectivityReport; + // The last ConnectivityReport made available for this network. This value is only null before a + // report is generated. Once non-null, it will never be null again. + @Nullable private ConnectivityReport mConnectivityReport; public final Messenger messenger; public final AsyncChannel asyncChannel; From 5d51a917f533614e2065495ba9ec59315078491c Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Mon, 30 Mar 2020 12:43:49 -0700 Subject: [PATCH 142/229] Simplify unregister logic for Connectivity Diagnostics callbacks. ConnectivityService is updated to simplify the logic for unregistering ConnectivityDiagnosticsCallback instances. This change removes the given callback from ConnectivityService's data structure. If the callback was not registered with ConnectivityService, it is logged and the function exits; else, the unregister() operation continues. Bug: 150867635 Test: atest FrameworksNetTests Change-Id: I9096969a1bf33da72b117f5bbc88257df805e688 Merged-In: I9096969a1bf33da72b117f5bbc88257df805e688 (cherry picked from commit f047313940b5af49a3b0e72a5f2d94fc1dda9c9d) --- .../core/java/com/android/server/ConnectivityService.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index e3f574f366..2e5a844c88 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -7892,12 +7892,14 @@ public class ConnectivityService extends IConnectivityManager.Stub ensureRunningOnConnectivityServiceThread(); final IBinder iCb = cb.asBinder(); - if (!mConnectivityDiagnosticsCallbacks.containsKey(iCb)) { + final ConnectivityDiagnosticsCallbackInfo cbInfo = + mConnectivityDiagnosticsCallbacks.remove(iCb); + if (cbInfo == null) { if (VDBG) log("Removing diagnostics callback that is not currently registered"); return; } - final NetworkRequestInfo nri = mConnectivityDiagnosticsCallbacks.get(iCb).mRequestInfo; + final NetworkRequestInfo nri = cbInfo.mRequestInfo; if (uid != nri.mUid) { if (VDBG) loge("Different uid than registrant attempting to unregister cb"); @@ -7909,8 +7911,6 @@ public class ConnectivityService extends IConnectivityManager.Stub // enforceRequestCountLimit(). decrementNetworkRequestPerUidCount(nri); - final ConnectivityDiagnosticsCallbackInfo cbInfo = - mConnectivityDiagnosticsCallbacks.remove(iCb); iCb.unlinkToDeath(cbInfo, 0); } From 85308a5a14e84ed78e2ef9b843f33fbe956c4961 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Thu, 5 Mar 2020 22:13:31 -0800 Subject: [PATCH 143/229] Update CS helper for clearing NetworkCapabilities UIDs. NetworkCapabilities needs to have its UIDs cleared (UID ranges, owner UID, and administrator UIDs) before it can be shared with apps via ConnectivityDiagnosticsCallback invocations. The previous helper used for clearing these values mutated the provided NetworkCapabilities. This is updated to instead return a sanitized copy of the provided NetworkCapabilities Bug: 148942124 Test: atest FrameworksNetTests Change-Id: I2431a6d273d0d73432919baf41b4f66397f4b7dc Merged-In: I2431a6d273d0d73432919baf41b4f66397f4b7dc (cherry picked from commit 45bbc4f6ac910a2ea87eb6b2197e34db50d3ada8) --- .../com/android/server/ConnectivityService.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2e5a844c88..4ab035e7f4 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -7918,8 +7918,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @NonNull ConnectivityReportEvent reportEvent, @NonNull PersistableBundle extras) { final NetworkAgentInfo nai = reportEvent.mNai; final NetworkCapabilities networkCapabilities = - new NetworkCapabilities(nai.networkCapabilities); - clearNetworkCapabilitiesUids(networkCapabilities); + getNetworkCapabilitiesWithoutUids(nai.networkCapabilities); final ConnectivityReport report = new ConnectivityReport( reportEvent.mNai.network, @@ -7943,8 +7942,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @NonNull NetworkAgentInfo nai, long timestampMillis, int detectionMethod, @NonNull PersistableBundle extras) { final NetworkCapabilities networkCapabilities = - new NetworkCapabilities(nai.networkCapabilities); - clearNetworkCapabilitiesUids(networkCapabilities); + getNetworkCapabilitiesWithoutUids(nai.networkCapabilities); final DataStallReport report = new DataStallReport( nai.network, @@ -7977,10 +7975,12 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void clearNetworkCapabilitiesUids(@NonNull NetworkCapabilities nc) { - nc.setUids(null); - nc.setAdministratorUids(new int[0]); - nc.setOwnerUid(Process.INVALID_UID); + private NetworkCapabilities getNetworkCapabilitiesWithoutUids(@NonNull NetworkCapabilities nc) { + final NetworkCapabilities sanitized = new NetworkCapabilities(nc); + sanitized.setUids(null); + sanitized.setAdministratorUids(new int[0]); + sanitized.setOwnerUid(Process.INVALID_UID); + return sanitized; } private List getMatchingPermissionedCallbacks( From cbb19fcba731f9bffc5da3798382ac76ec43ad4a Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 26 Mar 2020 21:21:03 -0700 Subject: [PATCH 144/229] Make VpnProfile.maxMtu default value match Ikev2VpnProfile This change corrects the VpnProfile's maxMtu defaults to match that of the Ikev2VpnProfile. 1400 is too high as a default, and Settings will run into an issue here quite often. Bug: 152573931 Test: FrameworksNetTests passing Change-Id: I97ba5903b3cc1ed6a21c706ed3d78bd8ecbeee0c Merged-In: I97ba5903b3cc1ed6a21c706ed3d78bd8ecbeee0c (cherry picked from commit d0a44f49df01a1aefa505ee90c9806dee135b4e4) --- tests/net/java/com/android/internal/net/VpnProfileTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/net/java/com/android/internal/net/VpnProfileTest.java b/tests/net/java/com/android/internal/net/VpnProfileTest.java index 8a4b53343c..ceca6f0288 100644 --- a/tests/net/java/com/android/internal/net/VpnProfileTest.java +++ b/tests/net/java/com/android/internal/net/VpnProfileTest.java @@ -65,7 +65,7 @@ public class VpnProfileTest { assertTrue(p.getAllowedAlgorithms() != null && p.getAllowedAlgorithms().isEmpty()); assertFalse(p.isBypassable); assertFalse(p.isMetered); - assertEquals(1400, p.maxMtu); + assertEquals(1360, p.maxMtu); assertFalse(p.areAuthParamsInline); } From f7d30445c7d924688b21adf7dd57456810450252 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Mon, 30 Mar 2020 09:12:37 +0000 Subject: [PATCH 145/229] Update constructor of NetworkMonitor Remove redundant parameter. Bug: 152374582 Test: m -j40 ; atest FrameworksNetIntegrationTests Merged-In: I3a636f0ea5145ac4435e06a9827bb8e01862542d Change-Id: I3a636f0ea5145ac4435e06a9827bb8e01862542d --- .../server/net/integrationtests/TestNetworkStackService.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt index 23caf49529..eec3cdbe8d 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt @@ -24,7 +24,6 @@ import android.net.Network import android.net.metrics.IpConnectivityLog import android.net.util.SharedLog import android.os.IBinder -import com.android.networkstack.metrics.DataStallStatsUtils import com.android.networkstack.netlink.TcpSocketTracker import com.android.server.NetworkStackService import com.android.server.NetworkStackService.NetworkMonitorConnector @@ -91,7 +90,6 @@ class TestNetworkStackService : Service() { mock(IpConnectivityLog::class.java), mock(SharedLog::class.java), mock(NetworkStackService.NetworkStackServiceManager::class.java), NetworkMonitorDeps(privateDnsBypassNetwork), - mock(DataStallStatsUtils::class.java), mock(TcpSocketTracker::class.java)) cb.onNetworkMonitorCreated(NetworkMonitorConnector(nm, TestPermissionChecker())) } From d5c455815d610ed8e32ee6fa1cc47f21639b081f Mon Sep 17 00:00:00 2001 From: Lucas Lin Date: Tue, 31 Mar 2020 18:31:33 +0000 Subject: [PATCH 146/229] Add more tests in LinkPropertiesTests.java Test getAllInterfaceNames(), hasIpv4DefaultRoute(), hasIpv4DnsServer() and hasIpv6DnsServer(). Bug: 139268426 Bug: 135998869 Bug: 138306002 Test: atest CtsNetTestCasesLatestSdk:android.net.LinkPropertiesTest Change-Id: I2bae76dc93e7aa02efe25dca4b6e99692c79135a Merged-In: Ie77dd7eb5c7ecc763c661e8510f9a308e695e77f (cherry picked from commit 30a56a5c719c38894b3dfe803d1b58db26cc1c95) --- .../java/android/net/LinkPropertiesTest.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java index 2b5720a47e..b4f0daa025 100644 --- a/tests/net/common/java/android/net/LinkPropertiesTest.java +++ b/tests/net/common/java/android/net/LinkPropertiesTest.java @@ -480,6 +480,8 @@ public class LinkPropertiesTest { assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(1, rmnet0.getAllAddresses().size()); assertEquals(1, rmnet0.getAllLinkAddresses().size()); + assertEquals(1, rmnet0.getAllInterfaceNames().size()); + assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); rmnet0.addStackedLink(clat4); assertEquals(1, rmnet0.getStackedLinks().size()); @@ -487,6 +489,9 @@ public class LinkPropertiesTest { assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(2, rmnet0.getAllAddresses().size()); assertEquals(2, rmnet0.getAllLinkAddresses().size()); + assertEquals(2, rmnet0.getAllInterfaceNames().size()); + assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); + assertEquals("clat4", rmnet0.getAllInterfaceNames().get(1)); rmnet0.addStackedLink(clat4); assertEquals(1, rmnet0.getStackedLinks().size()); @@ -494,6 +499,9 @@ public class LinkPropertiesTest { assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(2, rmnet0.getAllAddresses().size()); assertEquals(2, rmnet0.getAllLinkAddresses().size()); + assertEquals(2, rmnet0.getAllInterfaceNames().size()); + assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); + assertEquals("clat4", rmnet0.getAllInterfaceNames().get(1)); assertEquals(0, clat4.getStackedLinks().size()); @@ -513,6 +521,8 @@ public class LinkPropertiesTest { assertEquals(1, rmnet0.getLinkAddresses().size()); assertEquals(1, rmnet0.getAllAddresses().size()); assertEquals(1, rmnet0.getAllLinkAddresses().size()); + assertEquals(1, rmnet0.getAllInterfaceNames().size()); + assertEquals("rmnet0", rmnet0.getAllInterfaceNames().get(0)); assertFalse(rmnet0.removeStackedLink("clat4")); } @@ -1197,4 +1207,48 @@ public class LinkPropertiesTest { lp.clear(); assertNull(lp.getCaptivePortalData()); } + + private LinkProperties makeIpv4LinkProperties() { + final LinkProperties linkProperties = new LinkProperties(); + linkProperties.setInterfaceName(NAME); + linkProperties.addLinkAddress(LINKADDRV4); + linkProperties.addDnsServer(DNS1); + linkProperties.addRoute(new RouteInfo(GATEWAY1)); + linkProperties.addRoute(new RouteInfo(GATEWAY2)); + return linkProperties; + } + + private LinkProperties makeIpv6LinkProperties() { + final LinkProperties linkProperties = new LinkProperties(); + linkProperties.setInterfaceName(NAME); + linkProperties.addLinkAddress(LINKADDRV6); + linkProperties.addDnsServer(DNS6); + linkProperties.addRoute(new RouteInfo(GATEWAY61)); + linkProperties.addRoute(new RouteInfo(GATEWAY62)); + return linkProperties; + } + + @Test + public void testHasIpv4DefaultRoute() { + final LinkProperties Ipv4 = makeIpv4LinkProperties(); + assertTrue(Ipv4.hasIpv4DefaultRoute()); + final LinkProperties Ipv6 = makeIpv6LinkProperties(); + assertFalse(Ipv6.hasIpv4DefaultRoute()); + } + + @Test + public void testHasIpv4DnsServer() { + final LinkProperties Ipv4 = makeIpv4LinkProperties(); + assertTrue(Ipv4.hasIpv4DnsServer()); + final LinkProperties Ipv6 = makeIpv6LinkProperties(); + assertFalse(Ipv6.hasIpv4DnsServer()); + } + + @Test + public void testHasIpv6DnsServer() { + final LinkProperties Ipv4 = makeIpv4LinkProperties(); + assertFalse(Ipv4.hasIpv6DnsServer()); + final LinkProperties Ipv6 = makeIpv6LinkProperties(); + assertTrue(Ipv6.hasIpv6DnsServer()); + } } From 6602482f2682c5149f2e519f4cdf71dc31893583 Mon Sep 17 00:00:00 2001 From: Lucas Lin Date: Tue, 31 Mar 2020 18:35:12 +0000 Subject: [PATCH 147/229] Add MatchAllNetworkSpecifierTest Bug: 139268426 Bug: 135998869 Test: atest CtsNetTestCasesLatestSdk:MatchAllNetworkSpecifierTest Change-Id: I6c6911041aff1b245e576109a879247cc256093b Merged-In: Ib593708d5621ff20e6a0c31e5698b2b658f64d45 (cherry picked from commit f46c71b420f4089e0f36a296ed5b59398794f538) --- .../net/MatchAllNetworkSpecifierTest.kt | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt diff --git a/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt b/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt new file mode 100644 index 0000000000..ef15b668e2 --- /dev/null +++ b/tests/net/common/java/android/net/MatchAllNetworkSpecifierTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 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.net.wifi.aware.DiscoverySession +import android.net.wifi.aware.PeerHandle +import android.net.wifi.aware.WifiAwareNetworkSpecifier +import androidx.test.filters.SmallTest +import androidx.test.runner.AndroidJUnit4 + +import com.android.testutils.assertParcelSane + +import java.lang.IllegalStateException + +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito + +@RunWith(AndroidJUnit4::class) +@SmallTest +class MatchAllNetworkSpecifierTest { + @Test + fun testParcel() { + assertParcelSane(MatchAllNetworkSpecifier(), 0) + } + + @Test(expected = IllegalStateException::class) + fun testSatisfiedBy() { + val specifier = MatchAllNetworkSpecifier() + val discoverySession = Mockito.mock(DiscoverySession::class.java) + val peerHandle = Mockito.mock(PeerHandle::class.java) + val wifiAwareNetworkSpecifier = WifiAwareNetworkSpecifier.Builder(discoverySession, + peerHandle).build() + specifier.satisfiedBy(wifiAwareNetworkSpecifier) + } +} From ccd5ba288a8a9c4a4547079a20ec4f17031e55d7 Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Mon, 30 Mar 2020 06:38:49 +0000 Subject: [PATCH 148/229] Make LinkPropertiesTest compatible with Q CompareResult had been moved from LinkProperties to LinkPropertiesUtils so this change ignores testCompareResult() on Q and only check compareAllRoutes() works while android version is at least R. Bug: 151782584 Test: atest CtsNetTestCasesLatestSdk:LinkPropertiesTest Merged-In: I38b0d83abf983b3bcc01fc6aea2e5cc307734198 Change-Id: I38b0d83abf983b3bcc01fc6aea2e5cc307734198 --- .../java/android/net/LinkPropertiesTest.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java index 2b5720a47e..f163512ed4 100644 --- a/tests/net/common/java/android/net/LinkPropertiesTest.java +++ b/tests/net/common/java/android/net/LinkPropertiesTest.java @@ -445,14 +445,20 @@ public class LinkPropertiesTest { // Check comparisons work. LinkProperties lp2 = new LinkProperties(lp); assertAllRoutesHaveInterface("wlan0", lp2); - assertEquals(0, lp.compareAllRoutes(lp2).added.size()); - assertEquals(0, lp.compareAllRoutes(lp2).removed.size()); + // LinkProperties#compareAllRoutes exists both in R and before R, but the return type + // changed in R, so a test compiled with the R version of LinkProperties cannot run on Q. + if (isAtLeastR()) { + assertEquals(0, lp.compareAllRoutes(lp2).added.size()); + assertEquals(0, lp.compareAllRoutes(lp2).removed.size()); + } lp2.setInterfaceName("p2p0"); assertAllRoutesHaveInterface("p2p0", lp2); assertAllRoutesNotHaveInterface("wlan0", lp2); - assertEquals(3, lp.compareAllRoutes(lp2).added.size()); - assertEquals(3, lp.compareAllRoutes(lp2).removed.size()); + if (isAtLeastR()) { + assertEquals(3, lp.compareAllRoutes(lp2).added.size()); + assertEquals(3, lp.compareAllRoutes(lp2).removed.size()); + } // Remove route with incorrect interface, no route removed. lp.removeRoute(new RouteInfo(prefix2, null, null)); @@ -936,7 +942,7 @@ public class LinkPropertiesTest { } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testCompareResult() { // Either adding or removing items compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(1), From 7fb7c3e0bf81bc76af84f299973c5a8d6e403228 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 2 Apr 2020 04:50:41 +0000 Subject: [PATCH 149/229] Only apply VPN isolation if it's fully routed VPN is considered fully routed if both IPv4 and IPv6 have either a default route or a prohibit route. Bug: 145332510 Test: atest FrameworksNetTests Merged-In: I59cf48552bca98092d1212e3d718fd420add5458 Change-Id: I59cf48552bca98092d1212e3d718fd420add5458 --- core/java/android/net/LinkProperties.java | 30 ++++++++++ core/java/android/net/RouteInfo.java | 26 +++++++++ .../android/server/ConnectivityService.java | 3 +- .../java/android/net/LinkPropertiesTest.java | 25 ++++++++ .../java/android/net/RouteInfoTest.java | 58 +++++++++++++++++++ .../server/ConnectivityServiceTest.java | 5 ++ 6 files changed, 146 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index 7ff954bdc1..651494d1c9 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -1073,6 +1073,21 @@ public final class LinkProperties implements Parcelable { return false; } + /** + * Returns true if this link has an IPv4 unreachable default route. + * + * @return {@code true} if there is an IPv4 unreachable default route, {@code false} otherwise. + * @hide + */ + public boolean hasIpv4UnreachableDefaultRoute() { + for (RouteInfo r : mRoutes) { + if (r.isIPv4UnreachableDefault()) { + return true; + } + } + return false; + } + /** * For backward compatibility. * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely @@ -1101,6 +1116,21 @@ public final class LinkProperties implements Parcelable { return false; } + /** + * Returns true if this link has an IPv6 unreachable default route. + * + * @return {@code true} if there is an IPv6 unreachable default route, {@code false} otherwise. + * @hide + */ + public boolean hasIpv6UnreachableDefaultRoute() { + for (RouteInfo r : mRoutes) { + if (r.isIPv6UnreachableDefault()) { + return true; + } + } + return false; + } + /** * For backward compatibility. * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index dbdaa4c2da..e550f85e6b 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -425,6 +425,16 @@ public final class RouteInfo implements Parcelable { return mType == RTN_UNICAST && mDestination.getPrefixLength() == 0; } + /** + * Indicates if this route is an unreachable default route. + * + * @return {@code true} if it's an unreachable route with prefix length of 0. + * @hide + */ + private boolean isUnreachableDefaultRoute() { + return mType == RTN_UNREACHABLE && mDestination.getPrefixLength() == 0; + } + /** * Indicates if this route is an IPv4 default route. * @hide @@ -433,6 +443,14 @@ public final class RouteInfo implements Parcelable { return isDefaultRoute() && mDestination.getAddress() instanceof Inet4Address; } + /** + * Indicates if this route is an IPv4 unreachable default route. + * @hide + */ + public boolean isIPv4UnreachableDefault() { + return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet4Address; + } + /** * Indicates if this route is an IPv6 default route. * @hide @@ -441,6 +459,14 @@ public final class RouteInfo implements Parcelable { return isDefaultRoute() && mDestination.getAddress() instanceof Inet6Address; } + /** + * Indicates if this route is an IPv6 unreachable default route. + * @hide + */ + public boolean isIPv6UnreachableDefault() { + return isUnreachableDefaultRoute() && mDestination.getAddress() instanceof Inet6Address; + } + /** * Indicates if this route is a host route (ie, matches only a single host address). * diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 4ab035e7f4..2eaa766ad3 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -6313,7 +6313,8 @@ public class ConnectivityService extends IConnectivityManager.Stub && !nai.networkAgentConfig.allowBypass && nc.getOwnerUid() != Process.SYSTEM_UID && lp.getInterfaceName() != null - && (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute()); + && (lp.hasIPv4DefaultRoute() || lp.hasIpv4UnreachableDefaultRoute()) + && (lp.hasIPv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute()); } private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc, diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java index b4f0daa025..939f8eb8c1 100644 --- a/tests/net/common/java/android/net/LinkPropertiesTest.java +++ b/tests/net/common/java/android/net/LinkPropertiesTest.java @@ -16,6 +16,8 @@ package android.net; +import static android.net.RouteInfo.RTN_UNREACHABLE; + import static com.android.testutils.ParcelUtilsKt.assertParcelSane; import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless; import static com.android.testutils.ParcelUtilsKt.parcelingRoundTrip; @@ -46,6 +48,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; @@ -1251,4 +1254,26 @@ public class LinkPropertiesTest { final LinkProperties Ipv6 = makeIpv6LinkProperties(); assertTrue(Ipv6.hasIpv6DnsServer()); } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testHasIpv4UnreachableDefaultRoute() { + final LinkProperties lp = makeTestObject(); + assertFalse(lp.hasIpv4UnreachableDefaultRoute()); + assertFalse(lp.hasIpv6UnreachableDefaultRoute()); + + lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); + assertTrue(lp.hasIpv4UnreachableDefaultRoute()); + assertFalse(lp.hasIpv6UnreachableDefaultRoute()); + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testHasIpv6UnreachableDefaultRoute() { + final LinkProperties lp = makeTestObject(); + assertFalse(lp.hasIpv6UnreachableDefaultRoute()); + assertFalse(lp.hasIpv4UnreachableDefaultRoute()); + + lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE)); + assertTrue(lp.hasIpv6UnreachableDefaultRoute()); + assertFalse(lp.hasIpv4UnreachableDefaultRoute()); + } } diff --git a/tests/net/common/java/android/net/RouteInfoTest.java b/tests/net/common/java/android/net/RouteInfoTest.java index 1658262c17..8204b494bb 100644 --- a/tests/net/common/java/android/net/RouteInfoTest.java +++ b/tests/net/common/java/android/net/RouteInfoTest.java @@ -31,6 +31,7 @@ import static org.junit.Assert.fail; import android.os.Build; +import androidx.core.os.BuildCompat; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -62,6 +63,11 @@ public class RouteInfoTest { return new IpPrefix(prefix); } + private static boolean isAtLeastR() { + // BuildCompat.isAtLeastR is documented to return false on release SDKs (including R) + return Build.VERSION.SDK_INT > Build.VERSION_CODES.Q || BuildCompat.isAtLeastR(); + } + @Test public void testConstructor() { RouteInfo r; @@ -195,78 +201,130 @@ public class RouteInfoTest { assertTrue(r.isDefaultRoute()); assertTrue(r.isIPv4Default()); assertFalse(r.isIPv6Default()); + if (isAtLeastR()) { + assertFalse(r.isIPv4UnreachableDefault()); + assertFalse(r.isIPv6UnreachableDefault()); + } r = new RouteInfo(Prefix("::/0"), Address("::"), "wlan0"); assertFalse(r.isHostRoute()); assertTrue(r.isDefaultRoute()); assertFalse(r.isIPv4Default()); assertTrue(r.isIPv6Default()); + if (isAtLeastR()) { + assertFalse(r.isIPv4UnreachableDefault()); + assertFalse(r.isIPv6UnreachableDefault()); + } r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0"); assertFalse(r.isHostRoute()); assertFalse(r.isDefaultRoute()); assertFalse(r.isIPv4Default()); assertFalse(r.isIPv6Default()); + if (isAtLeastR()) { + assertFalse(r.isIPv4UnreachableDefault()); + assertFalse(r.isIPv6UnreachableDefault()); + } r = new RouteInfo(Prefix("2001:db8::/48"), null, "wlan0"); assertFalse(r.isHostRoute()); assertFalse(r.isDefaultRoute()); assertFalse(r.isIPv4Default()); assertFalse(r.isIPv6Default()); + if (isAtLeastR()) { + assertFalse(r.isIPv4UnreachableDefault()); + assertFalse(r.isIPv6UnreachableDefault()); + } r = new RouteInfo(Prefix("192.0.2.0/32"), Address("0.0.0.0"), "wlan0"); assertTrue(r.isHostRoute()); assertFalse(r.isDefaultRoute()); assertFalse(r.isIPv4Default()); assertFalse(r.isIPv6Default()); + if (isAtLeastR()) { + assertFalse(r.isIPv4UnreachableDefault()); + assertFalse(r.isIPv6UnreachableDefault()); + } r = new RouteInfo(Prefix("2001:db8::/128"), Address("::"), "wlan0"); assertTrue(r.isHostRoute()); assertFalse(r.isDefaultRoute()); assertFalse(r.isIPv4Default()); assertFalse(r.isIPv6Default()); + if (isAtLeastR()) { + assertFalse(r.isIPv4UnreachableDefault()); + assertFalse(r.isIPv6UnreachableDefault()); + } r = new RouteInfo(Prefix("192.0.2.0/32"), null, "wlan0"); assertTrue(r.isHostRoute()); assertFalse(r.isDefaultRoute()); assertFalse(r.isIPv4Default()); assertFalse(r.isIPv6Default()); + if (isAtLeastR()) { + assertFalse(r.isIPv4UnreachableDefault()); + assertFalse(r.isIPv6UnreachableDefault()); + } r = new RouteInfo(Prefix("2001:db8::/128"), null, "wlan0"); assertTrue(r.isHostRoute()); assertFalse(r.isDefaultRoute()); assertFalse(r.isIPv4Default()); assertFalse(r.isIPv6Default()); + if (isAtLeastR()) { + assertFalse(r.isIPv4UnreachableDefault()); + assertFalse(r.isIPv6UnreachableDefault()); + } r = new RouteInfo(Prefix("::/128"), Address("fe80::"), "wlan0"); assertTrue(r.isHostRoute()); assertFalse(r.isDefaultRoute()); assertFalse(r.isIPv4Default()); assertFalse(r.isIPv6Default()); + if (isAtLeastR()) { + assertFalse(r.isIPv4UnreachableDefault()); + assertFalse(r.isIPv6UnreachableDefault()); + } r = new RouteInfo(Prefix("0.0.0.0/32"), Address("192.0.2.1"), "wlan0"); assertTrue(r.isHostRoute()); assertFalse(r.isDefaultRoute()); assertFalse(r.isIPv4Default()); assertFalse(r.isIPv6Default()); + if (isAtLeastR()) { + assertFalse(r.isIPv4UnreachableDefault()); + assertFalse(r.isIPv6UnreachableDefault()); + } r = new RouteInfo(Prefix("0.0.0.0/32"), Address("192.0.2.1"), "wlan0"); assertTrue(r.isHostRoute()); assertFalse(r.isDefaultRoute()); assertFalse(r.isIPv4Default()); assertFalse(r.isIPv6Default()); + if (isAtLeastR()) { + assertFalse(r.isIPv4UnreachableDefault()); + assertFalse(r.isIPv6UnreachableDefault()); + } r = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE); assertFalse(r.isHostRoute()); assertFalse(r.isDefaultRoute()); assertFalse(r.isIPv4Default()); assertFalse(r.isIPv6Default()); + if (isAtLeastR()) { + assertTrue(r.isIPv4UnreachableDefault()); + assertFalse(r.isIPv6UnreachableDefault()); + } r = new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE); assertFalse(r.isHostRoute()); assertFalse(r.isDefaultRoute()); assertFalse(r.isIPv4Default()); assertFalse(r.isIPv6Default()); + if (isAtLeastR()) { + assertFalse(r.isIPv4UnreachableDefault()); + assertTrue(r.isIPv6UnreachableDefault()); + } } @Test diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index b02398d1f1..912a27f08f 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6336,6 +6336,7 @@ public class ConnectivityServiceTest { LinkProperties lp = new LinkProperties(); lp.setInterfaceName("tun0"); 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 vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER)); final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange); @@ -6361,6 +6362,7 @@ public class ConnectivityServiceTest { public void testLegacyVpnDoesNotResultInInterfaceFilteringRule() throws Exception { LinkProperties lp = new LinkProperties(); lp.setInterfaceName("tun0"); + 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 vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER)); @@ -6392,6 +6394,7 @@ public class ConnectivityServiceTest { LinkProperties lp = new LinkProperties(); lp.setInterfaceName("tun0"); 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 vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER)); final TestNetworkAgentWrapper vpnNetworkAgent = establishVpn(lp, VPN_UID, vpnRange); @@ -6428,6 +6431,7 @@ public class ConnectivityServiceTest { reset(mMockNetd); lp = new LinkProperties(); lp.setInterfaceName("tun1"); + lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE)); lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null)); vpnNetworkAgent.sendLinkProperties(lp); waitForIdle(); @@ -6440,6 +6444,7 @@ public class ConnectivityServiceTest { public void testUidUpdateChangesInterfaceFilteringRule() throws Exception { LinkProperties lp = new LinkProperties(); lp.setInterfaceName("tun0"); + 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 = UidRange.createForUser(VPN_USER); From 71863e96047070ac88d152b692ea62da3a609cbb Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Thu, 2 Apr 2020 15:34:33 -0700 Subject: [PATCH 150/229] Added a new capability for temporarily unmetered network. Added a new network capability TEMOPORARILY_NOT_METERED to support the case that a network can temporarily become unmetered. This allows carriers to deploy unmetered 5G network. When devices camp on 5G network, this capability will be dynamically added to the network and will be removed once leaving 5G coverage. Bug: 153081494 Test: Manual Change-Id: I10e26cb0852e67f614e7b9c4e49f95e078602e21 --- core/java/android/net/NetworkCapabilities.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 9ff7ebee6d..73c6b3daf2 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -169,6 +169,7 @@ public final class NetworkCapabilities implements Parcelable { NET_CAPABILITY_OEM_PAID, NET_CAPABILITY_MCX, NET_CAPABILITY_PARTIAL_CONNECTIVITY, + NET_CAPABILITY_TEMPORARILY_NOT_METERED, }) public @interface NetCapability { } @@ -336,8 +337,16 @@ public final class NetworkCapabilities implements Parcelable { @SystemApi public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; + /** + * This capability will be set for networks that are generally metered, but are currently + * unmetered, e.g., because the user is in a particular area. This capability can be changed at + * any time. When it is removed, applications are responsible for stopping any data transfer + * that should not occur on a metered network. + */ + public static final int NET_CAPABILITY_TEMPORARILY_NOT_METERED = 25; + private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS; - private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_PARTIAL_CONNECTIVITY; + private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_TEMPORARILY_NOT_METERED; /** * Network capabilities that are expected to be mutable, i.e., can change while a particular @@ -353,7 +362,8 @@ public final class NetworkCapabilities implements Parcelable { | (1 << NET_CAPABILITY_FOREGROUND) | (1 << NET_CAPABILITY_NOT_CONGESTED) | (1 << NET_CAPABILITY_NOT_SUSPENDED) - | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY); + | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY + | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED)); /** * Network capabilities that are not allowed in NetworkRequests. This exists because the @@ -424,6 +434,7 @@ public final class NetworkCapabilities implements Parcelable { */ private static final long TEST_NETWORKS_ALLOWED_CAPABILITIES = (1 << NET_CAPABILITY_NOT_METERED) + | (1 << NET_CAPABILITY_TEMPORARILY_NOT_METERED) | (1 << NET_CAPABILITY_NOT_RESTRICTED) | (1 << NET_CAPABILITY_NOT_VPN) | (1 << NET_CAPABILITY_NOT_ROAMING) @@ -1864,6 +1875,7 @@ public final class NetworkCapabilities implements Parcelable { case NET_CAPABILITY_OEM_PAID: return "OEM_PAID"; case NET_CAPABILITY_MCX: return "MCX"; case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY"; + case NET_CAPABILITY_TEMPORARILY_NOT_METERED: return "TEMPORARILY_NOT_METERED"; default: return Integer.toString(capability); } } From 24260d5e6dd4f7458b058be9e069b03a17a06344 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 3 Apr 2020 08:41:32 +0000 Subject: [PATCH 151/229] Fix setAdministratorUids tests on Q setAdministratorUids does not exist on Q, so such tests must be skipped on Q devices. Bug: 147903575 Test: atest CtsNetTestCasesLatestSdk on Q and AOSP devices Merged-In: I1b362660de9733bb9f0ede1ed5cf62279bf1c05e Change-Id: I1b362660de9733bb9f0ede1ed5cf62279bf1c05e --- .../android/net/NetworkCapabilitiesTest.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index 316a83adf4..6e9dc8eaf2 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -55,6 +55,10 @@ import android.util.ArraySet; import androidx.core.os.BuildCompat; import androidx.test.runner.AndroidJUnit4; +import com.android.testutils.DevSdkIgnoreRule; +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; + +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -67,6 +71,9 @@ public class NetworkCapabilitiesTest { private static final String TEST_SSID = "TEST_SSID"; private static final String DIFFERENT_TEST_SSID = "DIFFERENT_TEST_SSID"; + @Rule + public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule(); + private boolean isAtLeastR() { // BuildCompat.isAtLeastR() is used to check the Android version before releasing Android R. // Build.VERSION.SDK_INT > Build.VERSION_CODES.Q is used to check the Android version after @@ -441,7 +448,7 @@ public class NetworkCapabilitiesTest { return range; } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testSetAdministratorUids() { NetworkCapabilities nc = new NetworkCapabilities().setAdministratorUids(new int[] {2, 1, 3}); @@ -449,7 +456,7 @@ public class NetworkCapabilitiesTest { assertArrayEquals(new int[] {1, 2, 3}, nc.getAdministratorUids()); } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testSetAdministratorUidsWithDuplicates() { try { new NetworkCapabilities().setAdministratorUids(new int[] {1, 1}); @@ -510,6 +517,12 @@ public class NetworkCapabilitiesTest { assertFalse(nc2.appliesToUid(12)); assertTrue(nc1.appliesToUid(22)); assertTrue(nc2.appliesToUid(22)); + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testCombineCapabilities_AdministratorUids() { + final NetworkCapabilities nc1 = new NetworkCapabilities(); + final NetworkCapabilities nc2 = new NetworkCapabilities(); final int[] adminUids = {3, 6, 12}; nc1.setAdministratorUids(adminUids); @@ -518,7 +531,7 @@ public class NetworkCapabilitiesTest { assertArrayEquals(nc2.getAdministratorUids(), adminUids); final int[] adminUidsOtherOrder = {3, 12, 6}; - nc1.setAdministratorUids(adminUids); + nc1.setAdministratorUids(adminUidsOtherOrder); assertTrue(nc2.equalsAdministratorUids(nc1)); final int[] adminUids2 = {11, 1, 12, 3, 6}; From 56f59c493bae56fdf09f63bf94be246260633326 Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 2 Apr 2020 18:36:24 +0000 Subject: [PATCH 152/229] [SP26.2] add a method in NetworkStats that removes empty entries In current design, entries with zeros are preserved after addition/subtraction. These entries are not very useful and lead to difficulty of verifying the result of addition/subtraction. However, change the behavior in the original NetworkStats is considered risky in current stage. Thus, this change provide a function that could remove these empty entries in tests. Test: atest FrameworksNetTests Bug: 152827872 Bug: 150644692 Change-Id: I40a76935d55712b8083ee1e17e137a8a4ef5e029 Merged-In: I40a76935d55712b8083ee1e17e137a8a4ef5e029 (cherry picked from commit 6c7bef3064dbe949b7b213036b8e70c125ddd343) --- .../java/android/net/NetworkStatsTest.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java index e71d599525..98f705f45e 100644 --- a/tests/net/java/android/net/NetworkStatsTest.java +++ b/tests/net/java/android/net/NetworkStatsTest.java @@ -502,6 +502,53 @@ public class NetworkStatsTest { DEFAULT_NETWORK_NO, 64L, 2L, 0L, 0L, 0L); } + @Test + public void testRemoveEmptyEntries() throws Exception { + // Test empty stats. + final NetworkStats statsEmpty = new NetworkStats(TEST_START, 3); + assertEquals(0, statsEmpty.removeEmptyEntries().size()); + + // Test stats with non-zero entry. + final NetworkStats statsNonZero = new NetworkStats(TEST_START, 1) + .insertEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO, + ROAMING_NO, DEFAULT_NETWORK_NO, 1L, 128L, 0L, 2L, 20L); + assertEquals(1, statsNonZero.size()); + final NetworkStats expectedNonZero = statsNonZero.removeEmptyEntries(); + assertEquals(1, expectedNonZero.size()); + assertValues(expectedNonZero, 0, TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO, + ROAMING_NO, DEFAULT_NETWORK_NO, 1L, 128L, 0L, 2L, 20L); + + // Test stats with empty entry. + final NetworkStats statsZero = new NetworkStats(TEST_START, 1) + .insertEntry(TEST_IFACE, 99, SET_DEFAULT, TAG_NONE, METERED_NO, + ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L); + assertEquals(1, statsZero.size()); + final NetworkStats expectedZero = statsZero.removeEmptyEntries(); + assertEquals(1, statsZero.size()); // Assert immutable. + assertEquals(0, expectedZero.size()); + + // Test stats with multiple entries. + final NetworkStats statsMultiple = new NetworkStats(TEST_START, 0) + .insertEntry(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 2L, 64L, 0L, 2L, 20L) + .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 4L, 32L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 0L, 8L, 0L, 0L, 0L) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 4L, 0L, 0L) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 0L, 2L, 0L) + .insertEntry(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 0L, 0L, 1L); + assertEquals(9, statsMultiple.size()); + final NetworkStats expectedMultiple = statsMultiple.removeEmptyEntries(); + assertEquals(9, statsMultiple.size()); // Assert immutable. + assertEquals(7, expectedMultiple.size()); + assertValues(expectedMultiple.getTotalIncludingTags(null), 14L, 104L, 4L, 4L, 21L); + + // Test stats with multiple empty entries. + assertEquals(statsMultiple.size(), statsMultiple.subtract(statsMultiple).size()); + assertEquals(0, statsMultiple.subtract(statsMultiple).removeEmptyEntries().size()); + } + @Test public void testClone() throws Exception { final NetworkStats original = new NetworkStats(TEST_START, 5) From b80fe74899555d72ec8f894a74c06892843812a5 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Thu, 2 Apr 2020 18:36:31 +0000 Subject: [PATCH 153/229] [SP26] add CTS for NetworkStats Test: atest NetworkStatsApiTest Test: atest CtsNetTestCasesLatestSdk:NetworkStatsApiTest on Q device Bug: 150644692 Change-Id: I690704b43cfd16de70c4c83916f6d750cf613f67 Merged-In: I690704b43cfd16de70c4c83916f6d750cf613f67 (cherry picked from commit 5c670a2714f3ed783b6d5245714d0039c8fd1e9c) --- .../net/netstats/NetworkStatsApiTest.kt | 209 ++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt diff --git a/tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt b/tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt new file mode 100644 index 0000000000..9119d62fb0 --- /dev/null +++ b/tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2020 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.netstats + +import android.net.NetworkStats +import android.net.NetworkStats.DEFAULT_NETWORK_NO +import android.net.NetworkStats.DEFAULT_NETWORK_YES +import android.net.NetworkStats.Entry +import android.net.NetworkStats.IFACE_VT +import android.net.NetworkStats.METERED_NO +import android.net.NetworkStats.METERED_YES +import android.net.NetworkStats.ROAMING_NO +import android.net.NetworkStats.ROAMING_YES +import android.net.NetworkStats.SET_DEFAULT +import android.net.NetworkStats.SET_FOREGROUND +import android.net.NetworkStats.TAG_NONE +import android.os.Build +import androidx.test.filters.SmallTest +import com.android.testutils.DevSdkIgnoreRule +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo +import com.android.testutils.assertFieldCountEquals +import com.android.testutils.assertNetworkStatsEquals +import com.android.testutils.assertParcelingIsLossless +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import kotlin.test.assertEquals + +@RunWith(JUnit4::class) +@SmallTest +class NetworkStatsApiTest { + @Rule + @JvmField + val ignoreRule = DevSdkIgnoreRule() + + private val testStatsEmpty = NetworkStats(0L, 0) + + // stats1 and stats2 will have some entries with common keys, which are expected to + // be merged if performing add on these 2 stats. + private val testStats1 = NetworkStats(0L, 0) + // Entries which only appear in set1. + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 20, 3, 57, 40, 3)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 31, 7, 24, 5, 8)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 25, 3, 47, 8, 2)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 37, 52, 1, 10, 4)) + // Entries which are common for set1 and set2. + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 101, 2, 103, 4, 5)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 17, 2, 11, 1, 0)) + .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 40, 1, 0, 0, 8)) + .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 1, 6, 2, 0)) + + private val testStats2 = NetworkStats(0L, 0) + // Entries which are common for set1 and set2. + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 15, 2, 31, 1)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45)) + .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 11, 2, 3, 4, 7)) + .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4, 3, 2, 1, 0)) + // Entry which only appears in set2. + .addEntry(Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0)) + + // This is a result of adding stats1 and stats2, while the merging of common key items is + // subject to test later, this should not be initialized with for a loop to add stats1 + // and stats2 above. + private val testStats3 = NetworkStats(0L, 9) + // Entries which are unique either in stats1 or stats2. + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 101, 2, 103, 4, 5)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 31, 7, 24, 5, 8)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 25, 3, 47, 8, 2)) + .addEntry(Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0)) + // Entries which are common for stats1 and stats2 are being merged. + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 20, 3, 57, 40, 3)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 20, 17, 13, 32, 1)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 50, 113, 11, 11, 49)) + .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 51, 3, 3, 4, 15)) + .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 7, 4, 8, 3, 0)) + + companion object { + private const val TEST_IFACE = "test0" + private const val TEST_UID1 = 1001 + private const val TEST_UID2 = 1002 + } + + @Before + fun setUp() { + assertEquals(8, testStats1.size()) + assertEquals(5, testStats2.size()) + assertEquals(9, testStats3.size()) + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testAddEntry() { + val expectedEntriesInStats2 = arrayOf( + Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 15, 2, 31, 1), + Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45), + Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 11, 2, 3, 4, 7), + Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4, 3, 2, 1, 0), + Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0)) + + // While testStats* are already initialized with addEntry, verify content added + // matches expectation. + for (i in expectedEntriesInStats2.indices) { + val entry = testStats2.getValues(i, null) + assertEquals(expectedEntriesInStats2[i], entry) + } + + // Verify entry updated with addEntry. + val stats = testStats2.addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 12, -5, 7, 0, 9)) + assertEquals(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 16, -2, 9, 1, 9), + stats.getValues(3, null)) + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testAdd() { + var stats = NetworkStats(0L, 0) + assertNetworkStatsEquals(testStatsEmpty, stats) + stats = stats.add(testStats2) + assertNetworkStatsEquals(testStats2, stats) + stats = stats.add(testStats1) + // EMPTY + STATS2 + STATS1 = STATS3 + assertNetworkStatsEquals(testStats3, stats) + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testParcelUnparcel() { + assertParcelingIsLossless(testStatsEmpty) + assertParcelingIsLossless(testStats1) + assertParcelingIsLossless(testStats2) + assertFieldCountEquals(15, NetworkStats::class.java) + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testDescribeContents() { + assertEquals(0, testStatsEmpty.describeContents()) + assertEquals(0, testStats1.describeContents()) + assertEquals(0, testStats2.describeContents()) + assertEquals(0, testStats3.describeContents()) + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testSubtract() { + // STATS3 - STATS2 = STATS1 + assertNetworkStatsEquals(testStats1, testStats3.subtract(testStats2)) + // STATS3 - STATS1 = STATS2 + assertNetworkStatsEquals(testStats2, testStats3.subtract(testStats1)) + } + + @Test + @IgnoreUpTo(Build.VERSION_CODES.Q) + fun testMethodsDontModifyReceiver() { + listOf(testStatsEmpty, testStats1, testStats2, testStats3).forEach { + val origStats = it.clone() + it.addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45)) + it.add(testStats3) + it.subtract(testStats1) + assertNetworkStatsEquals(origStats, it) + } + } +} \ No newline at end of file From 26fc3f31ffef361b1bbf890d2e948001494a2413 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Mon, 6 Apr 2020 07:25:10 +0000 Subject: [PATCH 154/229] Fix a bug where the legacy extra info is reset on connect. Bug: 149459996 Test: NetworkAgentTest FrameworksNetTests FrameworksWifiTests FrameworksTelephonyTests Change-Id: I3e437f0fe2eb28f1d621551a8daf164a06af83fc Merged-In: I3e437f0fe2eb28f1d621551a8daf164a06af83fc (cherry picked from commit a3fdb94a32eda40e322b7dbdaf3fad9b42bfbbb9, originally aosp/1277602) --- core/java/android/net/NetworkAgent.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index fe90a84579..c42dacc187 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -624,7 +624,9 @@ public abstract class NetworkAgent { throw new UnsupportedOperationException( "Legacy agents can't call markConnected."); } - mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); + // |reason| cannot be used by the non-legacy agents + mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null /* reason */, + mNetworkInfo.getExtraInfo()); queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); } @@ -638,7 +640,9 @@ public abstract class NetworkAgent { if (mIsLegacy) { throw new UnsupportedOperationException("Legacy agents can't call unregister."); } - mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null); + // When unregistering an agent nobody should use the extrainfo (or reason) any more. + mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null /* reason */, + null /* extraInfo */); queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); } From 6c0cbccf96860fec337dc2ff04f5aad37c126b3f Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 2 Apr 2020 15:24:59 +0000 Subject: [PATCH 155/229] Rename the *Nat64Prefix to *Nat64PrefixFromDns. This just a rename with no functional changes at all. It is preparation for supporting getting the NAT64 prefix from the RA. Bug: 150648313 Test: covered by existing ConnectivityServiceTest and Nat464XlatTest Merged-In: Ia9a09a708870827b1e4cf068f930fa9542dd116c Change-Id: Ia9a09a708870827b1e4cf068f930fa9542dd116c --- .../com/android/server/ConnectivityService.java | 8 ++++---- .../android/server/connectivity/Nat464Xlat.java | 16 ++++++++++------ .../server/connectivity/Nat464XlatTest.java | 10 +++++----- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2eaa766ad3..8a1de1f076 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3153,7 +3153,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - nai.clatd.setNat64Prefix(prefix); + nai.clatd.setNat64PrefixFromDns(prefix); handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties)); } @@ -5865,9 +5865,9 @@ public class ConnectivityService extends IConnectivityManager.Stub @NonNull LinkProperties oldLp) { int netId = networkAgent.network.netId; - // The NetworkAgentInfo does not know whether clatd is running on its network or not, or - // whether there is a NAT64 prefix. Before we do anything else, make sure its LinkProperties - // are accurate. + // The NetworkAgent does not know whether clatd is running on its network or not, or whether + // a NAT64 prefix was discovered by the DNS resolver. Before we do anything else, make sure + // the LinkProperties for the network are accurate. networkAgent.clatd.fixupLinkProperties(oldLp, newLp); updateInterfaces(newLp, oldLp, netId, networkAgent.networkCapabilities, diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index 82465f8a09..3b3c52072b 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -81,7 +81,7 @@ public class Nat464Xlat extends BaseNetworkObserver { RUNNING, // start() called, and the stacked iface is known to be up. } - private IpPrefix mNat64Prefix; + private IpPrefix mNat64PrefixFromDns; private String mBaseIface; private String mIface; private Inet6Address mIPv6Address; @@ -100,7 +100,7 @@ public class Nat464Xlat extends BaseNetworkObserver { * currently connected and where the NetworkAgent has not disabled 464xlat. It is the signal to * enable NAT64 prefix discovery. * - * @param network the NetworkAgentInfo corresponding to the network. + * @param nai the NetworkAgentInfo corresponding to the network. * @return true if the network requires clat, false otherwise. */ @VisibleForTesting @@ -180,7 +180,7 @@ public class Nat464Xlat extends BaseNetworkObserver { String addrStr = null; try { - addrStr = mNetd.clatdStart(baseIface, mNat64Prefix.toString()); + addrStr = mNetd.clatdStart(baseIface, getNat64Prefix().toString()); } catch (RemoteException | ServiceSpecificException e) { Slog.e(TAG, "Error starting clatd on " + baseIface + ": " + e); } @@ -318,8 +318,12 @@ public class Nat464Xlat extends BaseNetworkObserver { } } - public void setNat64Prefix(IpPrefix nat64Prefix) { - mNat64Prefix = nat64Prefix; + private IpPrefix getNat64Prefix() { + return mNat64PrefixFromDns; + } + + public void setNat64PrefixFromDns(IpPrefix prefix) { + mNat64PrefixFromDns = prefix; } /** @@ -328,7 +332,7 @@ public class Nat464Xlat extends BaseNetworkObserver { * has no idea that 464xlat is running on top of it. */ public void fixupLinkProperties(@NonNull LinkProperties oldLp, @NonNull LinkProperties lp) { - lp.setNat64Prefix(mNat64Prefix); + lp.setNat64Prefix(getNat64Prefix()); if (!isRunning()) { return; diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java index 9b248878fe..d0ebb5283f 100644 --- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java +++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java @@ -181,7 +181,7 @@ public class Nat464XlatTest { Nat464Xlat nat = makeNat464Xlat(); ArgumentCaptor c = ArgumentCaptor.forClass(LinkProperties.class); - nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX)); + nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); // Start clat. nat.start(); @@ -222,7 +222,7 @@ public class Nat464XlatTest { ArgumentCaptor c = ArgumentCaptor.forClass(LinkProperties.class); InOrder inOrder = inOrder(mNetd, mConnectivity); - nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX)); + nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); nat.start(); @@ -309,7 +309,7 @@ public class Nat464XlatTest { Nat464Xlat nat = makeNat464Xlat(); ArgumentCaptor c = ArgumentCaptor.forClass(LinkProperties.class); - nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX)); + nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); nat.start(); @@ -348,7 +348,7 @@ public class Nat464XlatTest { public void testStopBeforeClatdStarts() throws Exception { Nat464Xlat nat = makeNat464Xlat(); - nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX)); + nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); nat.start(); @@ -380,7 +380,7 @@ public class Nat464XlatTest { public void testStopAndClatdNeverStarts() throws Exception { Nat464Xlat nat = makeNat464Xlat(); - nat.setNat64Prefix(new IpPrefix(NAT64_PREFIX)); + nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); nat.start(); From 24398db2b6ea2cba4b3f1010466c586d604c5e79 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 6 Apr 2020 11:24:19 +0000 Subject: [PATCH 156/229] Refactor the Nat464Xlat function for simplicity. This makes the code easier to understand by making state transitions more explicit. It also makes it easier to address a TODO to turn the class into a StateMachine. This should be an exact no-op refactoring. The current cases covered by the code (all mutually exclusive) are: 1. requiresClat && !isPrefixDiscoveryStarted Action: startPrefixDiscovery() Equivalent to IDLE && requiresClat, because isPrefixDiscoveryStarted returns true for every state except IDLE. 2. requiresClat && isPrefixDiscoveryStarted && shouldStartClat Action: start() Equivalent to DISCOVERING && shouldStartClat, because isPrefixDiscoveryStarted is true in DISCOVERING, STARTING, and RUNNING, but start() does nothing if mState is STARTING or RUNNING. 3. requiresClat && isPrefixDiscoveryStarted && !shouldStartClat Action: stop() Equivalent to (STARTING or RUNNING) && !shouldStartClat, because isPrefixDiscoveryStarted is true in DISCOVERING, STARTING, and RUNNING, but stop() does nothing if mState is not STARTING or RUNNING. 4. !requiresClat && isStarted Action: stop() Equivalent to (STARTING or RUNNING) && !requiresClat, because isStarted() is only true in STARTING and RUNNING. 5. !requiresClat && !isStarted && isPrefixDiscoveryStarted Action: leaveStartedState() Equivalent to DISCOVERING && !requiresClat, because the only state with isPrefixDiscoveryStarted and !isStarted is DISCOVERING. Also, simplify case #5. In this case, calling leaveStartedState is superfluous, because in the DISCOVERING state: - There is no need to call unregisterObserver, since the observer is only registered when entering STARTING and is unregistered when going back to DISCOVERING or IDLE. - mIface and mBaseIface don't need to be set to null because they are only set to non-null when entering STARTING and nulled out when going back to DISCOVERING or IDLE. Bug: 126113090 Bug: 150648313 Test: covered by existing ConnectivityServiceTest and Nat464XlatTest Merged-In: Ice536bcb269cc8b040c6e7a72c15d0bc8b5bd235 Change-Id: Ice536bcb269cc8b040c6e7a72c15d0bc8b5bd235 --- .../server/connectivity/Nat464Xlat.java | 61 ++++++++++++------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index 82465f8a09..af2db4abde 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -213,12 +213,10 @@ public class Nat464Xlat extends BaseNetworkObserver { } mIface = null; mBaseIface = null; - mState = State.IDLE; if (requiresClat(mNetwork)) { mState = State.DISCOVERING; } else { stopPrefixDiscovery(); - mState = State.IDLE; } } @@ -285,6 +283,7 @@ public class Nat464Xlat extends BaseNetworkObserver { private void stopPrefixDiscovery() { try { mDnsResolver.stopPrefix64Discovery(getNetId()); + mState = State.IDLE; } catch (RemoteException | ServiceSpecificException e) { Slog.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e); } @@ -294,27 +293,43 @@ public class Nat464Xlat extends BaseNetworkObserver { * Starts/stops NAT64 prefix discovery and clatd as necessary. */ public void update() { - // TODO: turn this class into a proper StateMachine. // http://b/126113090 - if (requiresClat(mNetwork)) { - if (!isPrefixDiscoveryStarted()) { - startPrefixDiscovery(); - } else if (shouldStartClat(mNetwork)) { - // NAT64 prefix detected. Start clatd. - // TODO: support the NAT64 prefix changing after it's been discovered. There is no - // need to support this at the moment because it cannot happen without changes to - // the Dns64Configuration code in netd. - start(); - } else { - // NAT64 prefix removed. Stop clatd and go back into DISCOVERING state. - stop(); - } - } else { - // Network no longer requires clat. Stop clat and prefix discovery. - if (isStarted()) { - stop(); - } else if (isPrefixDiscoveryStarted()) { - leaveStartedState(); - } + // TODO: turn this class into a proper StateMachine. http://b/126113090 + switch (mState) { + case IDLE: + if (requiresClat(mNetwork)) { + // Network is detected to be IPv6-only. + // TODO: consider going to STARTING directly if the NAT64 prefix is already + // known. This would however result in clatd running without prefix discovery + // running, which might be a surprising combination. + startPrefixDiscovery(); // Enters DISCOVERING state. + return; + } + break; + + case DISCOVERING: + if (shouldStartClat(mNetwork)) { + // NAT64 prefix detected. Start clatd. + start(); // Enters STARTING state. + return; + } + if (!requiresClat(mNetwork)) { + // IPv4 address added. Go back to IDLE state. + stopPrefixDiscovery(); + return; + } + break; + + case STARTING: + case RUNNING: + // NAT64 prefix removed, or IPv4 address added. + // Stop clatd and go back into DISCOVERING or idle. + if (!shouldStartClat(mNetwork)) { + stop(); + } + break; + // TODO: support the NAT64 prefix changing after it's been discovered. There is + // no need to support this at the moment because it cannot happen without + // changes to the Dns64Configuration code in netd. } } From 50756739b5492d985027ffb5cbff7f5612b41ff9 Mon Sep 17 00:00:00 2001 From: Treehugger Robot Date: Tue, 7 Apr 2020 06:59:06 +0000 Subject: [PATCH 157/229] Fix a stupid NPE Okay so this is really not a behavior change as it converts an NPE into an illegal argument exception, but still, that's what should happen (and that's what the upcoming test actually tests for). Test: upcoming NetworkAgentTest Bug: 139268426 Change-Id: I0d9b8cb8f8dcb587b9430b486b863efb9e9e77ef Merged-In: I3e17211c03bc74426bf5e2e414ec322d73b0060b (cherry picked from commit 827d7ceea1e83cca9ba3f6189e20b6780c0194ed, aosp/1277595) --- core/java/android/net/NetworkAgent.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index c42dacc187..e9bcefef50 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -556,12 +556,12 @@ public abstract class NetworkAgent { @NonNull public Network register() { if (VDBG) log("Registering NetworkAgent"); - final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context - .getSystemService(Context.CONNECTIVITY_SERVICE); synchronized (mRegisterLock) { if (mNetwork != null) { throw new IllegalStateException("Agent already registered"); } + final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context + .getSystemService(Context.CONNECTIVITY_SERVICE); mNetwork = cm.registerNetworkAgent(new Messenger(mHandler), new NetworkInfo(mInitialConfiguration.info), mInitialConfiguration.properties, mInitialConfiguration.capabilities, From 4aae1e23cfb2dcd22b1d84effcad1d9eb7a197f2 Mon Sep 17 00:00:00 2001 From: Treehugger Robot Date: Tue, 7 Apr 2020 09:56:23 +0000 Subject: [PATCH 158/229] Add trivial dependencies tests for the network stack Test: this Bug: 153033018 Change-Id: I3e66752ebfb5f4324d897210ce26ddaf67f53228 Merged-In: Ie3c15ed25ef3088d3b9b650ffc7f34f49efa6b81 (cherry picked from commit c79353f2e4a99635bcf6eb9177c971f268f71204, aosp/1275998) --- .../java/android/net/DependenciesTest.java | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 tests/net/common/java/android/net/DependenciesTest.java diff --git a/tests/net/common/java/android/net/DependenciesTest.java b/tests/net/common/java/android/net/DependenciesTest.java new file mode 100644 index 0000000000..ac1c28a454 --- /dev/null +++ b/tests/net/common/java/android/net/DependenciesTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2020 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 static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +/** + * A simple class that tests dependencies to java standard tools from the + * Network stack. These tests are not meant to be comprehensive tests of + * the relevant APIs : such tests belong in the relevant test suite for + * these dependencies. Instead, this just makes sure coverage is present + * by calling the methods in the exact way (or a representative way of how) + * they are called in the network stack. + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +public class DependenciesTest { + // Used to in ipmemorystore's RegularMaintenanceJobService to convert + // 24 hours into seconds + @Test + public void testTimeUnit() { + final int hours = 24; + final long inSeconds = TimeUnit.HOURS.toMillis(hours); + assertEquals(inSeconds, hours * 60 * 60 * 1000); + } + + private byte[] makeTrivialArray(final int size) { + final byte[] src = new byte[size]; + for (int i = 0; i < size; ++i) { + src[i] = (byte) i; + } + return src; + } + + // Used in ApfFilter to find an IP address from a byte array + @Test + public void testArrays() { + final int size = 128; + final byte[] src = makeTrivialArray(size); + + // Test copy + final int copySize = 16; + final int offset = 24; + final byte[] expected = new byte[copySize]; + for (int i = 0; i < copySize; ++i) { + expected[i] = (byte) (offset + i); + } + + final byte[] copy = Arrays.copyOfRange(src, offset, offset + copySize); + assertArrayEquals(expected, copy); + assertArrayEquals(new byte[0], Arrays.copyOfRange(src, size, size)); + } + + // Used mainly in the Dhcp code + @Test + public void testCopyOf() { + final byte[] src = makeTrivialArray(128); + final byte[] copy = Arrays.copyOf(src, src.length); + assertArrayEquals(src, copy); + assertFalse(src == copy); + + assertArrayEquals(new byte[0], Arrays.copyOf(src, 0)); + + final int excess = 16; + final byte[] biggerCopy = Arrays.copyOf(src, src.length + excess); + for (int i = src.length; i < src.length + excess; ++i) { + assertEquals(0, biggerCopy[i]); + } + for (int i = src.length - 1; i >= 0; --i) { + assertEquals(src[i], biggerCopy[i]); + } + } + + // Used mainly in DnsUtils but also various other places + @Test + public void testAsList() { + final int size = 24; + final Object[] src = new Object[size]; + final ArrayList expected = new ArrayList<>(size); + for (int i = 0; i < size; ++i) { + final Object o = new Object(); + src[i] = o; + expected.add(o); + } + assertEquals(expected, Arrays.asList(src)); + } +} From 7ab8d925bf0590addc2ba751b0b13cf9d809fc03 Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 7 Apr 2020 12:01:32 +0000 Subject: [PATCH 159/229] Fix NetworkStatsApiTest failed on Q device Currently, the addEntry method is used in constructor of test, which is not correct since there is no such method in Q devices. Thus, initialize of NetworkStats variables outside of constructor. Test: atest NetworkStatsApiTest Test: atest CtsNetTestCasesLatestSdk:NetworkStatsApiTest on Q device Bug: 150644692 Change-Id: Ibf2f8118c459a8d7a0992deca8f0f339ccd1bcea Merged-In: Ibf2f8118c459a8d7a0992deca8f0f339ccd1bcea (cherry picked from commit ae023a8bbd3a7482fd66547d58759c88e100f207) --- .../net/netstats/NetworkStatsApiTest.kt | 124 +++++++++--------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt b/tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt index 9119d62fb0..7b22e45db9 100644 --- a/tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt +++ b/tests/net/common/java/android/net/netstats/NetworkStatsApiTest.kt @@ -31,7 +31,6 @@ import android.net.NetworkStats.TAG_NONE import android.os.Build import androidx.test.filters.SmallTest import com.android.testutils.DevSdkIgnoreRule -import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.assertFieldCountEquals import com.android.testutils.assertNetworkStatsEquals import com.android.testutils.assertParcelingIsLossless @@ -47,70 +46,22 @@ import kotlin.test.assertEquals class NetworkStatsApiTest { @Rule @JvmField - val ignoreRule = DevSdkIgnoreRule() + val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = Build.VERSION_CODES.Q) private val testStatsEmpty = NetworkStats(0L, 0) + // Note that these variables need to be initialized outside of constructor, initialize + // here with methods that don't exist in Q devices will result in crash. + // stats1 and stats2 will have some entries with common keys, which are expected to // be merged if performing add on these 2 stats. - private val testStats1 = NetworkStats(0L, 0) - // Entries which only appear in set1. - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 20, 3, 57, 40, 3)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 31, 7, 24, 5, 8)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 25, 3, 47, 8, 2)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 37, 52, 1, 10, 4)) - // Entries which are common for set1 and set2. - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 101, 2, 103, 4, 5)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 17, 2, 11, 1, 0)) - .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 40, 1, 0, 0, 8)) - .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 1, 6, 2, 0)) - - private val testStats2 = NetworkStats(0L, 0) - // Entries which are common for set1 and set2. - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 15, 2, 31, 1)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45)) - .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 11, 2, 3, 4, 7)) - .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4, 3, 2, 1, 0)) - // Entry which only appears in set2. - .addEntry(Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0)) + private lateinit var testStats1: NetworkStats + private lateinit var testStats2: NetworkStats // This is a result of adding stats1 and stats2, while the merging of common key items is // subject to test later, this should not be initialized with for a loop to add stats1 // and stats2 above. - private val testStats3 = NetworkStats(0L, 9) - // Entries which are unique either in stats1 or stats2. - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 101, 2, 103, 4, 5)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 31, 7, 24, 5, 8)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 25, 3, 47, 8, 2)) - .addEntry(Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0)) - // Entries which are common for stats1 and stats2 are being merged. - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 20, 3, 57, 40, 3)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 20, 17, 13, 32, 1)) - .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 50, 113, 11, 11, 49)) - .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 51, 3, 3, 4, 15)) - .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 7, 4, 8, 3, 0)) + private lateinit var testStats3: NetworkStats companion object { private const val TEST_IFACE = "test0" @@ -120,13 +71,67 @@ class NetworkStatsApiTest { @Before fun setUp() { + testStats1 = NetworkStats(0L, 0) + // Entries which only appear in set1. + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 20, 3, 57, 40, 3)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 31, 7, 24, 5, 8)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 25, 3, 47, 8, 2)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 37, 52, 1, 10, 4)) + // Entries which are common for set1 and set2. + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 101, 2, 103, 4, 5)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 17, 2, 11, 1, 0)) + .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 40, 1, 0, 0, 8)) + .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 1, 6, 2, 0)) assertEquals(8, testStats1.size()) + + testStats2 = NetworkStats(0L, 0) + // Entries which are common for set1 and set2. + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 3, 15, 2, 31, 1)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 13, 61, 10, 1, 45)) + .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 11, 2, 3, 4, 7)) + .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 4, 3, 2, 1, 0)) + // Entry which only appears in set2. + .addEntry(Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0)) assertEquals(5, testStats2.size()) + + testStats3 = NetworkStats(0L, 9) + // Entries which are unique either in stats1 or stats2. + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 101, 2, 103, 4, 5)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_YES, DEFAULT_NETWORK_NO, 31, 7, 24, 5, 8)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, 25, 3, 47, 8, 2)) + .addEntry(Entry(IFACE_VT, TEST_UID2, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 2, 3, 7, 8, 0)) + // Entries which are common for stats1 and stats2 are being merged. + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, 20, 3, 57, 40, 3)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 20, 17, 13, 32, 1)) + .addEntry(Entry(TEST_IFACE, TEST_UID1, SET_FOREGROUND, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 50, 113, 11, 11, 49)) + .addEntry(Entry(TEST_IFACE, TEST_UID2, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 51, 3, 3, 4, 15)) + .addEntry(Entry(IFACE_VT, TEST_UID1, SET_DEFAULT, TAG_NONE, + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 7, 4, 8, 3, 0)) assertEquals(9, testStats3.size()) } @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) fun testAddEntry() { val expectedEntriesInStats2 = arrayOf( Entry(TEST_IFACE, TEST_UID1, SET_DEFAULT, 0x80, @@ -156,7 +161,6 @@ class NetworkStatsApiTest { } @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) fun testAdd() { var stats = NetworkStats(0L, 0) assertNetworkStatsEquals(testStatsEmpty, stats) @@ -168,7 +172,6 @@ class NetworkStatsApiTest { } @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) fun testParcelUnparcel() { assertParcelingIsLossless(testStatsEmpty) assertParcelingIsLossless(testStats1) @@ -177,7 +180,6 @@ class NetworkStatsApiTest { } @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) fun testDescribeContents() { assertEquals(0, testStatsEmpty.describeContents()) assertEquals(0, testStats1.describeContents()) @@ -186,7 +188,6 @@ class NetworkStatsApiTest { } @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) fun testSubtract() { // STATS3 - STATS2 = STATS1 assertNetworkStatsEquals(testStats1, testStats3.subtract(testStats2)) @@ -195,7 +196,6 @@ class NetworkStatsApiTest { } @Test - @IgnoreUpTo(Build.VERSION_CODES.Q) fun testMethodsDontModifyReceiver() { listOf(testStatsEmpty, testStats1, testStats2, testStats3).forEach { val origStats = it.clone() From c12fcce03c4b0251a64dcdabb6041549e7b4eba8 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Tue, 7 Apr 2020 17:40:09 +0800 Subject: [PATCH 160/229] Add more tests in NetworkCapabilitiesTest.java Test deduceRestrictedCapability(), getAdministratorUids(), setAdministratorUids(), getNetworkSpecifier(), getOwnerUid(), setLinkDownstreamBandwidthKbps(), setLinkUpstreamBandwidthKbps(), setSignalStrength() and Builder(). Bug: 139268426 Bug: 135998869 Bug: 138306002 Test: atest CtsNetTestCasesLatestSdk:android.net.NetworkCapabilitiesTest Change-Id: I525941c47b71cd61ee872fd4d71b02a5d3767e21 Merged-In: I90c7a8c47710ea4ad8e8d2682c10440fd7f82270 --- .../android/net/NetworkCapabilitiesTest.java | 241 ++++++++++++++++++ 1 file changed, 241 insertions(+) diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index 6e9dc8eaf2..12d80fc2c0 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -17,6 +17,8 @@ package android.net; import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; +import static android.net.NetworkCapabilities.MAX_TRANSPORT; +import static android.net.NetworkCapabilities.MIN_TRANSPORT; import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL; import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS; import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS; @@ -32,10 +34,12 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVIT import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P; import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES; +import static android.net.NetworkCapabilities.SIGNAL_STRENGTH_UNSPECIFIED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_TEST; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES; import static com.android.testutils.ParcelUtilsKt.assertParcelSane; @@ -45,10 +49,15 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.net.wifi.aware.DiscoverySession; +import android.net.wifi.aware.PeerHandle; +import android.net.wifi.aware.WifiAwareNetworkSpecifier; import android.os.Build; +import android.os.Process; import android.test.suitebuilder.annotation.SmallTest; import android.util.ArraySet; @@ -61,6 +70,7 @@ import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; import java.util.Arrays; import java.util.Set; @@ -74,6 +84,9 @@ public class NetworkCapabilitiesTest { @Rule public DevSdkIgnoreRule mDevSdkIgnoreRule = new DevSdkIgnoreRule(); + private DiscoverySession mDiscoverySession = Mockito.mock(DiscoverySession.class); + private PeerHandle mPeerHandle = Mockito.mock(PeerHandle.class); + private boolean isAtLeastR() { // BuildCompat.isAtLeastR() is used to check the Android version before releasing Android R. // Build.VERSION.SDK_INT > Build.VERSION_CODES.Q is used to check the Android version after @@ -685,4 +698,232 @@ public class NetworkCapabilitiesTest { assertEquals(TRANSPORT_VPN, transportTypes[2]); assertEquals(TRANSPORT_TEST, transportTypes[3]); } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testTelephonyNetworkSpecifier() { + final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier(1); + final NetworkCapabilities nc1 = new NetworkCapabilities.Builder() + .addTransportType(TRANSPORT_WIFI) + .setNetworkSpecifier(specifier) + .build(); + assertEquals(specifier, nc1.getNetworkSpecifier()); + try { + final NetworkCapabilities nc2 = new NetworkCapabilities.Builder() + .setNetworkSpecifier(specifier) + .build(); + fail("Must have a single transport type. Without transport type or multiple transport" + + " types is invalid."); + } catch (IllegalStateException expected) { } + } + + @Test + public void testWifiAwareNetworkSpecifier() { + final NetworkCapabilities nc = new NetworkCapabilities() + .addTransportType(TRANSPORT_WIFI_AWARE); + // If NetworkSpecifier is not set, the default value is null. + assertNull(nc.getNetworkSpecifier()); + final WifiAwareNetworkSpecifier specifier = new WifiAwareNetworkSpecifier.Builder( + mDiscoverySession, mPeerHandle).build(); + nc.setNetworkSpecifier(specifier); + assertEquals(specifier, nc.getNetworkSpecifier()); + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testAdministratorUidsAndOwnerUid() { + // Test default owner uid. + // If the owner uid is not set, the default value should be Process.INVALID_UID. + final NetworkCapabilities nc1 = new NetworkCapabilities.Builder().build(); + assertEquals(Process.INVALID_UID, nc1.getOwnerUid()); + // Test setAdministratorUids and getAdministratorUids. + final int[] administratorUids = {1001, 10001}; + final NetworkCapabilities nc2 = new NetworkCapabilities.Builder() + .setAdministratorUids(administratorUids) + .build(); + assertTrue(Arrays.equals(administratorUids, nc2.getAdministratorUids())); + // Test setOwnerUid and getOwnerUid. + // The owner UID must be included in administrator UIDs, or throw IllegalStateException. + try { + final NetworkCapabilities nc3 = new NetworkCapabilities.Builder() + .setOwnerUid(1001) + .build(); + fail("The owner UID must be included in administrator UIDs."); + } catch (IllegalStateException expected) { } + final NetworkCapabilities nc4 = new NetworkCapabilities.Builder() + .setAdministratorUids(administratorUids) + .setOwnerUid(1001) + .build(); + assertEquals(1001, nc4.getOwnerUid()); + try { + final NetworkCapabilities nc5 = new NetworkCapabilities.Builder() + .setAdministratorUids(null) + .build(); + fail("Should not set null into setAdministratorUids"); + } catch (NullPointerException expected) { } + } + + @Test + public void testLinkBandwidthKbps() { + final NetworkCapabilities nc = new NetworkCapabilities(); + // The default value of LinkDown/UpstreamBandwidthKbps should be LINK_BANDWIDTH_UNSPECIFIED. + assertEquals(LINK_BANDWIDTH_UNSPECIFIED, nc.getLinkDownstreamBandwidthKbps()); + assertEquals(LINK_BANDWIDTH_UNSPECIFIED, nc.getLinkUpstreamBandwidthKbps()); + nc.setLinkDownstreamBandwidthKbps(512); + nc.setLinkUpstreamBandwidthKbps(128); + assertEquals(512, nc.getLinkDownstreamBandwidthKbps()); + assertNotEquals(128, nc.getLinkDownstreamBandwidthKbps()); + assertEquals(128, nc.getLinkUpstreamBandwidthKbps()); + assertNotEquals(512, nc.getLinkUpstreamBandwidthKbps()); + } + + @Test + public void testSignalStrength() { + final NetworkCapabilities nc = new NetworkCapabilities(); + // The default value of signal strength should be SIGNAL_STRENGTH_UNSPECIFIED. + assertEquals(SIGNAL_STRENGTH_UNSPECIFIED, nc.getSignalStrength()); + nc.setSignalStrength(-80); + assertEquals(-80, nc.getSignalStrength()); + assertNotEquals(-50, nc.getSignalStrength()); + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testDeduceRestrictedCapability() { + final NetworkCapabilities nc = new NetworkCapabilities(); + // Default capabilities don't have restricted capability. + assertFalse(nc.deduceRestrictedCapability()); + // If there is a force restricted capability, then the network capabilities is restricted. + nc.addCapability(NET_CAPABILITY_OEM_PAID); + nc.addCapability(NET_CAPABILITY_INTERNET); + assertTrue(nc.deduceRestrictedCapability()); + // Except for the force restricted capability, if there is any unrestricted capability in + // capabilities, then the network capabilities is not restricted. + nc.removeCapability(NET_CAPABILITY_OEM_PAID); + nc.addCapability(NET_CAPABILITY_CBS); + assertFalse(nc.deduceRestrictedCapability()); + // Except for the force restricted capability, the network capabilities will only be treated + // as restricted when there is no any unrestricted capability. + nc.removeCapability(NET_CAPABILITY_INTERNET); + assertTrue(nc.deduceRestrictedCapability()); + } + + private void assertNoTransport(NetworkCapabilities nc) { + for (int i = MIN_TRANSPORT; i <= MAX_TRANSPORT; i++) { + assertFalse(nc.hasTransport(i)); + } + } + + // Checks that all transport types from MIN_TRANSPORT to maxTransportType are set and all + // transport types from maxTransportType + 1 to MAX_TRANSPORT are not set when positiveSequence + // is true. If positiveSequence is false, then the check sequence is opposite. + private void checkCurrentTransportTypes(NetworkCapabilities nc, int maxTransportType, + boolean positiveSequence) { + for (int i = MIN_TRANSPORT; i <= maxTransportType; i++) { + if (positiveSequence) { + assertTrue(nc.hasTransport(i)); + } else { + assertFalse(nc.hasTransport(i)); + } + } + for (int i = MAX_TRANSPORT; i > maxTransportType; i--) { + if (positiveSequence) { + assertFalse(nc.hasTransport(i)); + } else { + assertTrue(nc.hasTransport(i)); + } + } + } + + @Test + public void testMultipleTransportTypes() { + final NetworkCapabilities nc = new NetworkCapabilities(); + assertNoTransport(nc); + // Test adding multiple transport types. + for (int i = MIN_TRANSPORT; i <= MAX_TRANSPORT; i++) { + nc.addTransportType(i); + checkCurrentTransportTypes(nc, i, true /* positiveSequence */); + } + // Test removing multiple transport types. + for (int i = MIN_TRANSPORT; i <= MAX_TRANSPORT; i++) { + nc.removeTransportType(i); + checkCurrentTransportTypes(nc, i, false /* positiveSequence */); + } + assertNoTransport(nc); + nc.addTransportType(TRANSPORT_WIFI); + assertTrue(nc.hasTransport(TRANSPORT_WIFI)); + assertFalse(nc.hasTransport(TRANSPORT_VPN)); + nc.addTransportType(TRANSPORT_VPN); + assertTrue(nc.hasTransport(TRANSPORT_WIFI)); + assertTrue(nc.hasTransport(TRANSPORT_VPN)); + nc.removeTransportType(TRANSPORT_WIFI); + assertFalse(nc.hasTransport(TRANSPORT_WIFI)); + assertTrue(nc.hasTransport(TRANSPORT_VPN)); + nc.removeTransportType(TRANSPORT_VPN); + assertFalse(nc.hasTransport(TRANSPORT_WIFI)); + assertFalse(nc.hasTransport(TRANSPORT_VPN)); + assertNoTransport(nc); + } + + @Test + public void testAddAndRemoveTransportType() { + final NetworkCapabilities nc = new NetworkCapabilities(); + try { + nc.addTransportType(-1); + fail("Should not set invalid transport type into addTransportType"); + } catch (IllegalArgumentException expected) { } + try { + nc.removeTransportType(-1); + fail("Should not set invalid transport type into removeTransportType"); + } catch (IllegalArgumentException e) { } + } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testBuilder() { + final int ownerUid = 1001; + final int signalStrength = -80; + final int requestUid = 10100; + final int[] administratorUids = {ownerUid, 10001}; + final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier(1); + final String ssid = "TEST_SSID"; + final String packageName = "com.google.test.networkcapabilities"; + final NetworkCapabilities nc = new NetworkCapabilities.Builder() + .addTransportType(TRANSPORT_WIFI) + .addTransportType(TRANSPORT_CELLULAR) + .removeTransportType(TRANSPORT_CELLULAR) + .addCapability(NET_CAPABILITY_EIMS) + .addCapability(NET_CAPABILITY_CBS) + .removeCapability(NET_CAPABILITY_CBS) + .setAdministratorUids(administratorUids) + .setOwnerUid(ownerUid) + .setLinkDownstreamBandwidthKbps(512) + .setLinkUpstreamBandwidthKbps(128) + .setNetworkSpecifier(specifier) + .setTransportInfo(null) + .setSignalStrength(signalStrength) + .setSsid(ssid) + .setRequestorUid(requestUid) + .setRequestorPackageName(packageName) + .build(); + assertEquals(1, nc.getTransportTypes().length); + assertEquals(TRANSPORT_WIFI, nc.getTransportTypes()[0]); + assertTrue(nc.hasCapability(NET_CAPABILITY_EIMS)); + assertFalse(nc.hasCapability(NET_CAPABILITY_CBS)); + assertTrue(Arrays.equals(administratorUids, nc.getAdministratorUids())); + assertEquals(ownerUid, nc.getOwnerUid()); + assertEquals(512, nc.getLinkDownstreamBandwidthKbps()); + assertNotEquals(128, nc.getLinkDownstreamBandwidthKbps()); + assertEquals(128, nc.getLinkUpstreamBandwidthKbps()); + assertNotEquals(512, nc.getLinkUpstreamBandwidthKbps()); + assertEquals(specifier, nc.getNetworkSpecifier()); + assertNull(nc.getTransportInfo()); + assertEquals(signalStrength, nc.getSignalStrength()); + assertNotEquals(-50, nc.getSignalStrength()); + assertEquals(ssid, nc.getSsid()); + assertEquals(requestUid, nc.getRequestorUid()); + assertEquals(packageName, nc.getRequestorPackageName()); + // Cannot assign null into NetworkCapabilities.Builder + try { + final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder(null); + fail("Should not set null into NetworkCapabilities.Builder"); + } catch (NullPointerException expected) { } + assertEquals(nc, new NetworkCapabilities.Builder(nc).build()); + } } From ec5e7af9777088c746a87dea47550cd5ccedf040 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Wed, 8 Apr 2020 14:54:06 +0800 Subject: [PATCH 161/229] Set WifiAwareNetworkInfo into setTransportInfo() Bug: 139268426 Bug: 135998869 Bug: 138306002 Test: atest CtsNetTestCasesLatestSdk:NetworkCapabilitiesTest Change-Id: Ibbe1cd126d6538003fbb1e5e85892bfb15a920e8 --- .../java/android/net/NetworkCapabilitiesTest.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index 12d80fc2c0..3f8261d5ad 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -875,6 +875,11 @@ public class NetworkCapabilitiesTest { } catch (IllegalArgumentException e) { } } + private class TestTransportInfo implements TransportInfo { + TestTransportInfo() { + } + } + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testBuilder() { final int ownerUid = 1001; @@ -882,6 +887,7 @@ public class NetworkCapabilitiesTest { final int requestUid = 10100; final int[] administratorUids = {ownerUid, 10001}; final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier(1); + final TestTransportInfo transportInfo = new TestTransportInfo(); final String ssid = "TEST_SSID"; final String packageName = "com.google.test.networkcapabilities"; final NetworkCapabilities nc = new NetworkCapabilities.Builder() @@ -896,7 +902,7 @@ public class NetworkCapabilitiesTest { .setLinkDownstreamBandwidthKbps(512) .setLinkUpstreamBandwidthKbps(128) .setNetworkSpecifier(specifier) - .setTransportInfo(null) + .setTransportInfo(transportInfo) .setSignalStrength(signalStrength) .setSsid(ssid) .setRequestorUid(requestUid) @@ -913,7 +919,7 @@ public class NetworkCapabilitiesTest { assertEquals(128, nc.getLinkUpstreamBandwidthKbps()); assertNotEquals(512, nc.getLinkUpstreamBandwidthKbps()); assertEquals(specifier, nc.getNetworkSpecifier()); - assertNull(nc.getTransportInfo()); + assertEquals(transportInfo, nc.getTransportInfo()); assertEquals(signalStrength, nc.getSignalStrength()); assertNotEquals(-50, nc.getSignalStrength()); assertEquals(ssid, nc.getSsid()); From 09d50fe69d368feced7a4c76283a8159dcff4c24 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 7 Apr 2020 13:21:46 +0800 Subject: [PATCH 162/229] [SP27.3] Rename TestableNetworkStatsProvider Currently, TestableNetworkStatsProvider is a subclass of INetworkStatsProvider. This is not very accurate naming after API council review feedback since now we have NetworkStatsProvider as a system api interface. This is the counter-part change of actual renaming CL in NetworkStack. Test: atest FrameworksNetTests TetheringTests Bug: 150643374 Change-Id: Ifa8175dc4e2fe2b907ec13b3bd2eca12974f5ea7 --- .../com/android/server/net/NetworkStatsServiceTest.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index 6e6331312e..1db90b71e2 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -109,7 +109,7 @@ import com.android.internal.util.test.BroadcastInterceptingContext; import com.android.server.net.NetworkStatsService.NetworkStatsSettings; import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config; import com.android.testutils.HandlerUtilsKt; -import com.android.testutils.TestableNetworkStatsProvider; +import com.android.testutils.TestableNetworkStatsProviderBinder; import libcore.io.IoUtils; @@ -1118,7 +1118,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { expectNetworkStatsUidDetail(buildEmptyStats()); // Register custom provider and retrieve callback. - final TestableNetworkStatsProvider provider = new TestableNetworkStatsProvider(); + final TestableNetworkStatsProviderBinder provider = + new TestableNetworkStatsProviderBinder(); final INetworkStatsProviderCallback cb = mService.registerNetworkStatsProvider("TEST", provider); assertNotNull(cb); @@ -1176,7 +1177,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]); // Register custom provider and retrieve callback. - final TestableNetworkStatsProvider provider = new TestableNetworkStatsProvider(); + final TestableNetworkStatsProviderBinder provider = + new TestableNetworkStatsProviderBinder(); final INetworkStatsProviderCallback cb = mService.registerNetworkStatsProvider("TEST", provider); assertNotNull(cb); From b9db69f623b9615b141528bbc0eaaef3bc64dcc0 Mon Sep 17 00:00:00 2001 From: Treehugger Robot Date: Fri, 10 Apr 2020 19:11:51 +0000 Subject: [PATCH 163/229] Fix a theoretical NPE Test: NetworkAgentTests Bug: 153718627 Change-Id: I955b6dac6de48b12696dc640f131f5983ac552df Merged-In: I08f57cce0cd85d5cd66e9a0ef948224290e9200e (cherry picked from commit 31492c708746a51f70c74913a4d6cd97bf06ae63, aosp/1284575) --- core/java/android/net/NetworkAgent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index e9bcefef50..31d7d08209 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -812,7 +812,7 @@ public abstract class NetworkAgent { * this is the destination the probes are being redirected to, otherwise {@code null}. */ public void onValidationStatus(@ValidationStatus int status, @Nullable Uri redirectUri) { - networkStatus(status, redirectUri.toString()); + networkStatus(status, null == redirectUri ? "" : redirectUri.toString()); } /** @hide TODO delete once subclasses have moved to onValidationStatus */ protected void networkStatus(int status, String redirectUrl) { From db2aad69edb0de75a1150d236824c7060e8f61a8 Mon Sep 17 00:00:00 2001 From: chenbruce Date: Thu, 20 Feb 2020 14:28:31 +0800 Subject: [PATCH 164/229] Set transport types to resolver For a given network, resolver doesn't know what transport types are. Therefore, when a new network is created or transport types are changed in a give network, transport types will be updated and sent by calling setResolverConfiguration(). In the same time, if link properties or transport types are null, setResolverConfiguration() won't be called. The original behaviors of setResolverConfiguration() aren't changed. Only increasing one new behavior that when a given network has transport type change, calling setResolverConfiguration() directly and resolver updates the transport types for that given network. Bug: 143732914 Test: atest FrameworksNetTests atest FrameworksNetIntegrationTests Change-Id: I6527cde0e177ba08c886576131b35fc769c2bb53 --- .../android/server/ConnectivityService.java | 14 ++- .../server/connectivity/DnsManager.java | 59 +++++++-- .../server/ConnectivityServiceTest.java | 23 ++++ .../server/connectivity/DnsManagerTest.java | 112 ++++++++++++++++-- 4 files changed, 186 insertions(+), 22 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 8a1de1f076..51427c191a 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3339,6 +3339,8 @@ public class ConnectivityService extends IConnectivityManager.Stub getNetworkPermission(networkAgent.networkCapabilities)); } mDnsResolver.createNetworkCache(networkAgent.network.netId); + mDnsManager.updateTransportsForNetwork(networkAgent.network.netId, + networkAgent.networkCapabilities.getTransportTypes()); return true; } catch (RemoteException | ServiceSpecificException e) { loge("Error creating network " + networkAgent.network.netId + ": " @@ -6088,7 +6090,13 @@ public class ConnectivityService extends IConnectivityManager.Stub log("Setting DNS servers for network " + netId + " to " + dnses); } try { - mDnsManager.setDnsConfigurationForNetwork(netId, newLp, isDefaultNetwork); + mDnsManager.noteDnsServersForNetwork(netId, newLp); + // TODO: netd should listen on [::1]:53 and proxy queries to the current + // default network, and we should just set net.dns1 to ::1, not least + // because applications attempting to use net.dns resolvers will bypass + // the privacy protections of things like DNS-over-TLS. + if (isDefaultNetwork) mDnsManager.setDefaultDnsSystemProperties(newLp.getDnsServers()); + mDnsManager.flushVmDnsCache(); } catch (Exception e) { loge("Exception in setDnsConfigurationForNetwork: " + e); } @@ -6286,6 +6294,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // bubble those changes through. updateAllVpnsCapabilities(); } + + if (!newNc.equalsTransportTypes(prevNc)) { + mDnsManager.updateTransportsForNetwork(nai.network.netId, newNc.getTransportTypes()); + } } /** diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java index 5250a771d7..506c8e3919 100644 --- a/services/core/java/com/android/server/connectivity/DnsManager.java +++ b/services/core/java/com/android/server/connectivity/DnsManager.java @@ -27,6 +27,7 @@ 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; import android.content.Context; import android.content.Intent; @@ -34,6 +35,7 @@ import android.net.IDnsResolver; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkUtils; +import android.net.ResolverOptionsParcel; import android.net.ResolverParamsParcel; import android.net.Uri; import android.net.shared.PrivateDnsConfig; @@ -237,6 +239,8 @@ public class DnsManager { // TODO: Replace these Maps with SparseArrays. private final Map mPrivateDnsMap; private final Map mPrivateDnsValidationMap; + private final Map mLinkPropertiesMap; + private final Map mTransportsMap; private int mNumDnsEntries; private int mSampleValidity; @@ -253,6 +257,8 @@ public class DnsManager { mSystemProperties = sp; mPrivateDnsMap = new HashMap<>(); mPrivateDnsValidationMap = new HashMap<>(); + mLinkPropertiesMap = new HashMap<>(); + mTransportsMap = new HashMap<>(); // TODO: Create and register ContentObservers to track every setting // used herein, posting messages to respond to changes. @@ -265,6 +271,8 @@ public class DnsManager { public void removeNetwork(Network network) { mPrivateDnsMap.remove(network.netId); mPrivateDnsValidationMap.remove(network.netId); + mTransportsMap.remove(network.netId); + mLinkPropertiesMap.remove(network.netId); } public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) { @@ -304,9 +312,35 @@ public class DnsManager { statuses.updateStatus(update); } - public void setDnsConfigurationForNetwork( - int netId, LinkProperties lp, boolean isDefaultNetwork) { + /** + * When creating a new network or transport types are changed in a specific network, + * transport types are always saved to a hashMap before update dns config. + * When destroying network, the specific network will be removed from the hashMap. + * The hashMap is always accessed on the same thread. + */ + public void updateTransportsForNetwork(int netId, @NonNull int[] transportTypes) { + mTransportsMap.put(netId, transportTypes); + sendDnsConfigurationForNetwork(netId); + } + /** + * When {@link LinkProperties} are changed in a specific network, they are + * always saved to a hashMap before update dns config. + * When destroying network, the specific network will be removed from the hashMap. + * The hashMap is always accessed on the same thread. + */ + public void noteDnsServersForNetwork(int netId, @NonNull LinkProperties lp) { + mLinkPropertiesMap.put(netId, lp); + sendDnsConfigurationForNetwork(netId); + } + + /** + * Send dns configuration parameters to resolver for a given network. + */ + public void sendDnsConfigurationForNetwork(int netId) { + final LinkProperties lp = mLinkPropertiesMap.get(netId); + final int[] transportTypes = mTransportsMap.get(netId); + if (lp == null || transportTypes == null) return; updateParametersSettings(); final ResolverParamsParcel paramsParcel = new ResolverParamsParcel(); @@ -319,15 +353,16 @@ public class DnsManager { // networks like IMS. final PrivateDnsConfig privateDnsCfg = mPrivateDnsMap.getOrDefault(netId, PRIVATE_DNS_OFF); - final boolean useTls = privateDnsCfg.useTls; final boolean strictMode = privateDnsCfg.inStrictMode(); + paramsParcel.netId = netId; paramsParcel.sampleValiditySeconds = mSampleValidity; paramsParcel.successThreshold = mSuccessThreshold; paramsParcel.minSamples = mMinSamples; paramsParcel.maxSamples = mMaxSamples; - paramsParcel.servers = NetworkUtils.makeStrings(lp.getDnsServers()); + paramsParcel.servers = + NetworkUtils.makeStrings(lp.getDnsServers()); paramsParcel.domains = getDomainStrings(lp.getDomains()); paramsParcel.tlsName = strictMode ? privateDnsCfg.hostname : ""; paramsParcel.tlsServers = @@ -337,6 +372,8 @@ public class DnsManager { .collect(Collectors.toList())) : useTls ? paramsParcel.servers // Opportunistic : new String[0]; // Off + paramsParcel.resolverOptions = new ResolverOptionsParcel(); + paramsParcel.transportTypes = transportTypes; // Prepare to track the validation status of the DNS servers in the // resolver config when private DNS is in opportunistic or strict mode. if (useTls) { @@ -349,7 +386,7 @@ public class DnsManager { mPrivateDnsValidationMap.remove(netId); } - Slog.d(TAG, String.format("setDnsConfigurationForNetwork(%d, %s, %s, %d, %d, %d, %d, " + Slog.d(TAG, String.format("sendDnsConfigurationForNetwork(%d, %s, %s, %d, %d, %d, %d, " + "%d, %d, %s, %s)", paramsParcel.netId, Arrays.toString(paramsParcel.servers), Arrays.toString(paramsParcel.domains), paramsParcel.sampleValiditySeconds, paramsParcel.successThreshold, paramsParcel.minSamples, @@ -363,13 +400,6 @@ public class DnsManager { Slog.e(TAG, "Error setting DNS configuration: " + e); return; } - - // TODO: netd should listen on [::1]:53 and proxy queries to the current - // default network, and we should just set net.dns1 to ::1, not least - // because applications attempting to use net.dns resolvers will bypass - // the privacy protections of things like DNS-over-TLS. - if (isDefaultNetwork) setDefaultDnsSystemProperties(lp.getDnsServers()); - flushVmDnsCache(); } public void setDefaultDnsSystemProperties(Collection dnses) { @@ -384,7 +414,10 @@ public class DnsManager { mNumDnsEntries = last; } - private void flushVmDnsCache() { + /** + * Flush DNS caches and events work before boot has completed. + */ + public void flushVmDnsCache() { /* * Tell the VMs to toss their DNS caches */ diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 912a27f08f..b864e37f9e 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -4907,6 +4907,29 @@ public class ConnectivityServiceTest { reset(mMockDnsResolver); } + @Test + public void testDnsConfigurationTransTypesPushed() throws Exception { + // Clear any interactions that occur as a result of CS starting up. + reset(mMockDnsResolver); + + final NetworkRequest request = new NetworkRequest.Builder() + .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET) + .build(); + final TestNetworkCallback callback = new TestNetworkCallback(); + mCm.registerNetworkCallback(request, callback); + + mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); + mWiFiNetworkAgent.connect(false); + callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + verify(mMockDnsResolver, times(1)).createNetworkCache( + eq(mWiFiNetworkAgent.getNetwork().netId)); + verify(mMockDnsResolver, times(2)).setResolverConfiguration( + mResolverParamsParcelCaptor.capture()); + final ResolverParamsParcel resolverParams = mResolverParamsParcelCaptor.getValue(); + assertContainsExactly(resolverParams.transportTypes, TRANSPORT_WIFI); + reset(mMockDnsResolver); + } + @Test public void testPrivateDnsNotification() throws Exception { NetworkRequest request = new NetworkRequest.Builder() diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java index 8fa0ab979a..a392ae3f13 100644 --- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java @@ -18,22 +18,34 @@ package com.android.server.connectivity; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; +import static android.net.NetworkCapabilities.TRANSPORT_VPN; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI; 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.MiscAssertsKt.assertContainsExactly; +import static com.android.testutils.MiscAssertsKt.assertContainsStringsExactly; +import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.annotation.NonNull; import android.content.Context; import android.net.IDnsResolver; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; +import android.net.ResolverOptionsParcel; +import android.net.ResolverParamsParcel; import android.net.RouteInfo; import android.net.shared.PrivateDnsConfig; import android.provider.Settings; @@ -47,6 +59,7 @@ import com.android.internal.util.test.FakeSettingsProvider; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -66,8 +79,11 @@ public class DnsManagerTest { static final int TEST_NETID = 100; static final int TEST_NETID_ALTERNATE = 101; static final int TEST_NETID_UNTRACKED = 102; - final boolean IS_DEFAULT = true; - final boolean NOT_DEFAULT = false; + static final int TEST_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800; + static final int TEST_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25; + static final int TEST_DEFAULT_MIN_SAMPLES = 8; + static final int TEST_DEFAULT_MAX_SAMPLES = 64; + static final int[] TEST_TRANSPORT_TYPES = {TRANSPORT_WIFI, TRANSPORT_VPN}; DnsManager mDnsManager; MockContentResolver mContentResolver; @@ -76,6 +92,35 @@ public class DnsManagerTest { @Mock IDnsResolver mMockDnsResolver; @Mock MockableSystemProperties mSystemProperties; + private void assertResolverOptionsEquals( + @NonNull ResolverOptionsParcel actual, + @NonNull ResolverOptionsParcel expected) { + assertEquals(actual.hosts, expected.hosts); + assertEquals(actual.tcMode, expected.tcMode); + assertFieldCountEquals(2, ResolverOptionsParcel.class); + } + + private void assertResolverParamsEquals(@NonNull ResolverParamsParcel actual, + @NonNull ResolverParamsParcel expected) { + assertEquals(actual.netId, expected.netId); + assertEquals(actual.sampleValiditySeconds, expected.sampleValiditySeconds); + assertEquals(actual.successThreshold, expected.successThreshold); + assertEquals(actual.minSamples, expected.minSamples); + assertEquals(actual.maxSamples, expected.maxSamples); + assertEquals(actual.baseTimeoutMsec, expected.baseTimeoutMsec); + assertEquals(actual.retryCount, expected.retryCount); + assertContainsStringsExactly(actual.servers, expected.servers); + assertContainsStringsExactly(actual.domains, expected.domains); + assertEquals(actual.tlsName, expected.tlsName); + assertContainsStringsExactly(actual.tlsServers, expected.tlsServers); + assertContainsStringsExactly(actual.tlsFingerprints, expected.tlsFingerprints); + assertEquals(actual.caCertificate, expected.caCertificate); + assertEquals(actual.tlsConnectTimeoutMs, expected.tlsConnectTimeoutMs); + assertResolverOptionsEquals(actual.resolverOptions, expected.resolverOptions); + assertContainsExactly(actual.transportTypes, expected.transportTypes); + assertFieldCountEquals(16, ResolverParamsParcel.class); + } + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -103,8 +148,13 @@ public class DnsManagerTest { lp.addDnsServer(InetAddress.getByName("4.4.4.4")); // Send a validation event that is tracked on the alternate netId - mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT); - mDnsManager.setDnsConfigurationForNetwork(TEST_NETID_ALTERNATE, lp, NOT_DEFAULT); + mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES); + mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); + mDnsManager.setDefaultDnsSystemProperties(lp.getDnsServers()); + mDnsManager.flushVmDnsCache(); + mDnsManager.updateTransportsForNetwork(TEST_NETID_ALTERNATE, TEST_TRANSPORT_TYPES); + mDnsManager.noteDnsServersForNetwork(TEST_NETID_ALTERNATE, lp); + mDnsManager.flushVmDnsCache(); mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID_ALTERNATE, InetAddress.parseNumericAddress("4.4.4.4"), "", true)); @@ -135,7 +185,10 @@ public class DnsManagerTest { InetAddress.parseNumericAddress("6.6.6.6"), InetAddress.parseNumericAddress("2001:db8:66:66::1") })); - mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT); + mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES); + mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); + mDnsManager.setDefaultDnsSystemProperties(lp.getDnsServers()); + mDnsManager.flushVmDnsCache(); fixedLp = new LinkProperties(lp); mDnsManager.updatePrivateDnsStatus(TEST_NETID, fixedLp); assertTrue(fixedLp.isPrivateDnsActive()); @@ -168,7 +221,10 @@ public class DnsManagerTest { // be tracked. LinkProperties lp = new LinkProperties(); lp.addDnsServer(InetAddress.getByName("3.3.3.3")); - mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT); + mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES); + mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); + mDnsManager.setDefaultDnsSystemProperties(lp.getDnsServers()); + mDnsManager.flushVmDnsCache(); mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, InetAddress.parseNumericAddress("3.3.3.3"), "", true)); @@ -179,7 +235,10 @@ public class DnsManagerTest { // Validation event has untracked netId mDnsManager.updatePrivateDns(new Network(TEST_NETID), mDnsManager.getPrivateDnsConfig()); - mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT); + mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES); + mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); + mDnsManager.setDefaultDnsSystemProperties(lp.getDnsServers()); + mDnsManager.flushVmDnsCache(); mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID_UNTRACKED, InetAddress.parseNumericAddress("3.3.3.3"), "", true)); @@ -225,7 +284,10 @@ public class DnsManagerTest { Settings.Global.putString(mContentResolver, PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_OFF); mDnsManager.updatePrivateDns(new Network(TEST_NETID), mDnsManager.getPrivateDnsConfig()); - mDnsManager.setDnsConfigurationForNetwork(TEST_NETID, lp, IS_DEFAULT); + mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES); + mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); + mDnsManager.setDefaultDnsSystemProperties(lp.getDnsServers()); + mDnsManager.flushVmDnsCache(); mDnsManager.updatePrivateDnsValidation( new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, InetAddress.parseNumericAddress("3.3.3.3"), "", true)); @@ -258,4 +320,38 @@ public class DnsManagerTest { assertEquals("strictmode.com", cfgStrict.hostname); assertEquals(new InetAddress[0], cfgStrict.ips); } + + @Test + public void testSendDnsConfiguration() throws Exception { + reset(mMockDnsResolver); + mDnsManager.updatePrivateDns(new Network(TEST_NETID), + mDnsManager.getPrivateDnsConfig()); + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName(TEST_IFACENAME); + lp.addDnsServer(InetAddress.getByName("3.3.3.3")); + lp.addDnsServer(InetAddress.getByName("4.4.4.4")); + mDnsManager.updateTransportsForNetwork(TEST_NETID, TEST_TRANSPORT_TYPES); + mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); + mDnsManager.setDefaultDnsSystemProperties(lp.getDnsServers()); + mDnsManager.flushVmDnsCache(); + + final ArgumentCaptor resolverParamsParcelCaptor = + ArgumentCaptor.forClass(ResolverParamsParcel.class); + verify(mMockDnsResolver, times(1)).setResolverConfiguration( + resolverParamsParcelCaptor.capture()); + final ResolverParamsParcel actualParams = resolverParamsParcelCaptor.getValue(); + final ResolverParamsParcel expectedParams = new ResolverParamsParcel(); + expectedParams.netId = TEST_NETID; + expectedParams.sampleValiditySeconds = TEST_DEFAULT_SAMPLE_VALIDITY_SECONDS; + expectedParams.successThreshold = TEST_DEFAULT_SUCCESS_THRESHOLD_PERCENT; + expectedParams.minSamples = TEST_DEFAULT_MIN_SAMPLES; + expectedParams.maxSamples = TEST_DEFAULT_MAX_SAMPLES; + expectedParams.servers = new String[]{"3.3.3.3", "4.4.4.4"}; + expectedParams.domains = new String[]{}; + expectedParams.tlsName = ""; + expectedParams.tlsServers = new String[]{"3.3.3.3", "4.4.4.4"}; + expectedParams.transportTypes = TEST_TRANSPORT_TYPES; + expectedParams.resolverOptions = new ResolverOptionsParcel(); + assertResolverParamsEquals(actualParams, expectedParams); + } } From 3acd429ba38322873ea82e04a02a92ea55cd0029 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Mon, 13 Apr 2020 09:33:03 +0000 Subject: [PATCH 165/229] Move CaptivePortalDataTest to common test to support cts Commit has to on top of aosp/1281921 to skip whole test in Q device since CaptivePortalData class is introduced in R. Result in Q will be: [1/1] android.net.CaptivePortalDataTest#skippedClassForDevSdkMismatch: IGNORED Bug: 152280218 Bug: 150640683 Test: atest CtsNetTestCasesLatestSdk:CaptivePortalDataTest on both Q and R device Merged-In: Iddd00e1c85abe767b1a41a1761d3266ba322dba6 Change-Id: Iddd00e1c85abe767b1a41a1761d3266ba322dba6 --- .../{ => common}/java/android/net/CaptivePortalDataTest.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) rename tests/net/{ => common}/java/android/net/CaptivePortalDataTest.kt (93%) diff --git a/tests/net/java/android/net/CaptivePortalDataTest.kt b/tests/net/common/java/android/net/CaptivePortalDataTest.kt similarity index 93% rename from tests/net/java/android/net/CaptivePortalDataTest.kt rename to tests/net/common/java/android/net/CaptivePortalDataTest.kt index 0071438268..51068c2c57 100644 --- a/tests/net/java/android/net/CaptivePortalDataTest.kt +++ b/tests/net/common/java/android/net/CaptivePortalDataTest.kt @@ -16,17 +16,20 @@ package android.net +import android.os.Build import androidx.test.filters.SmallTest -import androidx.test.runner.AndroidJUnit4 import com.android.testutils.assertParcelSane import com.android.testutils.assertParcelingIsLossless +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo +import com.android.testutils.DevSdkIgnoreRunner import org.junit.Test import org.junit.runner.RunWith import kotlin.test.assertEquals import kotlin.test.assertNotEquals @SmallTest -@RunWith(AndroidJUnit4::class) +@RunWith(DevSdkIgnoreRunner::class) +@IgnoreUpTo(Build.VERSION_CODES.Q) class CaptivePortalDataTest { private val data = CaptivePortalData.Builder() .setRefreshTime(123L) From 424cced078624b53faafca3baf72f0c107b21405 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Mon, 13 Apr 2020 10:57:24 +0000 Subject: [PATCH 166/229] Add more tests for CaptivePortalData Add missing tests to cover all system APIs Bug: 152280218 Bug: 150640683 Test: atest CtsNetTestCasesLatestSdk:CaptivePortalDataTest on both Q and R device Change-Id: I6d3826922f16816d5b18ed3540266442a0ed3e49 Merged-In: I6d3826922f16816d5b18ed3540266442a0ed3e49 (cherry picked from commit d9f9bf34637f699608fa3b919b3c85f3d5514a83) --- .../java/android/net/CaptivePortalDataTest.kt | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/net/common/java/android/net/CaptivePortalDataTest.kt b/tests/net/common/java/android/net/CaptivePortalDataTest.kt index 51068c2c57..bd1847b7c4 100644 --- a/tests/net/common/java/android/net/CaptivePortalDataTest.kt +++ b/tests/net/common/java/android/net/CaptivePortalDataTest.kt @@ -22,6 +22,8 @@ import com.android.testutils.assertParcelSane import com.android.testutils.assertParcelingIsLossless import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo import com.android.testutils.DevSdkIgnoreRunner +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue import org.junit.Test import org.junit.runner.RunWith import kotlin.test.assertEquals @@ -66,6 +68,46 @@ class CaptivePortalDataTest { assertNotEqualsAfterChange { it.setCaptive(false) } } + @Test + fun testUserPortalUrl() { + assertEquals(Uri.parse("https://portal.example.com/test"), data.userPortalUrl) + } + + @Test + fun testVenueInfoUrl() { + assertEquals(Uri.parse("https://venue.example.com/test"), data.venueInfoUrl) + } + + @Test + fun testIsSessionExtendable() { + assertTrue(data.isSessionExtendable) + } + + @Test + fun testByteLimit() { + assertEquals(456L, data.byteLimit) + // Test byteLimit unset. + assertEquals(-1L, CaptivePortalData.Builder(null).build().byteLimit) + } + + @Test + fun testRefreshTimeMillis() { + assertEquals(123L, data.refreshTimeMillis) + } + + @Test + fun testExpiryTimeMillis() { + assertEquals(789L, data.expiryTimeMillis) + // Test expiryTimeMillis unset. + assertEquals(-1L, CaptivePortalData.Builder(null).build().expiryTimeMillis) + } + + @Test + fun testIsCaptive() { + assertTrue(data.isCaptive) + assertFalse(makeBuilder().setCaptive(false).build().isCaptive) + } + private fun CaptivePortalData.mutate(mutator: (CaptivePortalData.Builder) -> Unit) = CaptivePortalData.Builder(this).apply { mutator(this) }.build() From e770137062f8f720285b6da4824da55cd40ffcf2 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Mon, 13 Apr 2020 16:09:41 +0000 Subject: [PATCH 167/229] Add instrumentation to test NetworkAgent. Test: NetworkAgentTest, new tests using this API Bug: 139268426 Change-Id: I0b65be788bb742fd1a8c0ca624e97368462f9b6a Merged-In: Ia83b1c896df63bb18e2aa4b74d6cc09eba990eb5 (cherry picked from commit d89dcb9765b9c73c950661faaf8af9b795934acb, aosp/1284574) --- core/java/android/net/NetworkAgent.java | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 31d7d08209..65e772cb5e 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -25,12 +25,14 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.Build; import android.os.Bundle; +import android.os.ConditionVariable; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; @@ -571,6 +573,37 @@ public abstract class NetworkAgent { return mNetwork; } + /** + * Register this network agent with a testing harness. + * + * The returned Messenger sends messages to the Handler. This allows a test to send + * this object {@code CMD_*} messages as if they came from ConnectivityService, which + * is useful for testing the behavior. + * + * @hide + */ + public Messenger registerForTest(final Network network) { + log("Registering NetworkAgent for test"); + synchronized (mRegisterLock) { + mNetwork = network; + mInitialConfiguration = null; + } + return new Messenger(mHandler); + } + + /** + * Waits for the handler to be idle. + * This is useful for testing, and has smaller scope than an accessor to mHandler. + * TODO : move the implementation in common library with the tests + * @hide + */ + @VisibleForTesting + public boolean waitForIdle(final long timeoutMs) { + final ConditionVariable cv = new ConditionVariable(false); + mHandler.post(cv::open); + return cv.block(timeoutMs); + } + /** * @return The Network associated with this agent, or null if it's not registered yet. */ From 0e9a7738d0cd961c853f9ca1cc85334c9caa7458 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Mon, 13 Apr 2020 19:10:13 +0000 Subject: [PATCH 168/229] Allow testing of signal strength - Let any process with NETWORK_SETTINGS register for signal strength wakeup. - Allow agents registering test networks to assign them a signal strength. Test: NetworkAgentTest Bug: 139268426 Change-Id: Iebfeb9316bcbd8472459c517abb16f1f9d879871 Merged-In: I2b4b89be3e69f4853fd6978d2c8f5c8eb4271f21 (cherry picked from commit 5cc7b18fe7fa94ce2e30572c476df445ed337741, aosp/1284585) --- core/java/android/net/NetworkCapabilities.java | 2 ++ services/core/java/com/android/server/ConnectivityService.java | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 73c6b3daf2..52d6fdfbd5 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -680,11 +680,13 @@ public final class NetworkCapabilities implements Parcelable { public void restrictCapabilitesForTestNetwork() { final long originalCapabilities = mNetworkCapabilities; final NetworkSpecifier originalSpecifier = mNetworkSpecifier; + final int originalSignalStrength = mSignalStrength; clearAll(); // Reset the transports to only contain TRANSPORT_TEST. mTransportTypes = (1 << TRANSPORT_TEST); mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES; mNetworkSpecifier = originalSpecifier; + mSignalStrength = originalSignalStrength; } /** diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 51427c191a..1a58d6047b 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2151,7 +2151,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private boolean checkNetworkSignalStrengthWakeupPermission(int pid, int uid) { return checkAnyPermissionOf(pid, uid, android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP, - NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, + android.Manifest.permission.NETWORK_SETTINGS); } private void enforceConnectivityRestrictedNetworksPermission() { From c6081f9c50c5f8d8edc195ddffdc9e90ee32e8ec Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 4 Mar 2020 12:58:00 +0800 Subject: [PATCH 169/229] [SM10] Adopt helper class to monitor RAT type change per sub Test: atest NetworkStatsServiceTest Bug: 146415925 Change-Id: I45c3aa9046b316c8cd0943543d620a22e4afefd1 Merged-In: I45c3aa9046b316c8cd0943543d620a22e4afefd1 (cherry picked from commit 219faff07bdc58c14fe58fc525e86383db1f8167) --- .../server/net/NetworkStatsServiceTest.java | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index 6e6331312e..c4c6dfddb4 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -60,14 +60,13 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.NonNull; -import android.annotation.Nullable; import android.app.AlarmManager; import android.app.usage.NetworkStatsManager; import android.content.Context; @@ -95,8 +94,6 @@ import android.os.Message; import android.os.Messenger; import android.os.PowerManager; import android.os.SimpleClock; -import android.telephony.PhoneStateListener; -import android.telephony.ServiceState; import android.telephony.TelephonyManager; import androidx.test.InstrumentationRegistry; @@ -126,6 +123,7 @@ import java.io.File; import java.time.Clock; import java.time.ZoneOffset; import java.util.Objects; +import java.util.concurrent.Executor; /** * Tests for {@link NetworkStatsService}. @@ -168,14 +166,13 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { private @Mock NetworkStatsSettings mSettings; private @Mock IBinder mBinder; private @Mock AlarmManager mAlarmManager; - private @Mock TelephonyManager mTelephonyManager; + @Mock + private NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor; private HandlerThread mHandlerThread; private NetworkStatsService mService; private INetworkStatsSession mSession; private INetworkManagementEventObserver mNetworkObserver; - @Nullable - private PhoneStateListener mPhoneStateListener; private final Clock mClock = new SimpleClock(ZoneOffset.UTC) { @Override @@ -203,8 +200,8 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { mHandlerThread = new HandlerThread("HandlerThread"); final NetworkStatsService.Dependencies deps = makeDependencies(); mService = new NetworkStatsService(mServiceContext, mNetManager, mAlarmManager, wakeLock, - mClock, mTelephonyManager, mSettings, - mStatsFactory, new NetworkStatsObservers(), mStatsDir, getBaseDir(mStatsDir), deps); + mClock, mSettings, mStatsFactory, new NetworkStatsObservers(), mStatsDir, + getBaseDir(mStatsDir), deps); mElapsedRealtime = 0L; @@ -224,12 +221,6 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { ArgumentCaptor.forClass(INetworkManagementEventObserver.class); verify(mNetManager).registerObserver(networkObserver.capture()); mNetworkObserver = networkObserver.getValue(); - - // Capture the phone state listener that created by service. - final ArgumentCaptor phoneStateListenerCaptor = - ArgumentCaptor.forClass(PhoneStateListener.class); - verify(mTelephonyManager).listen(phoneStateListenerCaptor.capture(), anyInt()); - mPhoneStateListener = phoneStateListenerCaptor.getValue(); } @NonNull @@ -239,6 +230,14 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { public HandlerThread makeHandlerThread() { return mHandlerThread; } + + @Override + public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor( + @NonNull Context context, @NonNull Executor executor, + @NonNull NetworkStatsService service) { + + return mNetworkStatsSubscriptionsMonitor; + } }; } @@ -678,10 +677,9 @@ public class NetworkStatsServiceTest extends NetworkStatsBaseTest { // TODO: support per IMSI state private void setMobileRatTypeAndWaitForIdle(int ratType) { - final ServiceState mockSs = mock(ServiceState.class); - when(mockSs.getDataNetworkType()).thenReturn(ratType); - mPhoneStateListener.onServiceStateChanged(mockSs); - + when(mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(anyString())) + .thenReturn(ratType); + mService.handleOnCollapsedRatTypeChanged(); HandlerUtilsKt.waitForIdle(mHandlerThread, WAIT_TIMEOUT); } From aa0c7d00cf1e79b4887ac3870af0bd9535176a21 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 16 Apr 2020 16:49:33 +0000 Subject: [PATCH 170/229] Support changing the NAT64 prefix without removing it. This cannot (currently) happen with DNS64 detection, but it can happen with the PREF64 option. Bug: 150648313 Test: atest ConnectivityServiceTest Nat464XlatTest --rerun-until-failure 100 Merged-In: I789fe9d46d3ac5d074ae697d23013f24a9e0246d Change-Id: I789fe9d46d3ac5d074ae697d23013f24a9e0246d --- .../server/connectivity/Nat464Xlat.java | 34 +++++++++++++++---- .../server/ConnectivityServiceTest.java | 25 ++++++++++++-- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index 741cb5b41e..e6b2d2678f 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -81,6 +81,9 @@ public class Nat464Xlat extends BaseNetworkObserver { RUNNING, // start() called, and the stacked iface is known to be up. } + /** NAT64 prefix currently in use. Only valid in STARTING or RUNNING states. */ + private IpPrefix mNat64PrefixInUse; + /** NAT64 prefix (if any) discovered from DNS via RFC 7050. */ private IpPrefix mNat64PrefixFromDns; private String mBaseIface; private String mIface; @@ -178,9 +181,10 @@ public class Nat464Xlat extends BaseNetworkObserver { return; } + mNat64PrefixInUse = getNat64Prefix(); String addrStr = null; try { - addrStr = mNetd.clatdStart(baseIface, getNat64Prefix().toString()); + addrStr = mNetd.clatdStart(baseIface, mNat64PrefixInUse.toString()); } catch (RemoteException | ServiceSpecificException e) { Slog.e(TAG, "Error starting clatd on " + baseIface + ": " + e); } @@ -211,12 +215,13 @@ public class Nat464Xlat extends BaseNetworkObserver { } catch (RemoteException | IllegalStateException e) { Slog.e(TAG, "Error unregistering clatd observer on " + mBaseIface + ": " + e); } + mNat64PrefixInUse = null; mIface = null; mBaseIface = null; if (requiresClat(mNetwork)) { mState = State.DISCOVERING; } else { - stopPrefixDiscovery(); + stopPrefixDiscovery(); // Enters IDLE state. } } @@ -274,19 +279,32 @@ public class Nat464Xlat extends BaseNetworkObserver { private void startPrefixDiscovery() { try { mDnsResolver.startPrefix64Discovery(getNetId()); - mState = State.DISCOVERING; } catch (RemoteException | ServiceSpecificException e) { Slog.e(TAG, "Error starting prefix discovery on netId " + getNetId() + ": " + e); } + mState = State.DISCOVERING; } private void stopPrefixDiscovery() { try { mDnsResolver.stopPrefix64Discovery(getNetId()); - mState = State.IDLE; } catch (RemoteException | ServiceSpecificException e) { Slog.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e); } + mState = State.IDLE; + } + + private void maybeHandleNat64PrefixChange() { + final IpPrefix newPrefix = getNat64Prefix(); + if (!Objects.equals(mNat64PrefixInUse, newPrefix)) { + Slog.d(TAG, "NAT64 prefix changed from " + mNat64PrefixInUse + " to " + + newPrefix); + stop(); + // It's safe to call update here, even though this method is called from update, because + // stop() is guaranteed to have moved out of STARTING and RUNNING, which are the only + // states in which this method can be called. + update(); + } } /** @@ -325,11 +343,11 @@ public class Nat464Xlat extends BaseNetworkObserver { // Stop clatd and go back into DISCOVERING or idle. if (!shouldStartClat(mNetwork)) { stop(); + break; } + // Only necessary while clat is actually started. + maybeHandleNat64PrefixChange(); break; - // TODO: support the NAT64 prefix changing after it's been discovered. There is - // no need to support this at the moment because it cannot happen without - // changes to the Dns64Configuration code in netd. } } @@ -347,6 +365,8 @@ public class Nat464Xlat extends BaseNetworkObserver { * has no idea that 464xlat is running on top of it. */ public void fixupLinkProperties(@NonNull LinkProperties oldLp, @NonNull LinkProperties lp) { + // This must be done even if clatd is not running, because otherwise shouldStartClat would + // never return true. lp.setNat64Prefix(getNat64Prefix()); if (!isRunning()) { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index b864e37f9e..dad0363a80 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -5969,6 +5969,9 @@ public class ConnectivityServiceTest { final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64"); final String kNat64PrefixString = "2001:db8:64:64:64:64::"; final IpPrefix kNat64Prefix = new IpPrefix(InetAddress.getByName(kNat64PrefixString), 96); + final String kOtherNat64PrefixString = "64:ff9b::"; + final IpPrefix kOtherNat64Prefix = new IpPrefix( + InetAddress.getByName(kOtherNat64PrefixString), 96); final RouteInfo defaultRoute = new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME); final RouteInfo ipv6Subnet = new RouteInfo(myIpv6, null, MOBILE_IFNAME); @@ -6082,6 +6085,24 @@ public class ConnectivityServiceTest { } reset(mMockNetd); + // Change the NAT64 prefix without first removing it. + // Expect clatd to be stopped and started with the new prefix. + mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */, + kOtherNat64PrefixString, 96); + networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, + (lp) -> lp.getStackedLinks().size() == 0); + verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME); + assertRoutesRemoved(cellNetId, stackedDefault); + + verify(mMockNetd, times(1)).clatdStart(MOBILE_IFNAME, kOtherNat64Prefix.toString()); + networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, + (lp) -> lp.getNat64Prefix().equals(kOtherNat64Prefix)); + clat.interfaceLinkStateChanged(CLAT_PREFIX + MOBILE_IFNAME, true); + networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, + (lp) -> lp.getStackedLinks().size() == 1); + assertRoutesAdded(cellNetId, stackedDefault); + reset(mMockNetd); + // Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked // linkproperties are cleaned up. cellLp.addLinkAddress(myIpv4); @@ -6096,7 +6117,7 @@ public class ConnectivityServiceTest { networkCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent); LinkProperties actualLpAfterIpv4 = mCm.getLinkProperties(mCellNetworkAgent.getNetwork()); LinkProperties expected = new LinkProperties(cellLp); - expected.setNat64Prefix(kNat64Prefix); + expected.setNat64Prefix(kOtherNat64Prefix); assertEquals(expected, actualLpAfterIpv4); assertEquals(0, actualLpAfterIpv4.getStackedLinks().size()); assertRoutesRemoved(cellNetId, stackedDefault); @@ -6115,7 +6136,7 @@ public class ConnectivityServiceTest { // Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone. mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */, - kNat64PrefixString, 96); + kOtherNat64PrefixString, 96); networkCallback.expectLinkPropertiesThat(mCellNetworkAgent, (lp) -> lp.getNat64Prefix() == null); From 5559f1edd908ade95c8dc2928b4c6f433ac4383e Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Thu, 16 Apr 2020 16:49:56 +0000 Subject: [PATCH 171/229] Add a function to process LinkProperties coming from an agent. There are tasks that need to be performed when receiving LinkProperties directly from a NetworkAgent (either at registration time or in subsequent updates). Currently, the only example of such a task is calling ensureDirectlyConnectedRoutes. This is currently done in handleUpdateLinkProperties, which is often unnecessary, because that method iscalled in many other cases than when receiving properties directly from an agent. Ensuring directly connected routes only needs to be done when receiving LinkProperties from the agent, because ConnectivityService does not directly manipulate routes. This CL does not do much except remove these superfluous calls and add the method. A future CL will add more code to the method. Bug: 150648313 Test: atest ConnectivityServiceTest Merged-In: Ibeeb5f79e8afd3350c935934713d7882f2e0281f Change-Id: Ibeeb5f79e8afd3350c935934713d7882f2e0281f --- .../android/server/ConnectivityService.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 1a58d6047b..001db3bd6a 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2722,7 +2722,9 @@ public class ConnectivityService extends IConnectivityManager.Stub break; } case NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED: { - handleUpdateLinkProperties(nai, (LinkProperties) msg.obj); + LinkProperties newLp = (LinkProperties) msg.obj; + processLinkPropertiesFromAgent(nai, newLp); + handleUpdateLinkProperties(nai, newLp); break; } case NetworkAgent.EVENT_NETWORK_INFO_CHANGED: { @@ -5817,7 +5819,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } LinkProperties lp = new LinkProperties(linkProperties); - lp.ensureDirectlyConnectedRoutes(); + // TODO: Instead of passing mDefaultRequest, provide an API to determine whether a Network // satisfies mDefaultRequest. final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); @@ -5825,8 +5827,11 @@ public class ConnectivityService extends IConnectivityManager.Stub new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), this, mNetd, mDnsResolver, mNMS, providerId); - // Make sure the network capabilities reflect what the agent info says. + + // Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says. nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); + processLinkPropertiesFromAgent(nai, nai.linkProperties); + final String extraInfo = networkInfo.getExtraInfo(); final String name = TextUtils.isEmpty(extraInfo) ? nai.networkCapabilities.getSsid() : extraInfo; @@ -5864,6 +5869,10 @@ public class ConnectivityService extends IConnectivityManager.Stub updateUids(nai, null, nai.networkCapabilities); } + private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) { + lp.ensureDirectlyConnectedRoutes(); + } + private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties newLp, @NonNull LinkProperties oldLp) { int netId = networkAgent.network.netId; @@ -6391,13 +6400,13 @@ public class ConnectivityService extends IConnectivityManager.Stub // Ignore updates for disconnected networks return; } - // newLp is already a defensive copy. - newLp.ensureDirectlyConnectedRoutes(); if (VDBG || DDBG) { log("Update of LinkProperties for " + nai.toShortString() + "; created=" + nai.created + "; everConnected=" + nai.everConnected); } + // TODO: eliminate this defensive copy after confirming that updateLinkProperties does not + // modify its oldLp parameter. updateLinkProperties(nai, newLp, new LinkProperties(nai.linkProperties)); } From 4e54d05cbc98d81f561c3903d6bc4e480652f62d Mon Sep 17 00:00:00 2001 From: Bruce Chen Date: Fri, 17 Apr 2020 04:28:04 +0000 Subject: [PATCH 172/229] Add testTransportTypesEqual to dnsmanager test cases A test that ensures that NetworkCapabilities.TRANSPORT_* is eaual to IDnsResolver.TRANSPORT_* for every possible value of each. Bug: 153267602 Test: atest FrameworksNetTests Merged-In: I6b23ccc6ce1659fdfd9573dfcd895f2c20fa9417 Change-Id: I3dd4ed0d1fcceca9c8aec9b3e6769603e4fa913b (cherry picked from commit 5f28e6f881e0ea52e8e96c1207654ce44b0d05a1) --- .../server/connectivity/DnsManagerTest.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java index a392ae3f13..0a603b8e4b 100644 --- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java @@ -18,6 +18,8 @@ package com.android.server.connectivity; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OFF; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME; +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.provider.Settings.Global.PRIVATE_DNS_DEFAULT_MODE; @@ -30,6 +32,7 @@ import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.reset; @@ -44,16 +47,19 @@ import android.net.IpPrefix; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; +import android.net.NetworkCapabilities; import android.net.ResolverOptionsParcel; import android.net.ResolverParamsParcel; import android.net.RouteInfo; import android.net.shared.PrivateDnsConfig; import android.provider.Settings; import android.test.mock.MockContentResolver; +import android.util.SparseArray; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.internal.util.MessageUtils; import com.android.internal.util.test.FakeSettingsProvider; import org.junit.Before; @@ -354,4 +360,23 @@ public class DnsManagerTest { expectedParams.resolverOptions = new ResolverOptionsParcel(); assertResolverParamsEquals(actualParams, expectedParams); } + + @Test + public void testTransportTypesEqual() throws Exception { + SparseArray ncTransTypes = MessageUtils.findMessageNames( + new Class[] { NetworkCapabilities.class }, new String[]{ "TRANSPORT_" }); + SparseArray dnsTransTypes = MessageUtils.findMessageNames( + new Class[] { IDnsResolver.class }, new String[]{ "TRANSPORT_" }); + assertEquals(0, MIN_TRANSPORT); + assertEquals(MAX_TRANSPORT + 1, ncTransTypes.size()); + // TRANSPORT_UNKNOWN in IDnsResolver is defined to -1 and only for resolver. + assertEquals("TRANSPORT_UNKNOWN", dnsTransTypes.get(-1)); + assertEquals(ncTransTypes.size(), dnsTransTypes.size() - 1); + for (int i = MIN_TRANSPORT; i < MAX_TRANSPORT; i++) { + String name = ncTransTypes.get(i, null); + assertNotNull("Could not find NetworkCapabilies.TRANSPORT_* constant equal to " + + i, name); + assertEquals(name, dnsTransTypes.get(i)); + } + } } From b9626ecd404e088e2a62af2b468b4c4de83345cd Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 17 Apr 2020 05:11:01 +0000 Subject: [PATCH 173/229] This contains a squash of two changes >>>>>>>>>>>>>>>>>>>>>> aosp/1284588 Adjust permission of NetworkProvider related API - Allow an app holds NETWORK_SETTINGS to acess registerNetworkProvier() and unregisterNetworkProvider(). - To access declareNetworkRequestUnfulfillable(), allow an app holds MANAGE_TEST_NETWORKS to declare a unfulfillable request that contains TRANSPORT_TEST transport. This makes easier to write cts to test. >>>>>>>>>>>>>>>>>>>>>> aosp/1285957 Add cts test for NetworkProvider It will skip whole tests on Q device since NetworkProvider class is introduced in R. Result on Q device would be: [1/1] android.net.NetworkProviderTest#skippedClassForDevSdkMismatch: IGNORED (3ms) >>>>>>>>>>>>>>>>>>>>>> Bug: 153614605 Bug: 153613690 Bug: 153612373 Test: atest FrameworksNetTests atest CtsNetTestCases:android.net.NetworkProviderTest Test: atest CtsNetTestCasesLatestSdk:android.net.NetworkProviderTest Change-Id: Ib6f42b8f0e94e8c2715a030587e065864edff25b Merged-In: Ic9809e731aa811a51c2f82d189372169d99a5ed9 Merged-In: If7bfc7fae503e3497c37754697d0b148ff4cab3b (cherry picked from commit 10138d42a8f3892fcdb129a39409efe42873f6fe) --- .../android/server/ConnectivityService.java | 24 ++- .../java/android/net/NetworkProviderTest.kt | 158 ++++++++++++++++++ 2 files changed, 179 insertions(+), 3 deletions(-) create mode 100644 tests/net/common/java/android/net/NetworkProviderTest.kt diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 001db3bd6a..f1ea5d0184 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2093,6 +2093,20 @@ public class ConnectivityService extends IConnectivityManager.Stub NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); } + private void enforceNetworkFactoryOrSettingsPermission() { + enforceAnyPermissionOf( + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_FACTORY, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); + } + + private void enforceNetworkFactoryOrTestNetworksPermission() { + enforceAnyPermissionOf( + android.Manifest.permission.MANAGE_TEST_NETWORKS, + android.Manifest.permission.NETWORK_FACTORY, + NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); + } + private boolean checkSettingsPermission() { return checkAnyPermissionOf( android.Manifest.permission.NETWORK_SETTINGS, @@ -5683,7 +5697,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public int registerNetworkProvider(Messenger messenger, String name) { - enforceNetworkFactoryPermission(); + enforceNetworkFactoryOrSettingsPermission(); NetworkProviderInfo npi = new NetworkProviderInfo(name, messenger, null /* asyncChannel */, nextNetworkProviderId(), () -> unregisterNetworkProvider(messenger)); @@ -5693,7 +5707,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void unregisterNetworkProvider(Messenger messenger) { - enforceNetworkFactoryPermission(); + enforceNetworkFactoryOrSettingsPermission(); mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_NETWORK_PROVIDER, messenger)); } @@ -5713,7 +5727,11 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void declareNetworkRequestUnfulfillable(NetworkRequest request) { - enforceNetworkFactoryPermission(); + if (request.hasTransport(TRANSPORT_TEST)) { + enforceNetworkFactoryOrTestNetworksPermission(); + } else { + enforceNetworkFactoryPermission(); + } mHandler.post(() -> handleReleaseNetworkRequest(request, Binder.getCallingUid(), true)); } diff --git a/tests/net/common/java/android/net/NetworkProviderTest.kt b/tests/net/common/java/android/net/NetworkProviderTest.kt new file mode 100644 index 0000000000..4601c4bf4a --- /dev/null +++ b/tests/net/common/java/android/net/NetworkProviderTest.kt @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2020 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.app.Instrumentation +import android.content.Context +import android.net.NetworkCapabilities.TRANSPORT_TEST +import android.os.Build +import android.os.HandlerThread +import android.os.Looper +import android.net.NetworkProviderTest.TestNetworkCallback.CallbackEntry.OnUnavailable +import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequested +import android.net.NetworkProviderTest.TestNetworkProvider.CallbackEntry.OnNetworkRequestWithdrawn +import androidx.test.InstrumentationRegistry +import com.android.testutils.ArrayTrackRecord +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo +import com.android.testutils.DevSdkIgnoreRunner +import java.util.UUID +import kotlin.test.assertEquals +import kotlin.test.assertNotEquals +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +private const val DEFAULT_TIMEOUT_MS = 5000L +private val instrumentation: Instrumentation + get() = InstrumentationRegistry.getInstrumentation() +private val context: Context get() = InstrumentationRegistry.getContext() +private val PROVIDER_NAME = "NetworkProviderTest" + +@RunWith(DevSdkIgnoreRunner::class) +@IgnoreUpTo(Build.VERSION_CODES.Q) +class NetworkProviderTest { + private val mCm = context.getSystemService(ConnectivityManager::class.java) + private val mHandlerThread = HandlerThread("${javaClass.simpleName} handler thread") + + @Before + fun setUp() { + instrumentation.getUiAutomation().adoptShellPermissionIdentity() + mHandlerThread.start() + } + + @After + fun tearDown() { + mHandlerThread.quitSafely() + instrumentation.getUiAutomation().dropShellPermissionIdentity() + } + + private class TestNetworkProvider(context: Context, looper: Looper) : + NetworkProvider(context, looper, PROVIDER_NAME) { + private val seenEvents = ArrayTrackRecord().newReadHead() + + sealed class CallbackEntry { + data class OnNetworkRequested( + val request: NetworkRequest, + val score: Int, + val id: Int + ) : CallbackEntry() + data class OnNetworkRequestWithdrawn(val request: NetworkRequest) : CallbackEntry() + } + + override fun onNetworkRequested(request: NetworkRequest, score: Int, id: Int) { + seenEvents.add(OnNetworkRequested(request, score, id)) + } + + override fun onNetworkRequestWithdrawn(request: NetworkRequest) { + seenEvents.add(OnNetworkRequestWithdrawn(request)) + } + + inline fun expectCallback( + crossinline predicate: (T) -> Boolean + ) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) } + } + + private fun createNetworkProvider(): TestNetworkProvider { + return TestNetworkProvider(context, mHandlerThread.looper) + } + + @Test + fun testOnNetworkRequested() { + val provider = createNetworkProvider() + assertEquals(provider.getProviderId(), NetworkProvider.ID_NONE) + mCm.registerNetworkProvider(provider) + assertNotEquals(provider.getProviderId(), NetworkProvider.ID_NONE) + + val specifier = StringNetworkSpecifier(UUID.randomUUID().toString()) + val nr: NetworkRequest = NetworkRequest.Builder() + .addTransportType(TRANSPORT_TEST) + .setNetworkSpecifier(specifier) + .build() + val cb = ConnectivityManager.NetworkCallback() + mCm.requestNetwork(nr, cb) + provider.expectCallback() { + callback -> callback.request.getNetworkSpecifier() == specifier && + callback.request.hasTransport(TRANSPORT_TEST) + } + + mCm.unregisterNetworkCallback(cb) + provider.expectCallback() { + callback -> callback.request.getNetworkSpecifier() == specifier && + callback.request.hasTransport(TRANSPORT_TEST) + } + mCm.unregisterNetworkProvider(provider) + // Provider id should be ID_NONE after unregister network provider + assertEquals(provider.getProviderId(), NetworkProvider.ID_NONE) + // unregisterNetworkProvider should not crash even if it's called on an + // already unregistered provider. + mCm.unregisterNetworkProvider(provider) + } + + private class TestNetworkCallback : ConnectivityManager.NetworkCallback() { + private val seenEvents = ArrayTrackRecord().newReadHead() + sealed class CallbackEntry { + object OnUnavailable : CallbackEntry() + } + + override fun onUnavailable() { + seenEvents.add(OnUnavailable) + } + + inline fun expectCallback( + crossinline predicate: (T) -> Boolean + ) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) } + } + + @Test + fun testDeclareNetworkRequestUnfulfillable() { + val provider = createNetworkProvider() + mCm.registerNetworkProvider(provider) + + val specifier = StringNetworkSpecifier(UUID.randomUUID().toString()) + val nr: NetworkRequest = NetworkRequest.Builder() + .addTransportType(TRANSPORT_TEST) + .setNetworkSpecifier(specifier) + .build() + + val cb = TestNetworkCallback() + mCm.requestNetwork(nr, cb) + provider.declareNetworkRequestUnfulfillable(nr) + cb.expectCallback() { nr.getNetworkSpecifier() == specifier } + mCm.unregisterNetworkProvider(provider) + } +} \ No newline at end of file From f0a0642b97c6209444f73e8162e968059d56b32b Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Fri, 17 Apr 2020 16:26:45 +0000 Subject: [PATCH 174/229] Move DhcpInfoTest to frameworks/base/tests/net/common Address comment from aosp/1162443. Move to FrameworksNetCommonTests so that it can be run in cts test and presubmit test. Also change package name from android.net.cts to android.net Bug: 154299158 Test: atest FrameworksNetTest atest CtsNetTestCasesLatestSdk:android.net.DhcpInfoTest Change-Id: Ib6c9b7729ec4c348d94d025996efa9a1f436258b Merged-In: I42a965ae5cb748fdd80b4d5c0f8b26f36f74be72 --- .../common/java/android/net/DhcpInfoTest.java | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 tests/net/common/java/android/net/DhcpInfoTest.java diff --git a/tests/net/common/java/android/net/DhcpInfoTest.java b/tests/net/common/java/android/net/DhcpInfoTest.java new file mode 100644 index 0000000000..bd5533f339 --- /dev/null +++ b/tests/net/common/java/android/net/DhcpInfoTest.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2009 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 static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTL; + +import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals; +import static com.android.testutils.ParcelUtilsKt.parcelingRoundTrip; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import android.annotation.Nullable; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.net.Inet4Address; +import java.net.InetAddress; + +@RunWith(AndroidJUnit4.class) +public class DhcpInfoTest { + private static final String STR_ADDR1 = "255.255.255.255"; + private static final String STR_ADDR2 = "127.0.0.1"; + private static final String STR_ADDR3 = "192.168.1.1"; + private static final String STR_ADDR4 = "192.168.1.0"; + private static final int LEASE_TIME = 9999; + + private int ipToInteger(String ipString) throws Exception { + return inet4AddressToIntHTL((Inet4Address) InetAddress.getByName(ipString)); + } + + private DhcpInfo createDhcpInfoObject() throws Exception { + final DhcpInfo dhcpInfo = new DhcpInfo(); + dhcpInfo.ipAddress = ipToInteger(STR_ADDR1); + dhcpInfo.gateway = ipToInteger(STR_ADDR2); + dhcpInfo.netmask = ipToInteger(STR_ADDR3); + dhcpInfo.dns1 = ipToInteger(STR_ADDR4); + dhcpInfo.dns2 = ipToInteger(STR_ADDR4); + dhcpInfo.serverAddress = ipToInteger(STR_ADDR2); + dhcpInfo.leaseDuration = LEASE_TIME; + return dhcpInfo; + } + + @Test + public void testConstructor() { + new DhcpInfo(); + } + + @Test + public void testToString() throws Exception { + final String expectedDefault = "ipaddr 0.0.0.0 gateway 0.0.0.0 netmask 0.0.0.0 " + + "dns1 0.0.0.0 dns2 0.0.0.0 DHCP server 0.0.0.0 lease 0 seconds"; + + DhcpInfo dhcpInfo = new DhcpInfo(); + + // Test default string. + assertEquals(expectedDefault, dhcpInfo.toString()); + + dhcpInfo = createDhcpInfoObject(); + + final String expected = "ipaddr " + STR_ADDR1 + " gateway " + STR_ADDR2 + " netmask " + + STR_ADDR3 + " dns1 " + STR_ADDR4 + " dns2 " + STR_ADDR4 + " DHCP server " + + STR_ADDR2 + " lease " + LEASE_TIME + " seconds"; + // Test with new values + assertEquals(expected, dhcpInfo.toString()); + } + + private boolean dhcpInfoEquals(@Nullable DhcpInfo left, @Nullable DhcpInfo right) { + if (left == null && right == null) return true; + + if (left == null || right == null) return false; + + return left.ipAddress == right.ipAddress + && left.gateway == right.gateway + && left.netmask == right.netmask + && left.dns1 == right.dns1 + && left.dns2 == right.dns2 + && left.serverAddress == right.serverAddress + && left.leaseDuration == right.leaseDuration; + } + + @Test + public void testParcelDhcpInfo() throws Exception { + // Cannot use assertParcelSane() here because this requires .equals() to work as + // defined, but DhcpInfo has a different legacy behavior that we cannot change. + final DhcpInfo dhcpInfo = createDhcpInfoObject(); + assertFieldCountEquals(7, DhcpInfo.class); + + final DhcpInfo dhcpInfoRoundTrip = parcelingRoundTrip(dhcpInfo); + assertTrue(dhcpInfoEquals(null, null)); + assertFalse(dhcpInfoEquals(null, dhcpInfoRoundTrip)); + assertFalse(dhcpInfoEquals(dhcpInfo, null)); + assertTrue(dhcpInfoEquals(dhcpInfo, dhcpInfoRoundTrip)); + } +} From 4308bfc4f05af28d07576ae21ac57679da3a0953 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 20 Apr 2020 11:37:18 +0000 Subject: [PATCH 175/229] Support learning the NAT64 prefix from two different sources. The NAT64 prefix from the RA always takes precedence over the NAT64 prefix from DNS discovery, because it is detected faster, and detecting it does not require sending any packets. Bug: 150648313 Test: new unit test Merged-In: Ic7452431d2d9aea1ae59b67a9d8383c6cc5b3902 Change-Id: Ic7452431d2d9aea1ae59b67a9d8383c6cc5b3902 --- .../android/server/ConnectivityService.java | 1 + .../server/connectivity/Nat464Xlat.java | 69 +++++++++----- .../server/ConnectivityServiceTest.java | 89 +++++++++++++++++++ .../server/connectivity/Nat464XlatTest.java | 44 ++++++++- 4 files changed, 179 insertions(+), 24 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index f1ea5d0184..552331ede9 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5889,6 +5889,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) { lp.ensureDirectlyConnectedRoutes(); + nai.clatd.setNat64PrefixFromRa(lp.getNat64Prefix()); } private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties newLp, diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index e6b2d2678f..8ad21966cb 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -81,15 +81,23 @@ public class Nat464Xlat extends BaseNetworkObserver { RUNNING, // start() called, and the stacked iface is known to be up. } - /** NAT64 prefix currently in use. Only valid in STARTING or RUNNING states. */ + /** + * NAT64 prefix currently in use. Only valid in STARTING or RUNNING states. + * Used, among other things, to avoid updates when switching from a prefix learned from one + * source (e.g., RA) to the same prefix learned from another source (e.g., RA). + */ private IpPrefix mNat64PrefixInUse; /** NAT64 prefix (if any) discovered from DNS via RFC 7050. */ private IpPrefix mNat64PrefixFromDns; + /** NAT64 prefix (if any) learned from the network via RA. */ + private IpPrefix mNat64PrefixFromRa; private String mBaseIface; private String mIface; private Inet6Address mIPv6Address; private State mState = State.IDLE; + private boolean mPrefixDiscoveryRunning; + public Nat464Xlat(NetworkAgentInfo nai, INetd netd, IDnsResolver dnsResolver, INetworkManagementService nmService) { mDnsResolver = dnsResolver; @@ -138,15 +146,6 @@ public class Nat464Xlat extends BaseNetworkObserver { return requiresClat(nai) && lp != null && lp.getNat64Prefix() != null; } - /** - * @return true if we have started prefix discovery and not yet stopped it (regardless of - * whether it is still running or has succeeded). - * A true result corresponds to internal states DISCOVERING, STARTING and RUNNING. - */ - public boolean isPrefixDiscoveryStarted() { - return mState == State.DISCOVERING || isStarted(); - } - /** * @return true if clatd has been started and has not yet stopped. * A true result corresponds to internal states STARTING and RUNNING. @@ -181,7 +180,7 @@ public class Nat464Xlat extends BaseNetworkObserver { return; } - mNat64PrefixInUse = getNat64Prefix(); + mNat64PrefixInUse = selectNat64Prefix(); String addrStr = null; try { addrStr = mNetd.clatdStart(baseIface, mNat64PrefixInUse.toString()); @@ -218,8 +217,14 @@ public class Nat464Xlat extends BaseNetworkObserver { mNat64PrefixInUse = null; mIface = null; mBaseIface = null; - if (requiresClat(mNetwork)) { - mState = State.DISCOVERING; + + if (isPrefixDiscoveryNeeded()) { + if (!mPrefixDiscoveryRunning) { + startPrefixDiscovery(); + } else { + // Prefix discovery is already running. Nothing to do. + mState = State.DISCOVERING; + } } else { stopPrefixDiscovery(); // Enters IDLE state. } @@ -283,6 +288,7 @@ public class Nat464Xlat extends BaseNetworkObserver { Slog.e(TAG, "Error starting prefix discovery on netId " + getNetId() + ": " + e); } mState = State.DISCOVERING; + mPrefixDiscoveryRunning = true; } private void stopPrefixDiscovery() { @@ -292,10 +298,18 @@ public class Nat464Xlat extends BaseNetworkObserver { Slog.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e); } mState = State.IDLE; + mPrefixDiscoveryRunning = false; + } + + private boolean isPrefixDiscoveryNeeded() { + // If there is no NAT64 prefix in the RA, prefix discovery is always needed. It cannot be + // stopped after it succeeds, because stopping it will cause netd to report that the prefix + // has been removed, and that will cause us to stop clatd. + return requiresClat(mNetwork) && mNat64PrefixFromRa == null; } private void maybeHandleNat64PrefixChange() { - final IpPrefix newPrefix = getNat64Prefix(); + final IpPrefix newPrefix = selectNat64Prefix(); if (!Objects.equals(mNat64PrefixInUse, newPrefix)) { Slog.d(TAG, "NAT64 prefix changed from " + mNat64PrefixInUse + " to " + newPrefix); @@ -314,13 +328,10 @@ public class Nat464Xlat extends BaseNetworkObserver { // TODO: turn this class into a proper StateMachine. http://b/126113090 switch (mState) { case IDLE: - if (requiresClat(mNetwork)) { - // Network is detected to be IPv6-only. - // TODO: consider going to STARTING directly if the NAT64 prefix is already - // known. This would however result in clatd running without prefix discovery - // running, which might be a surprising combination. + if (isPrefixDiscoveryNeeded()) { startPrefixDiscovery(); // Enters DISCOVERING state. - return; + } else if (requiresClat(mNetwork)) { + start(); // Enters STARTING state. } break; @@ -351,8 +362,20 @@ public class Nat464Xlat extends BaseNetworkObserver { } } - private IpPrefix getNat64Prefix() { - return mNat64PrefixFromDns; + /** + * Picks a NAT64 prefix to use. Always prefers the prefix from the RA if one is received from + * both RA and DNS, because the prefix in the RA has better security and updatability, and will + * almost always be received first anyway. + * + * Any network that supports legacy hosts will support discovering the DNS64 prefix via DNS as + * well. If the prefix from the RA is withdrawn, fall back to that for reliability purposes. + */ + private IpPrefix selectNat64Prefix() { + return mNat64PrefixFromRa != null ? mNat64PrefixFromRa : mNat64PrefixFromDns; + } + + public void setNat64PrefixFromRa(IpPrefix prefix) { + mNat64PrefixFromRa = prefix; } public void setNat64PrefixFromDns(IpPrefix prefix) { @@ -367,7 +390,7 @@ public class Nat464Xlat extends BaseNetworkObserver { public void fixupLinkProperties(@NonNull LinkProperties oldLp, @NonNull LinkProperties lp) { // This must be done even if clatd is not running, because otherwise shouldStartClat would // never return true. - lp.setNat64Prefix(getNat64Prefix()); + lp.setNat64Prefix(selectNat64Prefix()); if (!isRunning()) { return; diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index dad0363a80..c1e51dd62a 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6179,6 +6179,95 @@ public class ConnectivityServiceTest { mCm.unregisterNetworkCallback(networkCallback); } + private void expectNat64PrefixChange(TestableNetworkCallback callback, + TestNetworkAgentWrapper agent, IpPrefix prefix) { + callback.expectLinkPropertiesThat(agent, x -> Objects.equals(x.getNat64Prefix(), prefix)); + } + + @Test + public void testNat64PrefixMultipleSources() throws Exception { + final String iface = "wlan0"; + final String pref64FromRaStr = "64:ff9b::"; + final String pref64FromDnsStr = "2001:db8:64::"; + final IpPrefix pref64FromRa = new IpPrefix(InetAddress.getByName(pref64FromRaStr), 96); + final IpPrefix pref64FromDns = new IpPrefix(InetAddress.getByName(pref64FromDnsStr), 96); + final IpPrefix newPref64FromRa = new IpPrefix("2001:db8:64:64:64:64::/96"); + + final NetworkRequest request = new NetworkRequest.Builder() + .addCapability(NET_CAPABILITY_INTERNET) + .build(); + final TestNetworkCallback callback = new TestNetworkCallback(); + mCm.registerNetworkCallback(request, callback); + + final LinkProperties baseLp = new LinkProperties(); + baseLp.setInterfaceName(iface); + baseLp.addLinkAddress(new LinkAddress("2001:db8:1::1/64")); + baseLp.addDnsServer(InetAddress.getByName("2001:4860:4860::6464")); + + reset(mMockNetd, mMockDnsResolver); + InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver); + + // If a network already has a NAT64 prefix on connect, clatd is started immediately and + // prefix discovery is never started. + LinkProperties lp = new LinkProperties(baseLp); + lp.setNat64Prefix(pref64FromRa); + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp); + mCellNetworkAgent.connect(false); + final Network network = mCellNetworkAgent.getNetwork(); + int netId = network.getNetId(); + callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); + inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); + inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + callback.assertNoCallback(); + assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix()); + + // If the RA prefix is withdrawn, clatd is stopped and prefix discovery is started. + lp.setNat64Prefix(null); + mCellNetworkAgent.sendLinkProperties(lp); + expectNat64PrefixChange(callback, mCellNetworkAgent, null); + inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); + + mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */, + pref64FromDnsStr, 96); + expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns); + inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString()); + + // If the RA prefix reappears, clatd is restarted and prefix discovery is stopped. + lp.setNat64Prefix(pref64FromRa); + mCellNetworkAgent.sendLinkProperties(lp); + expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa); + inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); + inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); + inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + + // If the RA prefix changes, clatd is restarted and prefix discovery is not started. + lp.setNat64Prefix(newPref64FromRa); + mCellNetworkAgent.sendLinkProperties(lp); + expectNat64PrefixChange(callback, mCellNetworkAgent, newPref64FromRa); + inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockNetd).clatdStart(iface, newPref64FromRa.toString()); + inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + + // If the RA prefix changes to the same value, nothing happens. + lp.setNat64Prefix(newPref64FromRa); + mCellNetworkAgent.sendLinkProperties(lp); + callback.assertNoCallback(); + assertEquals(newPref64FromRa, mCm.getLinkProperties(network).getNat64Prefix()); + inOrder.verify(mMockNetd, never()).clatdStop(iface); + inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); + inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + + // The transition between no prefix and DNS prefix is tested in testStackedLinkProperties. + + callback.assertNoCallback(); + mCellNetworkAgent.disconnect(); + mCm.unregisterNetworkCallback(callback); + } + @Test public void testDataActivityTracking() throws Exception { final TestNetworkCallback networkCallback = new TestNetworkCallback(); diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java index d0ebb5283f..84dad981e0 100644 --- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java +++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java @@ -60,6 +60,7 @@ public class Nat464XlatTest { static final String STACKED_IFACE = "v4-test0"; static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29"); static final String NAT64_PREFIX = "64:ff9b::/96"; + static final String OTHER_NAT64_PREFIX = "2001:db8:0:64::/96"; static final int NETID = 42; @Mock ConnectivityService mConnectivity; @@ -139,7 +140,7 @@ public class Nat464XlatTest { for (NetworkInfo.DetailedState state : supportedDetailedStates) { mNai.networkInfo.setDetailedState(state, "reason", "extraInfo"); - mNai.linkProperties.setNat64Prefix(new IpPrefix("2001:db8:0:64::/96")); + mNai.linkProperties.setNat64Prefix(new IpPrefix(OTHER_NAT64_PREFIX)); assertRequiresClat(false, mNai); assertShouldStartClat(false, mNai); @@ -398,6 +399,47 @@ public class Nat464XlatTest { verifyNoMoreInteractions(mNetd, mNms, mConnectivity); } + @Test + public void testNat64PrefixPreference() throws Exception { + final IpPrefix prefixFromDns = new IpPrefix(NAT64_PREFIX); + final IpPrefix prefixFromRa = new IpPrefix(OTHER_NAT64_PREFIX); + + Nat464Xlat nat = makeNat464Xlat(); + + final LinkProperties emptyLp = new LinkProperties(); + LinkProperties fixedupLp; + + fixedupLp = new LinkProperties(); + nat.setNat64PrefixFromDns(prefixFromDns); + nat.fixupLinkProperties(emptyLp, fixedupLp); + assertEquals(prefixFromDns, fixedupLp.getNat64Prefix()); + + fixedupLp = new LinkProperties(); + nat.setNat64PrefixFromRa(prefixFromRa); + nat.fixupLinkProperties(emptyLp, fixedupLp); + assertEquals(prefixFromRa, fixedupLp.getNat64Prefix()); + + fixedupLp = new LinkProperties(); + nat.setNat64PrefixFromRa(null); + nat.fixupLinkProperties(emptyLp, fixedupLp); + assertEquals(prefixFromDns, fixedupLp.getNat64Prefix()); + + fixedupLp = new LinkProperties(); + nat.setNat64PrefixFromRa(prefixFromRa); + nat.fixupLinkProperties(emptyLp, fixedupLp); + assertEquals(prefixFromRa, fixedupLp.getNat64Prefix()); + + fixedupLp = new LinkProperties(); + nat.setNat64PrefixFromDns(null); + nat.fixupLinkProperties(emptyLp, fixedupLp); + assertEquals(prefixFromRa, fixedupLp.getNat64Prefix()); + + fixedupLp = new LinkProperties(); + nat.setNat64PrefixFromRa(null); + nat.fixupLinkProperties(emptyLp, fixedupLp); + assertEquals(null, fixedupLp.getNat64Prefix()); + } + static void assertIdle(Nat464Xlat nat) { assertTrue("Nat464Xlat was not IDLE", !nat.isStarted()); } From 1c0d43fc1544713146dd13a30c0767f57bf4ae7c Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 20 Apr 2020 11:37:54 +0000 Subject: [PATCH 176/229] Make the Nat464Xlat tests more realistic. 464xlat will never be started on a network that is not connected, or on a network that has no IPv6 address. This is a no-op test-only change but it is necessary for an upcoming change that violates some of the invalid assumptions currently made by this test and causes it to fail. Bug: 150648313 Test: test-only change Change-Id: I41766e9adaa7c24454648b371e6e3cc647693be5 Merged-In: I41766e9adaa7c24454648b371e6e3cc647693be5 (cherry picked from commit df0c522d18ee73c1d20cff1a1dc955b383e6c355) --- .../server/connectivity/Nat464XlatTest.java | 66 +++++++++++++++++-- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java index 84dad981e0..5046b6586f 100644 --- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java +++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java @@ -58,6 +58,7 @@ public class Nat464XlatTest { static final String BASE_IFACE = "test0"; static final String STACKED_IFACE = "v4-test0"; + static final LinkAddress V6ADDR = new LinkAddress("2001:db8:1::f00/64"); static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29"); static final String NAT64_PREFIX = "64:ff9b::/96"; static final String OTHER_NAT64_PREFIX = "2001:db8:0:64::/96"; @@ -82,6 +83,14 @@ public class Nat464XlatTest { }; } + private void markNetworkConnected() { + mNai.networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", ""); + } + + private void markNetworkDisconnected() { + mNai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, "", ""); + } + @Before public void setUp() throws Exception { mLooper = new TestLooper(); @@ -93,6 +102,7 @@ public class Nat464XlatTest { mNai.linkProperties.setInterfaceName(BASE_IFACE); mNai.networkInfo = new NetworkInfo(null); mNai.networkInfo.setType(ConnectivityManager.TYPE_WIFI); + markNetworkConnected(); when(mNai.connService()).thenReturn(mConnectivity); when(mNai.netAgentConfig()).thenReturn(mAgentConfig); when(mNai.handler()).thenReturn(mHandler); @@ -177,11 +187,20 @@ public class Nat464XlatTest { } } - @Test - public void testNormalStartAndStop() throws Exception { + private void makeClatUnnecessary(boolean dueToDisconnect) { + if (dueToDisconnect) { + markNetworkDisconnected(); + } else { + mNai.linkProperties.addLinkAddress(ADDR); + } + } + + private void checkNormalStartAndStop(boolean dueToDisconnect) throws Exception { Nat464Xlat nat = makeNat464Xlat(); ArgumentCaptor c = ArgumentCaptor.forClass(LinkProperties.class); + mNai.linkProperties.addLinkAddress(V6ADDR); + nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); // Start clat. @@ -201,6 +220,7 @@ public class Nat464XlatTest { assertRunning(nat); // Stop clat (Network disconnects, IPv4 addr appears, ...). + makeClatUnnecessary(dueToDisconnect); nat.stop(); verify(mNetd).clatdStop(eq(BASE_IFACE)); @@ -218,11 +238,23 @@ public class Nat464XlatTest { verifyNoMoreInteractions(mNetd, mNms, mConnectivity); } + @Test + public void testNormalStartAndStopDueToDisconnect() throws Exception { + checkNormalStartAndStop(true); + } + + @Test + public void testNormalStartAndStopDueToIpv4Addr() throws Exception { + checkNormalStartAndStop(false); + } + private void checkStartStopStart(boolean interfaceRemovedFirst) throws Exception { Nat464Xlat nat = makeNat464Xlat(); ArgumentCaptor c = ArgumentCaptor.forClass(LinkProperties.class); InOrder inOrder = inOrder(mNetd, mConnectivity); + mNai.linkProperties.addLinkAddress(V6ADDR); + nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); nat.start(); @@ -345,10 +377,11 @@ public class Nat464XlatTest { verifyNoMoreInteractions(mNetd, mNms, mConnectivity); } - @Test - public void testStopBeforeClatdStarts() throws Exception { + private void checkStopBeforeClatdStarts(boolean dueToDisconnect) throws Exception { Nat464Xlat nat = makeNat464Xlat(); + mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); + nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); nat.start(); @@ -357,6 +390,7 @@ public class Nat464XlatTest { verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...) + makeClatUnnecessary(dueToDisconnect); nat.stop(); verify(mNetd).clatdStop(eq(BASE_IFACE)); @@ -378,9 +412,20 @@ public class Nat464XlatTest { } @Test - public void testStopAndClatdNeverStarts() throws Exception { + public void testStopDueToDisconnectBeforeClatdStarts() throws Exception { + checkStopBeforeClatdStarts(true); + } + + @Test + public void testStopDueToIpv4AddrBeforeClatdStarts() throws Exception { + checkStopBeforeClatdStarts(false); + } + + private void checkStopAndClatdNeverStarts(boolean dueToDisconnect) throws Exception { Nat464Xlat nat = makeNat464Xlat(); + mNai.linkProperties.addLinkAddress(new LinkAddress("2001:db8::1/64")); + nat.setNat64PrefixFromDns(new IpPrefix(NAT64_PREFIX)); nat.start(); @@ -389,6 +434,7 @@ public class Nat464XlatTest { verify(mNetd).clatdStart(eq(BASE_IFACE), eq(NAT64_PREFIX)); // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...) + makeClatUnnecessary(dueToDisconnect); nat.stop(); verify(mNetd).clatdStop(eq(BASE_IFACE)); @@ -399,6 +445,16 @@ public class Nat464XlatTest { verifyNoMoreInteractions(mNetd, mNms, mConnectivity); } + @Test + public void testStopDueToDisconnectAndClatdNeverStarts() throws Exception { + checkStopAndClatdNeverStarts(true); + } + + @Test + public void testStopDueToIpv4AddressAndClatdNeverStarts() throws Exception { + checkStopAndClatdNeverStarts(false); + } + @Test public void testNat64PrefixPreference() throws Exception { final IpPrefix prefixFromDns = new IpPrefix(NAT64_PREFIX); From c9016cafe3443a34675e1ebad3e1dbbc0de440fd Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Mon, 20 Apr 2020 11:38:11 +0000 Subject: [PATCH 177/229] Stop prefix discovery if an RA prefix arrives in DISCOVERING Currently, if a prefix is learned from an RA while prefix discovery is running, clatd will be correctly started, but prefix discovery will be stopped. In order to fix this, make it possible to call stopPrefixDiscovery without transitioning to IDLE state (which is obviously necessary in this case), by moving the assignment of the next state from that method to its callers. For consistency, do the same for startPrefixDiscovery. Bug: 150648313 Test: new test coverage Change-Id: I3803fa3d9806848b331c35ee8bac256934bd1f21 Merged-In: I3803fa3d9806848b331c35ee8bac256934bd1f21 (cherry picked from commit c7c6f76402a989f91b02c37574b6a9de592cf1af) --- .../android/server/connectivity/Nat464Xlat.java | 14 ++++++++------ .../android/server/ConnectivityServiceTest.java | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index 8ad21966cb..34d0bed9a8 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -195,6 +195,9 @@ public class Nat464Xlat extends BaseNetworkObserver { } catch (ClassCastException | IllegalArgumentException | NullPointerException e) { Slog.e(TAG, "Invalid IPv6 address " + addrStr); } + if (mPrefixDiscoveryRunning && !isPrefixDiscoveryNeeded()) { + stopPrefixDiscovery(); + } } /** @@ -221,12 +224,11 @@ public class Nat464Xlat extends BaseNetworkObserver { if (isPrefixDiscoveryNeeded()) { if (!mPrefixDiscoveryRunning) { startPrefixDiscovery(); - } else { - // Prefix discovery is already running. Nothing to do. - mState = State.DISCOVERING; } + mState = State.DISCOVERING; } else { - stopPrefixDiscovery(); // Enters IDLE state. + stopPrefixDiscovery(); + mState = State.IDLE; } } @@ -287,7 +289,6 @@ public class Nat464Xlat extends BaseNetworkObserver { } catch (RemoteException | ServiceSpecificException e) { Slog.e(TAG, "Error starting prefix discovery on netId " + getNetId() + ": " + e); } - mState = State.DISCOVERING; mPrefixDiscoveryRunning = true; } @@ -297,7 +298,6 @@ public class Nat464Xlat extends BaseNetworkObserver { } catch (RemoteException | ServiceSpecificException e) { Slog.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e); } - mState = State.IDLE; mPrefixDiscoveryRunning = false; } @@ -330,6 +330,7 @@ public class Nat464Xlat extends BaseNetworkObserver { case IDLE: if (isPrefixDiscoveryNeeded()) { startPrefixDiscovery(); // Enters DISCOVERING state. + mState = State.DISCOVERING; } else if (requiresClat(mNetwork)) { start(); // Enters STARTING state. } @@ -344,6 +345,7 @@ public class Nat464Xlat extends BaseNetworkObserver { if (!requiresClat(mNetwork)) { // IPv4 address added. Go back to IDLE state. stopPrefixDiscovery(); + mState = State.IDLE; return; } break; diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index c1e51dd62a..a478e68c7d 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6228,6 +6228,22 @@ public class ConnectivityServiceTest { inOrder.verify(mMockNetd).clatdStop(iface); inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); + // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and + // clatd is started with the prefix from the RA. + lp.setNat64Prefix(pref64FromRa); + mCellNetworkAgent.sendLinkProperties(lp); + expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa); + inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); + inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); + + // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS + // discovery has succeeded. + lp.setNat64Prefix(null); + mCellNetworkAgent.sendLinkProperties(lp); + expectNat64PrefixChange(callback, mCellNetworkAgent, null); + inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); + mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */, pref64FromDnsStr, 96); expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns); From 4f5455fb44313c67e9f115def676485a81b30acf Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Mon, 20 Apr 2020 09:06:59 +0000 Subject: [PATCH 178/229] Add network agent to enhance NetworkProvider test Add network agent to test more situation that could get the onNetworkRequested callback. Bug: 153614605 Bug: 153613690 Bug: 153612373 Test: atest CtsNetTestCasesLatestSdk:android.net.NetworkProviderTest Change-Id: I7f827710b47546bd4419cc1ff06f03ec4635583d Merged-In: Id494a1697cc1b73e8e56ae585a69faec31c59f52 (cherry picked from commit 9e92e57fd70944cbe8bb61bbb7a5fa728d0e68f5) --- .../java/android/net/NetworkProviderTest.kt | 37 +++++++++++++++++-- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/tests/net/common/java/android/net/NetworkProviderTest.kt b/tests/net/common/java/android/net/NetworkProviderTest.kt index 4601c4bf4a..b7c47c2bc2 100644 --- a/tests/net/common/java/android/net/NetworkProviderTest.kt +++ b/tests/net/common/java/android/net/NetworkProviderTest.kt @@ -105,14 +105,43 @@ class NetworkProviderTest { .build() val cb = ConnectivityManager.NetworkCallback() mCm.requestNetwork(nr, cb) - provider.expectCallback() { - callback -> callback.request.getNetworkSpecifier() == specifier && + provider.expectCallback() { callback -> + callback.request.getNetworkSpecifier() == specifier && callback.request.hasTransport(TRANSPORT_TEST) } + val initialScore = 40 + val updatedScore = 60 + val nc = NetworkCapabilities().apply { + addTransportType(NetworkCapabilities.TRANSPORT_TEST) + removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) + removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED) + addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) + addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) + setNetworkSpecifier(specifier) + } + val lp = LinkProperties() + val config = NetworkAgentConfig.Builder().build() + val agent = object : NetworkAgent(context, mHandlerThread.looper, "TestAgent", nc, lp, + initialScore, config, provider) {} + + provider.expectCallback() { callback -> + callback.request.getNetworkSpecifier() == specifier && + callback.score == initialScore && + callback.id == agent.providerId + } + + agent.sendNetworkScore(updatedScore) + provider.expectCallback() { callback -> + callback.request.getNetworkSpecifier() == specifier && + callback.score == updatedScore && + callback.id == agent.providerId + } + mCm.unregisterNetworkCallback(cb) - provider.expectCallback() { - callback -> callback.request.getNetworkSpecifier() == specifier && + provider.expectCallback() { callback -> + callback.request.getNetworkSpecifier() == specifier && callback.request.hasTransport(TRANSPORT_TEST) } mCm.unregisterNetworkProvider(provider) From 22ef3a874701a456f92fa9fef056861f3c37d48a Mon Sep 17 00:00:00 2001 From: Treehugger Robot Date: Thu, 23 Apr 2020 15:48:31 +0000 Subject: [PATCH 179/229] Add test for NetworkSpecifier Tests for canBeSatisfiedBy() and redact() Bug: 154686765 Test: atest CtsNetTestCasesLatestSdk:android.net.NetworkSpecifierTest Change-Id: Iade6a5b355b8812a5eb191345dfe393938ee272c Merged-In: Iade6a5b355b8812a5eb191345dfe393938ee272c (cherry picked from commit ae84f1ac325e54f021c720744c787b66525d12ea) --- .../java/android/net/NetworkSpecifierTest.kt | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 tests/net/common/java/android/net/NetworkSpecifierTest.kt diff --git a/tests/net/common/java/android/net/NetworkSpecifierTest.kt b/tests/net/common/java/android/net/NetworkSpecifierTest.kt new file mode 100644 index 0000000000..f3409f5359 --- /dev/null +++ b/tests/net/common/java/android/net/NetworkSpecifierTest.kt @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2020 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.os.Build +import androidx.test.filters.SmallTest +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo +import com.android.testutils.DevSdkIgnoreRunner +import kotlin.test.assertTrue +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertNotEquals +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(DevSdkIgnoreRunner::class) +@IgnoreUpTo(Build.VERSION_CODES.Q) +class NetworkSpecifierTest { + private class TestNetworkSpecifier( + val intData: Int = 123, + val stringData: String = "init" + ) : NetworkSpecifier() { + override fun canBeSatisfiedBy(other: NetworkSpecifier?): Boolean = + other != null && + other is TestNetworkSpecifier && + other.intData >= intData && + stringData.equals(other.stringData) + + override fun redact(): NetworkSpecifier = TestNetworkSpecifier(intData, "redact") + } + + @Test + fun testRedact() { + val ns: TestNetworkSpecifier = TestNetworkSpecifier() + val redactNs = ns.redact() + assertTrue(redactNs is TestNetworkSpecifier) + assertEquals(ns.intData, redactNs.intData) + assertNotEquals(ns.stringData, redactNs.stringData) + assertTrue("redact".equals(redactNs.stringData)) + } + + @Test + fun testcanBeSatisfiedBy() { + val target: TestNetworkSpecifier = TestNetworkSpecifier() + assertFalse(target.canBeSatisfiedBy(null)) + assertTrue(target.canBeSatisfiedBy(TestNetworkSpecifier())) + val otherNs = TelephonyNetworkSpecifier.Builder().setSubscriptionId(123).build() + assertFalse(target.canBeSatisfiedBy(otherNs)) + assertTrue(target.canBeSatisfiedBy(TestNetworkSpecifier(intData = 999))) + assertFalse(target.canBeSatisfiedBy(TestNetworkSpecifier(intData = 1))) + assertFalse(target.canBeSatisfiedBy(TestNetworkSpecifier(stringData = "diff"))) + } +} \ No newline at end of file From 3745c39f98f913373e00102d125686d2e1966488 Mon Sep 17 00:00:00 2001 From: Rambo Wang Date: Wed, 22 Apr 2020 15:24:51 -0700 Subject: [PATCH 180/229] Restrict match conditions of TelephonyNetworkSpecifier#canBeSatisfied TelephonyNetworkSpecifier will now treat null as matching nothing. When the request specifies a TelephonyNetworkSpecifier while the network does not, this should not be treated as a match. Bug: 154703135 Test: atest android.net.TelephonyNetworkSpecifierTest Change-Id: I329110e929995c9eae6c6ce33b5414777acea1e1 --- .../net/TelephonyNetworkSpecifierTest.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/net/java/android/net/TelephonyNetworkSpecifierTest.java b/tests/net/java/android/net/TelephonyNetworkSpecifierTest.java index 47afed441a..efb92033df 100644 --- a/tests/net/java/android/net/TelephonyNetworkSpecifierTest.java +++ b/tests/net/java/android/net/TelephonyNetworkSpecifierTest.java @@ -19,7 +19,10 @@ package android.net; import static com.android.testutils.ParcelUtilsKt.assertParcelSane; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import android.net.wifi.WifiNetworkSpecifier; import android.telephony.SubscriptionManager; import androidx.test.filters.SmallTest; @@ -32,6 +35,7 @@ import org.junit.Test; @SmallTest public class TelephonyNetworkSpecifierTest { private static final int TEST_SUBID = 5; + private static final String TEST_SSID = "Test123"; /** * Validate that IllegalArgumentException will be thrown if build TelephonyNetworkSpecifier @@ -79,4 +83,31 @@ public class TelephonyNetworkSpecifierTest { .build(); assertParcelSane(specifier, 1 /* fieldCount */); } + + /** + * Validate the behavior of method canBeSatisfiedBy(). + */ + @Test + public void testCanBeSatisfiedBy() { + final TelephonyNetworkSpecifier tns1 = new TelephonyNetworkSpecifier.Builder() + .setSubscriptionId(TEST_SUBID) + .build(); + final TelephonyNetworkSpecifier tns2 = new TelephonyNetworkSpecifier.Builder() + .setSubscriptionId(TEST_SUBID) + .build(); + final WifiNetworkSpecifier wns = new WifiNetworkSpecifier.Builder() + .setSsid(TEST_SSID) + .build(); + final MatchAllNetworkSpecifier mans = new MatchAllNetworkSpecifier(); + + // Test equality + assertEquals(tns1, tns2); + assertTrue(tns1.canBeSatisfiedBy(tns1)); + assertTrue(tns1.canBeSatisfiedBy(tns2)); + + // Test other edge cases. + assertFalse(tns1.canBeSatisfiedBy(null)); + assertFalse(tns1.canBeSatisfiedBy(wns)); + assertTrue(tns1.canBeSatisfiedBy(mans)); + } } From f577197908e135532371c1638655bd6294fb3931 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 24 Apr 2020 12:19:37 +0000 Subject: [PATCH 181/229] Address comments on NetworkStack AIDL v6 Address issues found during AIDL review: - Rename clientAddr to singleClientAddr - Do not use a ParcelableBundle for notifyNetworkTested or notifyDataStallSuspected; instead use AIDL parcelables for stronger backwards compatibility guarantees. Test: atest NetworkMonitorTest ConnectivityServiceTest ConnectivityServiceIntegrationTest, manual Bug: 153500847 Merged-In: Id9b71784e5f6294d203230e57737979e063ff0f8 Change-Id: Id9b71784e5f6294d203230e57737979e063ff0f8 --- .../android/server/ConnectivityService.java | 79 ++++++++++++------- .../server/ConnectivityServiceTest.java | 55 ++++++------- 2 files changed, 80 insertions(+), 54 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 552331ede9..e4eb585e98 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -18,6 +18,14 @@ package com.android.server; import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE; 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; +import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport.KEY_NETWORK_VALIDATION_RESULT; +import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_DNS_EVENTS; +import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_TCP_METRICS; +import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_DNS_CONSECUTIVE_TIMEOUTS; +import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS; +import static android.net.ConnectivityDiagnosticsManager.DataStallReport.KEY_TCP_PACKET_FAIL_RATE; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.NETID_UNSET; import static android.net.ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC; @@ -72,6 +80,7 @@ import android.net.ConnectionInfo; import android.net.ConnectivityDiagnosticsManager.ConnectivityReport; import android.net.ConnectivityDiagnosticsManager.DataStallReport; import android.net.ConnectivityManager; +import android.net.DataStallReportParcelable; import android.net.ICaptivePortal; import android.net.IConnectivityDiagnosticsCallback; import android.net.IConnectivityManager; @@ -108,6 +117,7 @@ import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkStackClient; import android.net.NetworkState; +import android.net.NetworkTestResultParcelable; import android.net.NetworkUtils; import android.net.NetworkWatchlistManager; import android.net.PrivateDnsConfigParcel; @@ -2820,14 +2830,6 @@ public class ConnectivityService extends IConnectivityManager.Stub handleNetworkTested(nai, results.mTestResult, (results.mRedirectUrl == null) ? "" : results.mRedirectUrl); - - // Invoke ConnectivityReport generation for this Network test event. - final Message m = - mConnectivityDiagnosticsHandler.obtainMessage( - ConnectivityDiagnosticsHandler.EVENT_NETWORK_TESTED, - new ConnectivityReportEvent(results.mTimestampMillis, nai)); - m.setData(msg.getData()); - mConnectivityDiagnosticsHandler.sendMessage(m); break; } case EVENT_PROVISIONING_NOTIFICATION: { @@ -3006,23 +3008,33 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void notifyNetworkTested(int testResult, @Nullable String redirectUrl) { - notifyNetworkTestedWithExtras(testResult, redirectUrl, SystemClock.elapsedRealtime(), - PersistableBundle.EMPTY); + // Legacy version of notifyNetworkTestedWithExtras. + // Would only be called if the system has a NetworkStack module older than the + // framework, which does not happen in practice. } @Override - public void notifyNetworkTestedWithExtras( - int testResult, - @Nullable String redirectUrl, - long timestampMillis, - @NonNull PersistableBundle extras) { - final Message msg = - mTrackerHandler.obtainMessage( - EVENT_NETWORK_TESTED, - new NetworkTestedResults( - mNetId, testResult, timestampMillis, redirectUrl)); - msg.setData(new Bundle(extras)); + public void notifyNetworkTestedWithExtras(NetworkTestResultParcelable p) { + final Message msg = mTrackerHandler.obtainMessage( + EVENT_NETWORK_TESTED, + new NetworkTestedResults( + mNetId, p.result, p.timestampMillis, p.redirectUrl)); mTrackerHandler.sendMessage(msg); + + // Invoke ConnectivityReport generation for this Network test event. + final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(mNetId); + if (nai == null) return; + final Message m = mConnectivityDiagnosticsHandler.obtainMessage( + ConnectivityDiagnosticsHandler.EVENT_NETWORK_TESTED, + new ConnectivityReportEvent(p.timestampMillis, nai)); + + final PersistableBundle extras = new PersistableBundle(); + extras.putInt(KEY_NETWORK_VALIDATION_RESULT, p.result); + extras.putInt(KEY_NETWORK_PROBES_SUCCEEDED_BITMASK, p.probesSucceeded); + extras.putInt(KEY_NETWORK_PROBES_ATTEMPTED_BITMASK, p.probesAttempted); + + m.setData(new Bundle(extras)); + mConnectivityDiagnosticsHandler.sendMessage(m); } @Override @@ -3071,12 +3083,25 @@ public class ConnectivityService extends IConnectivityManager.Stub } @Override - public void notifyDataStallSuspected( - long timestampMillis, int detectionMethod, PersistableBundle extras) { - final Message msg = - mConnectivityDiagnosticsHandler.obtainMessage( - ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, - detectionMethod, mNetId, timestampMillis); + public void notifyDataStallSuspected(DataStallReportParcelable p) { + final Message msg = mConnectivityDiagnosticsHandler.obtainMessage( + ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, + p.detectionMethod, mNetId, p.timestampMillis); + + final PersistableBundle extras = new PersistableBundle(); + switch (p.detectionMethod) { + case DETECTION_METHOD_DNS_EVENTS: + extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts); + break; + case DETECTION_METHOD_TCP_METRICS: + extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate); + extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS, + p.tcpMetricsCollectionPeriodMillis); + break; + default: + log("Unknown data stall detection method, ignoring: " + p.detectionMethod); + return; + } msg.setData(new Bundle(extras)); // NetworkStateTrackerHandler currently doesn't take any actions based on data diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index a478e68c7d..a992778fd4 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -144,6 +144,7 @@ import android.net.ConnectivityManager.PacketKeepalive; import android.net.ConnectivityManager.PacketKeepaliveCallback; import android.net.ConnectivityManager.TooManyRequestsException; import android.net.ConnectivityThread; +import android.net.DataStallReportParcelable; import android.net.IConnectivityDiagnosticsCallback; import android.net.IDnsResolver; import android.net.IIpConnectivityMetrics; @@ -170,6 +171,7 @@ import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkStackClient; import android.net.NetworkState; +import android.net.NetworkTestResultParcelable; import android.net.NetworkUtils; import android.net.ProxyInfo; import android.net.ResolverParamsParcel; @@ -196,7 +198,6 @@ import android.os.Looper; import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.Parcelable; -import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; @@ -580,14 +581,6 @@ public class ConnectivityServiceTest { } private class TestNetworkAgentWrapper extends NetworkAgentWrapper { - private static final int VALIDATION_RESULT_BASE = NETWORK_VALIDATION_PROBE_DNS - | NETWORK_VALIDATION_PROBE_HTTP - | NETWORK_VALIDATION_PROBE_HTTPS; - private static final int VALIDATION_RESULT_VALID = VALIDATION_RESULT_BASE - | NETWORK_VALIDATION_RESULT_VALID; - private static final int VALIDATION_RESULT_PARTIAL = VALIDATION_RESULT_BASE - | NETWORK_VALIDATION_PROBE_FALLBACK - | NETWORK_VALIDATION_RESULT_PARTIAL; private static final int VALIDATION_RESULT_INVALID = 0; private static final long DATA_STALL_TIMESTAMP = 10L; @@ -595,12 +588,10 @@ public class ConnectivityServiceTest { private INetworkMonitor mNetworkMonitor; private INetworkMonitorCallbacks mNmCallbacks; - private int mNmValidationResult = VALIDATION_RESULT_BASE; + private int mNmValidationResult = VALIDATION_RESULT_INVALID; private int mProbesCompleted; private int mProbesSucceeded; private String mNmValidationRedirectUrl = null; - private PersistableBundle mValidationExtras = PersistableBundle.EMPTY; - private PersistableBundle mDataStallExtras = PersistableBundle.EMPTY; private boolean mNmProvNotificationRequested = false; private final ConditionVariable mNetworkStatusReceived = new ConditionVariable(); @@ -668,8 +659,13 @@ public class ConnectivityServiceTest { } mNmCallbacks.notifyProbeStatusChanged(mProbesCompleted, mProbesSucceeded); - mNmCallbacks.notifyNetworkTestedWithExtras( - mNmValidationResult, mNmValidationRedirectUrl, TIMESTAMP, mValidationExtras); + final NetworkTestResultParcelable p = new NetworkTestResultParcelable(); + p.result = mNmValidationResult; + p.probesAttempted = mProbesCompleted; + p.probesSucceeded = mProbesSucceeded; + p.redirectUrl = mNmValidationRedirectUrl; + p.timestampMillis = TIMESTAMP; + mNmCallbacks.notifyNetworkTestedWithExtras(p); if (mNmValidationRedirectUrl != null) { mNmCallbacks.showProvisioningNotification( @@ -751,9 +747,9 @@ public class ConnectivityServiceTest { } void setNetworkValid(boolean isStrictMode) { - mNmValidationResult = VALIDATION_RESULT_VALID; + mNmValidationResult = NETWORK_VALIDATION_RESULT_VALID; mNmValidationRedirectUrl = null; - int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTP; + int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS; if (isStrictMode) { probesSucceeded |= NETWORK_VALIDATION_PROBE_PRIVDNS; } @@ -765,8 +761,9 @@ public class ConnectivityServiceTest { void setNetworkInvalid(boolean isStrictMode) { mNmValidationResult = VALIDATION_RESULT_INVALID; mNmValidationRedirectUrl = null; - int probesCompleted = VALIDATION_RESULT_BASE; - int probesSucceeded = VALIDATION_RESULT_INVALID; + int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS + | NETWORK_VALIDATION_PROBE_HTTP; + int probesSucceeded = 0; // If the isStrictMode is true, it means the network is invalid when NetworkMonitor // tried to validate the private DNS but failed. if (isStrictMode) { @@ -782,7 +779,7 @@ public class ConnectivityServiceTest { mNmValidationRedirectUrl = redirectUrl; // Suppose the portal is found when NetworkMonitor probes NETWORK_VALIDATION_PROBE_HTTP // in the beginning, so the NETWORK_VALIDATION_PROBE_HTTPS hasn't probed yet. - int probesCompleted = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS; + int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP; int probesSucceeded = VALIDATION_RESULT_INVALID; if (isStrictMode) { probesCompleted |= NETWORK_VALIDATION_PROBE_PRIVDNS; @@ -791,18 +788,20 @@ public class ConnectivityServiceTest { } void setNetworkPartial() { - mNmValidationResult = VALIDATION_RESULT_PARTIAL; + mNmValidationResult = NETWORK_VALIDATION_RESULT_PARTIAL; mNmValidationRedirectUrl = null; - int probesCompleted = VALIDATION_RESULT_BASE; - int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS; + int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS + | NETWORK_VALIDATION_PROBE_FALLBACK; + int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_FALLBACK; setProbesStatus(probesCompleted, probesSucceeded); } void setNetworkPartialValid(boolean isStrictMode) { setNetworkPartial(); - mNmValidationResult |= VALIDATION_RESULT_VALID; - int probesCompleted = VALIDATION_RESULT_BASE; - int probesSucceeded = VALIDATION_RESULT_BASE & ~NETWORK_VALIDATION_PROBE_HTTPS; + mNmValidationResult |= NETWORK_VALIDATION_RESULT_VALID; + int probesCompleted = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS + | NETWORK_VALIDATION_PROBE_HTTP; + int probesSucceeded = NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTP; // Suppose the partial network cannot pass the private DNS validation as well, so only // add NETWORK_VALIDATION_PROBE_DNS in probesCompleted but not probesSucceeded. if (isStrictMode) { @@ -838,8 +837,10 @@ public class ConnectivityServiceTest { } void notifyDataStallSuspected() throws Exception { - mNmCallbacks.notifyDataStallSuspected( - DATA_STALL_TIMESTAMP, DATA_STALL_DETECTION_METHOD, mDataStallExtras); + final DataStallReportParcelable p = new DataStallReportParcelable(); + p.detectionMethod = DATA_STALL_DETECTION_METHOD; + p.timestampMillis = DATA_STALL_TIMESTAMP; + mNmCallbacks.notifyDataStallSuspected(p); } } From 3cb1e030829a8327d34ef89e5d6d515c3a6fe94e Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Wed, 29 Apr 2020 13:44:50 +0800 Subject: [PATCH 182/229] Add test prefix into test cases Bug: 152678151 Test: atest com.android.server.net.NetworkStatsFactoryTest Change-Id: I6e18915e383ac20072cb238d0136d7a8e4ceb811 Merged-In: I6e18915e383ac20072cb238d0136d7a8e4ceb811 --- .../server/net/NetworkStatsFactoryTest.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java index a21f5095c7..5ab2e323b6 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java @@ -104,7 +104,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnRewriteTrafficThroughItself() throws Exception { + public void testVpnRewriteTrafficThroughItself() throws Exception { VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; mFactory.updateVpnInfos(vpnInfos); @@ -133,7 +133,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithClat() throws Exception { + public void testVpnWithClat() throws Exception { VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {CLAT_PREFIX + TEST_IFACE})}; mFactory.updateVpnInfos(vpnInfos); mFactory.noteStackedIface(CLAT_PREFIX + TEST_IFACE, TEST_IFACE); @@ -166,7 +166,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithOneUnderlyingIface() throws Exception { + public void testVpnWithOneUnderlyingIface() throws Exception { VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; mFactory.updateVpnInfos(vpnInfos); @@ -189,7 +189,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithOneUnderlyingIfaceAndOwnTraffic() throws Exception { + public void testVpnWithOneUnderlyingIfaceAndOwnTraffic() throws Exception { // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE). VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; mFactory.updateVpnInfos(vpnInfos); @@ -217,7 +217,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithOneUnderlyingIface_withCompression() throws Exception { + public void testVpnWithOneUnderlyingIface_withCompression() throws Exception { // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE). VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; mFactory.updateVpnInfos(vpnInfos); @@ -238,7 +238,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithTwoUnderlyingIfaces_packetDuplication() throws Exception { + public void testVpnWithTwoUnderlyingIfaces_packetDuplication() throws Exception { // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set. // Additionally, VPN is duplicating traffic across both WiFi and Cell. @@ -264,7 +264,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithTwoUnderlyingIfaces_splitTraffic() throws Exception { + public void testVpnWithTwoUnderlyingIfaces_splitTraffic() throws Exception { // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set. // Additionally, VPN is arbitrarily splitting traffic across WiFi and Cell. @@ -291,7 +291,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithTwoUnderlyingIfaces_splitTrafficWithCompression() throws Exception { + public void testVpnWithTwoUnderlyingIfaces_splitTrafficWithCompression() throws Exception { // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set. // Additionally, VPN is arbitrarily splitting compressed traffic across WiFi and Cell. @@ -314,7 +314,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { } @Test - public void vpnWithIncorrectUnderlyingIface() throws Exception { + public void testVpnWithIncorrectUnderlyingIface() throws Exception { // WiFi and Cell networks are connected and VPN is using Cell (which has TEST_IFACE2), // but has declared only WiFi (TEST_IFACE) in its underlying network set. VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})}; From bd162416785c0b157e600da633e27127927fffed Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Tue, 28 Apr 2020 22:15:56 +0800 Subject: [PATCH 183/229] Filter debug entries for each vpn NetworkStats calculation needs to filter out debug entries to prevent over counting. While NetworkStatsFactory migrates data usage over a VPN to the TUN network, NetworkStatsFactory does not filter out debug entries per vpn which will cause debug entries left and cause exception. Bug: 152678151 Test: atest com.android.server.net.NetworkStatsFactoryTest and verify no exception Change-Id: I3525edc385b07858b48c7add2d331c4b5a2e84ad Merged-In: I3525edc385b07858b48c7add2d331c4b5a2e84ad --- .../server/net/NetworkStatsBaseTest.java | 9 ++++- .../server/net/NetworkStatsFactoryTest.java | 40 +++++++++++++++++++ .../raw/xt_qtaguid_vpn_one_underlying_two_vpn | 9 +++++ 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 tests/net/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn diff --git a/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java b/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java index 28785f7c97..3aafe0b075 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java @@ -41,6 +41,7 @@ abstract class NetworkStatsBaseTest { static final String TEST_IFACE = "test0"; static final String TEST_IFACE2 = "test1"; static final String TUN_IFACE = "test_nss_tun0"; + static final String TUN_IFACE2 = "test_nss_tun1"; static final int UID_RED = 1001; static final int UID_BLUE = 1002; @@ -107,10 +108,14 @@ abstract class NetworkStatsBaseTest { assertEquals("unexpected operations", operations, entry.operations); } - VpnInfo createVpnInfo(String[] underlyingIfaces) { + static VpnInfo createVpnInfo(String[] underlyingIfaces) { + return createVpnInfo(TUN_IFACE, underlyingIfaces); + } + + static VpnInfo createVpnInfo(String vpnIface, String[] underlyingIfaces) { VpnInfo info = new VpnInfo(); info.ownerUid = UID_VPN; - info.vpnIface = TUN_IFACE; + info.vpnIface = vpnIface; info.underlyingIfaces = underlyingIfaces; return info; } diff --git a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java index 5ab2e323b6..4473492d79 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java @@ -263,6 +263,46 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { assertValues(tunStats, TEST_IFACE2, UID_VPN, 1200L, 100L, 1200L, 100L); } + @Test + public void testConcurrentVpns() throws Exception { + // Assume two VPNs are connected on two different network interfaces. VPN1 is using + // TEST_IFACE and VPN2 is using TEST_IFACE2. + final VpnInfo[] vpnInfos = new VpnInfo[] { + createVpnInfo(TUN_IFACE, new String[] {TEST_IFACE}), + createVpnInfo(TUN_IFACE2, new String[] {TEST_IFACE2})}; + mFactory.updateVpnInfos(vpnInfos); + + // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption + // overhead per packet): + // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED + // over VPN1. + // 700 bytes (70 packets) were sent, and 3000 bytes (300 packets) were received by UID_RED + // over VPN2. + // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE + // over VPN1. + // 250 bytes (25 packets) were sent, and 500 bytes (50 packets) were received by UID_BLUE + // over VPN2. + // VPN1 sent 1650 bytes (150 packets), and received 3300 (300 packets) over TEST_IFACE. + // Of 1650 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes + // attributed to UID_BLUE, and 150 bytes attributed to UID_VPN. + // Of 3300 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes + // attributed to UID_BLUE, and 300 bytes attributed to UID_VPN. + // VPN2 sent 1045 bytes (95 packets), and received 3850 (350 packets) over TEST_IFACE2. + // Of 1045 bytes sent over Cell, expect 700 bytes attributed to UID_RED, 250 bytes + // attributed to UID_BLUE, and 95 bytes attributed to UID_VPN. + // Of 3850 bytes received over Cell, expect 3000 bytes attributed to UID_RED, 500 bytes + // attributed to UID_BLUE, and 350 bytes attributed to UID_VPN. + final NetworkStats tunStats = + parseDetailedStats(R.raw.xt_qtaguid_vpn_one_underlying_two_vpn); + + assertValues(tunStats, TEST_IFACE, UID_RED, 2000L, 200L, 1000L, 100L); + assertValues(tunStats, TEST_IFACE, UID_BLUE, 1000L, 100L, 500L, 50L); + assertValues(tunStats, TEST_IFACE2, UID_RED, 3000L, 300L, 700L, 70L); + assertValues(tunStats, TEST_IFACE2, UID_BLUE, 500L, 50L, 250L, 25L); + assertValues(tunStats, TEST_IFACE, UID_VPN, 300L, 0L, 150L, 0L); + assertValues(tunStats, TEST_IFACE2, UID_VPN, 350L, 0L, 95L, 0L); + } + @Test public void testVpnWithTwoUnderlyingIfaces_splitTraffic() throws Exception { // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and diff --git a/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn b/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn new file mode 100644 index 0000000000..eb0513b100 --- /dev/null +++ b/tests/net/res/raw/xt_qtaguid_vpn_one_underlying_two_vpn @@ -0,0 +1,9 @@ +idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets +2 test_nss_tun0 0x0 1001 0 2000 200 1000 100 0 0 0 0 0 0 0 0 0 0 0 0 +3 test_nss_tun0 0x0 1002 0 1000 100 500 50 0 0 0 0 0 0 0 0 0 0 0 0 +4 test_nss_tun1 0x0 1001 0 3000 300 700 70 0 0 0 0 0 0 0 0 0 0 0 0 +5 test_nss_tun1 0x0 1002 0 500 50 250 25 0 0 0 0 0 0 0 0 0 0 0 0 +6 test0 0x0 1004 0 3300 300 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +7 test0 0x0 1004 1 0 0 1650 150 0 0 0 0 0 0 0 0 0 0 0 0 +8 test1 0x0 1004 0 3850 350 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +9 test1 0x0 1004 1 0 0 1045 95 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file From 0fff1ed7b909b448f5241c87c4d3804877761088 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 28 Apr 2020 19:26:15 +0000 Subject: [PATCH 184/229] Add filtering for IPsec algorithms in IKEv2 VPNs This commit adds support for validating and filtering IPsec algorithms. Without a public API exposing IKEv2 algorithms (and their respective public APIs), the allowedAlgorithms can only filter the proposals for IPsec (Child) SA algorithms. Additionally, this removes the HMAC_SHA1 from the IKE SA's integrity algorithm proposals due to insecurity Bug: 153701879 Test: FrameworksNetTests passing, new tests added Change-Id: I7e61a1612692db275b751330af5bacbf86836a8c Merged-In: I7e61a1612692db275b751330af5bacbf86836a8c (cherry picked from commit 94e1c08a9ad4b0ff17e0f3a77fff0d3364040ba5) --- .../java/android/net/Ikev2VpnProfileTest.java | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/tests/net/java/android/net/Ikev2VpnProfileTest.java b/tests/net/java/android/net/Ikev2VpnProfileTest.java index 2273bc6122..ada5494efd 100644 --- a/tests/net/java/android/net/Ikev2VpnProfileTest.java +++ b/tests/net/java/android/net/Ikev2VpnProfileTest.java @@ -40,7 +40,10 @@ import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; +import java.util.List; import java.util.concurrent.TimeUnit; import javax.security.auth.x500.X500Principal; @@ -106,6 +109,7 @@ public class Ikev2VpnProfileTest { assertTrue(profile.isBypassable()); assertTrue(profile.isMetered()); assertEquals(TEST_MTU, profile.getMaxMtu()); + assertEquals(Ikev2VpnProfile.DEFAULT_ALGORITHMS, profile.getAllowedAlgorithms()); } @Test @@ -159,6 +163,78 @@ public class Ikev2VpnProfileTest { assertNull(profile.getUserCert()); } + @Test + public void testBuildWithAllowedAlgorithmsAead() throws Exception { + final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); + builder.setAuthPsk(PSK_BYTES); + + List allowedAlgorithms = Arrays.asList(IpSecAlgorithm.AUTH_CRYPT_AES_GCM); + builder.setAllowedAlgorithms(allowedAlgorithms); + + final Ikev2VpnProfile profile = builder.build(); + assertEquals(allowedAlgorithms, profile.getAllowedAlgorithms()); + } + + @Test + public void testBuildWithAllowedAlgorithmsNormal() throws Exception { + final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); + builder.setAuthPsk(PSK_BYTES); + + List allowedAlgorithms = + Arrays.asList(IpSecAlgorithm.AUTH_HMAC_SHA512, IpSecAlgorithm.CRYPT_AES_CBC); + builder.setAllowedAlgorithms(allowedAlgorithms); + + final Ikev2VpnProfile profile = builder.build(); + assertEquals(allowedAlgorithms, profile.getAllowedAlgorithms()); + } + + @Test + public void testSetAllowedAlgorithmsEmptyList() throws Exception { + final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); + + try { + builder.setAllowedAlgorithms(new ArrayList<>()); + fail("Expected exception due to no valid algorithm set"); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void testSetAllowedAlgorithmsInvalidList() throws Exception { + final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); + List allowedAlgorithms = new ArrayList<>(); + + try { + builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.AUTH_HMAC_SHA256)); + fail("Expected exception due to missing encryption"); + } catch (IllegalArgumentException expected) { + } + + try { + builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.CRYPT_AES_CBC)); + fail("Expected exception due to missing authentication"); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void testSetAllowedAlgorithmsInsecureAlgorithm() throws Exception { + final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); + List allowedAlgorithms = new ArrayList<>(); + + try { + builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.AUTH_HMAC_MD5)); + fail("Expected exception due to insecure algorithm"); + } catch (IllegalArgumentException expected) { + } + + try { + builder.setAllowedAlgorithms(Arrays.asList(IpSecAlgorithm.AUTH_HMAC_SHA1)); + fail("Expected exception due to insecure algorithm"); + } catch (IllegalArgumentException expected) { + } + } + @Test public void testBuildNoAuthMethodSet() throws Exception { final Ikev2VpnProfile.Builder builder = getBuilderWithDefaultOptions(); From 3d3c9f7b76751dda461c9252c52c005241efaa69 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 27 Apr 2020 08:08:57 +0000 Subject: [PATCH 185/229] Add comment / logging in NetworkMonitor callbacks Add a comment explaining the ordering of messages sent to the tracker and connectivity diagnostics handlers. Add a Slog.wtf call in case the deprecated notifyNetworkTested callback is called. Bug: 153500847 Test: atest ConnectivityServiceTest Merged-In: I2dbfc9bf7b2f785ea4594851bd354e9fd0fc0bd1 Change-Id: I2dbfc9bf7b2f785ea4594851bd354e9fd0fc0bd1 --- services/core/java/com/android/server/ConnectivityService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index e4eb585e98..2c63c6f8a6 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3011,10 +3011,13 @@ public class ConnectivityService extends IConnectivityManager.Stub // Legacy version of notifyNetworkTestedWithExtras. // Would only be called if the system has a NetworkStack module older than the // framework, which does not happen in practice. + Slog.wtf(TAG, "Deprecated notifyNetworkTested called: no action taken"); } @Override public void notifyNetworkTestedWithExtras(NetworkTestResultParcelable p) { + // Notify mTrackerHandler and mConnectivityDiagnosticsHandler of the event. Both use + // the same looper so messages will be processed in sequence. final Message msg = mTrackerHandler.obtainMessage( EVENT_NETWORK_TESTED, new NetworkTestedResults( From 2d70990d2c3e1793681c2360dd597283515df3ac Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 3 Oct 2019 11:09:00 -0700 Subject: [PATCH 186/229] Use TransformRecord to get SPI instead of SpiRecord IpSecService.applyTunnelModeTransform() currently does not take an SpiRecord instance, yet implicitly requires that the SpiRecord instance is still alive based on the stored SpiRecord resourceId in the TransformRecord's IpSecConfig. This check is unnecessary, as the SpiRecord has been subsumed into the TransformRecord, and the kernel resources are kept alive whether or not the SpiRecord is still held by the user. This allows users of the IpSecManager API to allocate short-lived SPIs during the creation of an IpSecTransform, without having to keep track of both of them (even though the SPI is no longer usable). The TransformRecord.getSpiRecord() call is already used in multiple other places in the same method. Bug: 142072071 Test: New tests added, passing. Change-Id: I1959f3080946267243564459ff4207647922566e Merged-In: I1959f3080946267243564459ff4207647922566e (cherry picked from commit 5258b1b82f39bf17e0751bcb94479464250aaec5) --- .../server/IpSecServiceParameterizedTest.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 23098ec067..84d09e26a8 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -571,6 +571,35 @@ public class IpSecServiceParameterizedTest { eq(TEST_SPI)); } + @Test + public void testApplyTransportModeTransformWithClosedSpi() throws Exception { + IpSecConfig ipSecConfig = new IpSecConfig(); + addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); + addAuthAndCryptToIpSecConfig(ipSecConfig); + + IpSecTransformResponse createTransformResp = + mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + + // Close SPI record + mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); + + Socket socket = new Socket(); + socket.bind(null); + ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); + + int resourceId = createTransformResp.resourceId; + mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId); + + verify(mMockNetd) + .ipSecApplyTransportModeTransform( + eq(pfd), + eq(mUid), + eq(IpSecManager.DIRECTION_OUT), + anyString(), + anyString(), + eq(TEST_SPI)); + } + @Test public void testRemoveTransportModeTransform() throws Exception { Socket socket = new Socket(); @@ -693,6 +722,45 @@ public class IpSecServiceParameterizedTest { verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); } + + @Test + public void testApplyTunnelModeTransformWithClosedSpi() throws Exception { + IpSecConfig ipSecConfig = new IpSecConfig(); + ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); + addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); + addAuthAndCryptToIpSecConfig(ipSecConfig); + + IpSecTransformResponse createTransformResp = + mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + IpSecTunnelInterfaceResponse createTunnelResp = + createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage"); + + // Close SPI record + mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); + + int transformResourceId = createTransformResp.resourceId; + int tunnelResourceId = createTunnelResp.resourceId; + mIpSecService.applyTunnelModeTransform(tunnelResourceId, IpSecManager.DIRECTION_OUT, + transformResourceId, "blessedPackage"); + + for (int selAddrFamily : ADDRESS_FAMILIES) { + verify(mMockNetd) + .ipSecUpdateSecurityPolicy( + eq(mUid), + eq(selAddrFamily), + eq(IpSecManager.DIRECTION_OUT), + anyString(), + anyString(), + eq(TEST_SPI), + anyInt(), // iKey/oKey + anyInt(), // mask + eq(tunnelResourceId)); + } + + ipSecConfig.setXfrmInterfaceId(tunnelResourceId); + verifyTransformNetdCalledForCreatingSA(ipSecConfig, createTransformResp); + } + @Test public void testAddRemoveAddressFromTunnelInterface() throws Exception { for (String pkgName : new String[]{"blessedPackage", "systemPackage"}) { From bfd3c75dce408d166fcb243b11fdfc3b34d6d9b2 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Tue, 10 Mar 2020 23:38:04 -0700 Subject: [PATCH 187/229] Add tests for Tunnel, Transport mode application with released SPIs This change adds tests to validate that both transport and tunnel mode transforms continue to work even after the SPI resource has been released. Specifically, since SPI resources are effectively subsumed by the creation of a Transform, the SPI resource is still "alive", but removed from the user-tracking sparse arrays. Bug: 142072071 Test: Added these new tests. Failing prior to aosp/1133555, passes with. Change-Id: I37dd459d08b57b14f72f3b28ea80fa231b152f10 Merged-In: I37dd459d08b57b14f72f3b28ea80fa231b152f10 (cherry picked from commit 4d3f871a944d24cd7cbe3aa51a789a71020eafb5) --- .../server/IpSecServiceParameterizedTest.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index 84d09e26a8..529d03c520 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -547,6 +547,16 @@ public class IpSecServiceParameterizedTest { @Test public void testApplyTransportModeTransform() throws Exception { + verifyApplyTransportModeTransformCommon(false); + } + + @Test + public void testApplyTransportModeTransformReleasedSpi() throws Exception { + verifyApplyTransportModeTransformCommon(true); + } + + public void verifyApplyTransportModeTransformCommon( + boolean closeSpiBeforeApply) throws Exception { IpSecConfig ipSecConfig = new IpSecConfig(); addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); addAuthAndCryptToIpSecConfig(ipSecConfig); @@ -554,6 +564,10 @@ public class IpSecServiceParameterizedTest { IpSecTransformResponse createTransformResp = mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); + if (closeSpiBeforeApply) { + mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); + } + Socket socket = new Socket(); socket.bind(null); ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); @@ -689,6 +703,15 @@ public class IpSecServiceParameterizedTest { @Test public void testApplyTunnelModeTransform() throws Exception { + verifyApplyTunnelModeTransformCommon(false); + } + + @Test + public void testApplyTunnelModeTransformReleasedSpi() throws Exception { + verifyApplyTunnelModeTransformCommon(true); + } + + public void verifyApplyTunnelModeTransformCommon(boolean closeSpiBeforeApply) throws Exception { IpSecConfig ipSecConfig = new IpSecConfig(); ipSecConfig.setMode(IpSecTransform.MODE_TUNNEL); addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig); @@ -699,6 +722,10 @@ public class IpSecServiceParameterizedTest { IpSecTunnelInterfaceResponse createTunnelResp = createAndValidateTunnel(mSourceAddr, mDestinationAddr, "blessedPackage"); + if (closeSpiBeforeApply) { + mIpSecService.releaseSecurityParameterIndex(ipSecConfig.getSpiResourceId()); + } + int transformResourceId = createTransformResp.resourceId; int tunnelResourceId = createTunnelResp.resourceId; mIpSecService.applyTunnelModeTransform(tunnelResourceId, IpSecManager.DIRECTION_OUT, From 2c4a47d65ce5bd424d76c5a9259904c3e7b29063 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Tue, 12 May 2020 08:53:53 +0000 Subject: [PATCH 188/229] Send full LinkProperties to NetworkMonitor Set the parcelSensitiveFields bit when sending LinkProperties to NetworkMonitor, so that the captive portal API URL is not lost. Test: atest ConnectivityServiceIntegrationTest (see followup change) Bug: 156062304 Original-Change: https://android-review.googlesource.com/1307833 Merged-In: Ifd4e9c02a6b9a2b2b8b254fc4da7bfb9e0a84550 Change-Id: Ifd4e9c02a6b9a2b2b8b254fc4da7bfb9e0a84550 --- .../core/java/com/android/server/ConnectivityService.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2c63c6f8a6..4db00e3c5f 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5973,7 +5973,8 @@ public class ConnectivityService extends IConnectivityManager.Stub // Start or stop DNS64 detection and 464xlat according to network state. networkAgent.clatd.update(); notifyIfacesChangedForNetworkStats(); - networkAgent.networkMonitor().notifyLinkPropertiesChanged(newLp); + networkAgent.networkMonitor().notifyLinkPropertiesChanged( + new LinkProperties(newLp, true /* parcelSensitiveFields */)); if (networkAgent.everConnected) { notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED); } @@ -7153,7 +7154,9 @@ public class ConnectivityService extends IConnectivityManager.Stub networkAgent.networkMonitor().setAcceptPartialConnectivity(); } networkAgent.networkMonitor().notifyNetworkConnected( - networkAgent.linkProperties, networkAgent.networkCapabilities); + new LinkProperties(networkAgent.linkProperties, + true /* parcelSensitiveFields */), + networkAgent.networkCapabilities); scheduleUnvalidatedPrompt(networkAgent); // Whether a particular NetworkRequest listen should cause signal strength thresholds to From a9b761d2612b59b5e7c8e1adc86b173e47e5cc57 Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Tue, 12 May 2020 18:47:10 +0000 Subject: [PATCH 189/229] Set owner and administrator UIDs for test networks. This change sets the owner and administrator UIDs for test networks when their initial values match the UID for the app creating the test network. This ensures that apps registering test networks can only make themselves owners / administrators of the network. Bug: 153449964 Test: atest NetworkAgentTest Change-Id: I3a974700aa1d83cb285295ed1de0aa263e2e5b58 Merged-In: I3a974700aa1d83cb285295ed1de0aa263e2e5b58 (cherry picked from commit 35782280a2adceec96b8e03c217788afa05894a0) --- .../java/android/net/NetworkCapabilities.java | 13 ++++- .../android/server/ConnectivityService.java | 6 +- .../android/server/TestNetworkService.java | 57 +++++++++---------- .../server/connectivity/NetworkAgentInfo.java | 7 ++- .../server/ConnectivityServiceTest.java | 13 +++-- .../connectivity/LingerMonitorTest.java | 3 +- 6 files changed, 56 insertions(+), 43 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 52d6fdfbd5..9ded22fb70 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -677,16 +677,27 @@ public final class NetworkCapabilities implements Parcelable { * restrictions. * @hide */ - public void restrictCapabilitesForTestNetwork() { + public void restrictCapabilitesForTestNetwork(int creatorUid) { final long originalCapabilities = mNetworkCapabilities; final NetworkSpecifier originalSpecifier = mNetworkSpecifier; final int originalSignalStrength = mSignalStrength; + final int originalOwnerUid = getOwnerUid(); + final int[] originalAdministratorUids = getAdministratorUids(); clearAll(); // Reset the transports to only contain TRANSPORT_TEST. mTransportTypes = (1 << TRANSPORT_TEST); mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES; mNetworkSpecifier = originalSpecifier; mSignalStrength = originalSignalStrength; + + // Only retain the owner and administrator UIDs if they match the app registering the remote + // caller that registered the network. + if (originalOwnerUid == creatorUid) { + setOwnerUid(creatorUid); + } + if (ArrayUtils.contains(originalAdministratorUids, creatorUid)) { + setAdministratorUids(new int[] {creatorUid}); + } } /** diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2c63c6f8a6..8ca6951aef 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2740,7 +2740,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // the Messenger, but if this ever changes, not making a defensive copy // here will give attack vectors to clients using this code path. networkCapabilities = new NetworkCapabilities(networkCapabilities); - networkCapabilities.restrictCapabilitesForTestNetwork(); + networkCapabilities.restrictCapabilitesForTestNetwork(nai.creatorUid); } updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities); break; @@ -5859,7 +5859,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // the call to mixInCapabilities below anyway, but sanitizing here means the NAI never // sees capabilities that may be malicious, which might prevent mistakes in the future. networkCapabilities = new NetworkCapabilities(networkCapabilities); - networkCapabilities.restrictCapabilitesForTestNetwork(); + networkCapabilities.restrictCapabilitesForTestNetwork(Binder.getCallingUid()); } else { enforceNetworkFactoryPermission(); } @@ -5872,7 +5872,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), new Network(mNetIdManager.reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig), - this, mNetd, mDnsResolver, mNMS, providerId); + this, mNetd, mDnsResolver, mNMS, providerId, Binder.getCallingUid()); // Make sure the LinkProperties and NetworkCapabilities reflect what the agent info says. nai.getAndSetNetworkCapabilities(mixInCapabilities(nai, nc)); diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index 0ea73460e1..d6bd5a1d7c 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -317,39 +317,34 @@ class TestNetworkService extends ITestNetworkManager.Stub { "Cannot create network for non ipsec, non-testtun interface"); } - // Setup needs to be done with NETWORK_STACK privileges. - int callingUid = Binder.getCallingUid(); - Binder.withCleanCallingIdentity( - () -> { - try { - mNMS.setInterfaceUp(iface); + try { + // This requires NETWORK_STACK privileges. + Binder.withCleanCallingIdentity(() -> mNMS.setInterfaceUp(iface)); - // Synchronize all accesses to mTestNetworkTracker to prevent the case - // where: - // 1. TestNetworkAgent successfully binds to death of binder - // 2. Before it is added to the mTestNetworkTracker, binder dies, - // binderDied() is called (on a different thread) - // 3. This thread is pre-empted, put() is called after remove() - synchronized (mTestNetworkTracker) { - TestNetworkAgent agent = - registerTestNetworkAgent( - mHandler.getLooper(), - mContext, - iface, - lp, - isMetered, - callingUid, - administratorUids, - binder); + // Synchronize all accesses to mTestNetworkTracker to prevent the case where: + // 1. TestNetworkAgent successfully binds to death of binder + // 2. Before it is added to the mTestNetworkTracker, binder dies, binderDied() is called + // (on a different thread) + // 3. This thread is pre-empted, put() is called after remove() + synchronized (mTestNetworkTracker) { + TestNetworkAgent agent = + registerTestNetworkAgent( + mHandler.getLooper(), + mContext, + iface, + lp, + isMetered, + Binder.getCallingUid(), + administratorUids, + binder); - mTestNetworkTracker.put(agent.getNetwork().netId, agent); - } - } catch (SocketException e) { - throw new UncheckedIOException(e); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - }); + mTestNetworkTracker.put(agent.getNetwork().netId, agent); + } + } catch (SocketException e) { + throw new UncheckedIOException(e); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** Teardown a test network */ diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index 15628f03ba..37b2de1070 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -168,6 +168,9 @@ public class NetworkAgentInfo implements Comparable { // Obtained by ConnectivityService and merged into NetworkAgent-provided information. public CaptivePortalData captivePortalData; + // The UID of the remote entity that created this Network. + public final int creatorUid; + // Networks are lingered when they become unneeded as a result of their NetworkRequests being // satisfied by a higher-scoring network. so as to allow communication to wrap up before the // network is taken down. This usually only happens to the default network. Lingering ends with @@ -268,7 +271,8 @@ public class NetworkAgentInfo implements Comparable { public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info, LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd, - IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) { + IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber, + int creatorUid) { this.messenger = messenger; asyncChannel = ac; network = net; @@ -282,6 +286,7 @@ public class NetworkAgentInfo implements Comparable { mHandler = handler; networkAgentConfig = config; this.factorySerialNumber = factorySerialNumber; + this.creatorUid = creatorUid; } /** diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index a992778fd4..d2b26d3bfd 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -75,6 +75,7 @@ import static android.net.NetworkPolicyManager.RULE_NONE; import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import static android.net.RouteInfo.RTN_UNREACHABLE; +import static android.os.Process.INVALID_UID; import static android.system.OsConstants.IPPROTO_TCP; import static com.android.server.ConnectivityServiceTestUtilsKt.transportToLegacyType; @@ -6945,7 +6946,7 @@ public class ConnectivityServiceTest { final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( null, null, null, null, null, new NetworkCapabilities(), 0, - mServiceContext, null, null, mService, null, null, null, 0); + mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); mServiceContext.setPermission( android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED); @@ -6961,7 +6962,7 @@ public class ConnectivityServiceTest { final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( null, null, null, null, null, new NetworkCapabilities(), 0, - mServiceContext, null, null, mService, null, null, null, 0); + mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); @@ -6977,7 +6978,7 @@ public class ConnectivityServiceTest { final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( null, null, null, null, null, new NetworkCapabilities(), 0, - mServiceContext, null, null, mService, null, null, null, 0); + mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); @@ -6994,7 +6995,7 @@ public class ConnectivityServiceTest { final NetworkAgentInfo naiWithoutUid = new NetworkAgentInfo( null, null, network, null, null, new NetworkCapabilities(), 0, - mServiceContext, null, null, mService, null, null, null, 0); + mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); @@ -7028,7 +7029,7 @@ public class ConnectivityServiceTest { final NetworkAgentInfo naiWithUid = new NetworkAgentInfo( null, null, null, null, null, nc, 0, mServiceContext, null, null, - mService, null, null, null, 0); + mService, null, null, null, 0, INVALID_UID); setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); @@ -7050,7 +7051,7 @@ public class ConnectivityServiceTest { final NetworkAgentInfo naiWithUid = new NetworkAgentInfo( null, null, null, null, null, nc, 0, mServiceContext, null, null, - mService, null, null, null, 0); + mService, null, null, null, 0, INVALID_UID); setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION); diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java index 24a8717722..aafa18a532 100644 --- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java @@ -38,6 +38,7 @@ import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.net.NetworkProvider; +import android.os.Binder; import android.os.INetworkManagementService; import android.text.format.DateUtils; @@ -354,7 +355,7 @@ public class LingerMonitorTest { caps.addTransportType(transport); NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null, caps, 50, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS, - NetworkProvider.ID_NONE); + NetworkProvider.ID_NONE, Binder.getCallingUid()); nai.everValidated = true; return nai; } From 9ddf8a5953d62eefff73303bba6db40c6ac04388 Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Tue, 12 May 2020 18:48:04 +0000 Subject: [PATCH 190/229] Create TestApi for simulating a Data Stall on ConnectivityService. This change adds a TestApi for simulating a Data Stall to ConnectivityService. This allows for Data Stalls to be triggered without having to manipulate the signals used by NetworkMonitor . This also allows NetworkMonitor to update the ways it detects Data Stalls without affecting CTS tests for ConnectivityDiagnosticsManager. Bug: 148032944 Test: atest ConnectivityDiagnosticsManagerTest Change-Id: Icad439efa2ab4c872c21d3ee6ceaae8c5b49f18d Merged-In: Icad439efa2ab4c872c21d3ee6ceaae8c5b49f18d (cherry picked from commit b06463a002eb6215e9dda64e599eabd74cb56382) --- .../java/android/net/ConnectivityManager.java | 25 +++++++++++ .../android/net/IConnectivityManager.aidl | 5 +++ .../android/server/ConnectivityService.java | 44 +++++++++++++++---- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 7332ede0b9..36ffe50ef8 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -48,6 +48,7 @@ import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; @@ -4693,4 +4694,28 @@ public class ConnectivityManager { Log.d(TAG, "StackLog:" + sb.toString()); } } + + /** + * Simulates a Data Stall for the specified Network. + * + *

    The caller must be the owner of the specified Network. + * + * @param detectionMethod The detection method used to identify the Data Stall. + * @param timestampMillis The timestamp at which the stall 'occurred', in milliseconds. + * @param network The Network for which a Data Stall is being simluated. + * @param extras The PersistableBundle of extras included in the Data Stall notification. + * @throws SecurityException if the caller is not the owner of the given network. + * @hide + */ + @TestApi + @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_TEST_NETWORKS, + android.Manifest.permission.NETWORK_STACK}) + public void simulateDataStall(int detectionMethod, long timestampMillis, + @NonNull Network network, @NonNull PersistableBundle extras) { + try { + mService.simulateDataStall(detectionMethod, timestampMillis, network, extras); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 14345608e9..69a47f24a0 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -18,6 +18,7 @@ package android.net; import android.app.PendingIntent; import android.net.ConnectionInfo; +import android.net.ConnectivityDiagnosticsManager; import android.net.IConnectivityDiagnosticsCallback; import android.net.LinkProperties; import android.net.Network; @@ -33,6 +34,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.Messenger; import android.os.ParcelFileDescriptor; +import android.os.PersistableBundle; import android.os.ResultReceiver; import com.android.internal.net.LegacyVpnInfo; @@ -227,4 +229,7 @@ interface IConnectivityManager void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback); IBinder startOrGetTestNetworkService(); + + void simulateDataStall(int detectionMethod, long timestampMillis, in Network network, + in PersistableBundle extras); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 8ca6951aef..629c580afc 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3087,10 +3087,6 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void notifyDataStallSuspected(DataStallReportParcelable p) { - final Message msg = mConnectivityDiagnosticsHandler.obtainMessage( - ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, - p.detectionMethod, mNetId, p.timestampMillis); - final PersistableBundle extras = new PersistableBundle(); switch (p.detectionMethod) { case DETECTION_METHOD_DNS_EVENTS: @@ -3105,12 +3101,9 @@ public class ConnectivityService extends IConnectivityManager.Stub log("Unknown data stall detection method, ignoring: " + p.detectionMethod); return; } - msg.setData(new Bundle(extras)); - // NetworkStateTrackerHandler currently doesn't take any actions based on data - // stalls so send the message directly to ConnectivityDiagnosticsHandler and avoid - // the cost of going through two handlers. - mConnectivityDiagnosticsHandler.sendMessage(msg); + proxyDataStallToConnectivityDiagnosticsHandler( + p.detectionMethod, mNetId, p.timestampMillis, extras); } @Override @@ -3124,6 +3117,19 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private void proxyDataStallToConnectivityDiagnosticsHandler(int detectionMethod, int netId, + long timestampMillis, @NonNull PersistableBundle extras) { + final Message msg = mConnectivityDiagnosticsHandler.obtainMessage( + ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, + detectionMethod, netId, timestampMillis); + msg.setData(new Bundle(extras)); + + // NetworkStateTrackerHandler currently doesn't take any actions based on data + // stalls so send the message directly to ConnectivityDiagnosticsHandler and avoid + // the cost of going through two handlers. + mConnectivityDiagnosticsHandler.sendMessage(msg); + } + private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) { return isPrivateDnsValidationRequired(nai.networkCapabilities); } @@ -8151,4 +8157,24 @@ public class ConnectivityService extends IConnectivityManager.Stub 0, callback)); } + + @Override + public void simulateDataStall(int detectionMethod, long timestampMillis, + @NonNull Network network, @NonNull PersistableBundle extras) { + enforceAnyPermissionOf(android.Manifest.permission.MANAGE_TEST_NETWORKS, + android.Manifest.permission.NETWORK_STACK); + final NetworkCapabilities nc = getNetworkCapabilitiesInternal(network); + if (!nc.hasTransport(TRANSPORT_TEST)) { + throw new SecurityException("Data Stall simluation is only possible for test networks"); + } + + final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); + if (nai == null || nai.creatorUid != Binder.getCallingUid()) { + throw new SecurityException("Data Stall simulation is only possible for network " + + "creators"); + } + + proxyDataStallToConnectivityDiagnosticsHandler( + detectionMethod, network.netId, timestampMillis, extras); + } } From 05c7af6c7c884172929d919abcab6dce8f415afa Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 1 May 2020 04:47:17 +0000 Subject: [PATCH 191/229] Use the new NetworkStackConnector constructor The constructor was changed to allow for unit tests. Bug: 137328719 Test: atest FrameworksNetIntegrationTests Original-Change: https://android-review.googlesource.com/1295360 Merged-In: I46f247268310e12d420531745a22e93cf3550e89 Change-Id: I46f247268310e12d420531745a22e93cf3550e89 --- .../server/net/integrationtests/TestNetworkStackService.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt index eec3cdbe8d..8c2de4035d 100644 --- a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt +++ b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt @@ -52,7 +52,7 @@ class TestNetworkStackService : Service() { doReturn(mock(IBinder::class.java)).`when`(it).getSystemService(Context.NETD_SERVICE) } - private class TestPermissionChecker : NetworkStackConnector.PermissionChecker() { + private class TestPermissionChecker : NetworkStackService.PermissionChecker() { override fun enforceNetworkStackCallingPermission() = Unit } @@ -62,8 +62,8 @@ class TestNetworkStackService : Service() { override fun sendNetworkConditionsBroadcast(context: Context, broadcast: Intent) = Unit } - private inner class TestNetworkStackConnector(context: Context) : - NetworkStackConnector(context, TestPermissionChecker()) { + private inner class TestNetworkStackConnector(context: Context) : NetworkStackConnector( + context, TestPermissionChecker(), NetworkStackService.Dependencies()) { private val network = Network(TEST_NETID) private val privateDnsBypassNetwork = TestNetwork(TEST_NETID) From 01ca51a90067a9e79d2f11cec84c70816a952e03 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Fri, 15 May 2020 03:50:20 +0000 Subject: [PATCH 192/229] Add methods for IKEv2/IPsec test mode profiles This change adds the ability for IKEv2/IPsec VPN profiles to run on Test Networks. If enabled, the IKEv2/IPsec VPN profiles will request ONLY test networks. Bug: 148582947 Test: FrameworksNetTests passing Test: Added for testing Change-Id: I2511b39b27a1e29ae97907cdb12728d13fb1628f Merged-In: I2511b39b27a1e29ae97907cdb12728d13fb1628f (cherry picked from commit 9e18eeb4a676ef3afc4bc510f18f81213b8edc55) --- .../android/internal/net/VpnProfileTest.java | 47 ++++++++++++++++--- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/tests/net/java/com/android/internal/net/VpnProfileTest.java b/tests/net/java/com/android/internal/net/VpnProfileTest.java index ceca6f0288..e5daa71c30 100644 --- a/tests/net/java/com/android/internal/net/VpnProfileTest.java +++ b/tests/net/java/com/android/internal/net/VpnProfileTest.java @@ -33,7 +33,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; /** Unit tests for {@link VpnProfile}. */ @SmallTest @@ -41,6 +43,9 @@ import java.util.Arrays; public class VpnProfileTest { private static final String DUMMY_PROFILE_KEY = "Test"; + private static final int ENCODED_INDEX_AUTH_PARAMS_INLINE = 23; + private static final int ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS = 24; + @Test public void testDefaults() throws Exception { final VpnProfile p = new VpnProfile(DUMMY_PROFILE_KEY); @@ -67,10 +72,11 @@ public class VpnProfileTest { assertFalse(p.isMetered); assertEquals(1360, p.maxMtu); assertFalse(p.areAuthParamsInline); + assertFalse(p.isRestrictedToTestNetworks); } private VpnProfile getSampleIkev2Profile(String key) { - final VpnProfile p = new VpnProfile(key); + final VpnProfile p = new VpnProfile(key, true /* isRestrictedToTestNetworks */); p.name = "foo"; p.type = VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS; @@ -116,7 +122,7 @@ public class VpnProfileTest { @Test public void testParcelUnparcel() { - assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 22); + assertParcelSane(getSampleIkev2Profile(DUMMY_PROFILE_KEY), 23); } @Test @@ -159,14 +165,41 @@ public class VpnProfileTest { assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooManyValues)); } + private String getEncodedDecodedIkev2ProfileMissingValues(int... missingIndices) { + // Sort to ensure when we remove, we can do it from greatest first. + Arrays.sort(missingIndices); + + final String encoded = new String(getSampleIkev2Profile(DUMMY_PROFILE_KEY).encode()); + final List parts = + new ArrayList<>(Arrays.asList(encoded.split(VpnProfile.VALUE_DELIMITER))); + + // Remove from back first to ensure indexing is consistent. + for (int i = missingIndices.length - 1; i >= 0; i--) { + parts.remove(missingIndices[i]); + } + + return String.join(VpnProfile.VALUE_DELIMITER, parts.toArray(new String[0])); + } + @Test public void testEncodeDecodeInvalidNumberOfValues() { - final VpnProfile profile = getSampleIkev2Profile(DUMMY_PROFILE_KEY); - final String encoded = new String(profile.encode()); - final byte[] tooFewValues = - encoded.substring(0, encoded.lastIndexOf(VpnProfile.VALUE_DELIMITER)).getBytes(); + final String tooFewValues = + getEncodedDecodedIkev2ProfileMissingValues( + ENCODED_INDEX_AUTH_PARAMS_INLINE, + ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */); - assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues)); + assertNull(VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes())); + } + + @Test + public void testEncodeDecodeMissingIsRestrictedToTestNetworks() { + final String tooFewValues = + getEncodedDecodedIkev2ProfileMissingValues( + ENCODED_INDEX_RESTRICTED_TO_TEST_NETWORKS /* missingIndices */); + + // Verify decoding without isRestrictedToTestNetworks defaults to false + final VpnProfile decoded = VpnProfile.decode(DUMMY_PROFILE_KEY, tooFewValues.getBytes()); + assertFalse(decoded.isRestrictedToTestNetworks); } @Test From 15eb17c2fcc013cb16fd739436608ce1c19562fd Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Mon, 18 May 2020 18:57:14 +0000 Subject: [PATCH 193/229] Move Data Stall logic to CS from NetworkMonitorCallbacks. This change moves the logic for handling Data Stall notifications from NetworkMonitorCallbacks to ConnectivityService. This avoids duplicate logic for managing data stall simulation requests from ConnectivityManager. This also puts all of the logic for proxying Data Stall notifications to the ConnectivityDiagnosticsHandler into one place. Bug: 148032944 Test: atest ConnectivityDiagnosticsManagerTest Change-Id: Ie2f6a1a2376c5c452750ab417cb5e8c24fc44fc3 Merged-In: Ie2f6a1a2376c5c452750ab417cb5e8c24fc44fc3 (cherry picked from commit 745eaa39a3c9bcaaa61671f66d8c1180195c84c4) --- .../android/server/ConnectivityService.java | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 119715456f..07503b5143 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3087,23 +3087,7 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public void notifyDataStallSuspected(DataStallReportParcelable p) { - final PersistableBundle extras = new PersistableBundle(); - switch (p.detectionMethod) { - case DETECTION_METHOD_DNS_EVENTS: - extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts); - break; - case DETECTION_METHOD_TCP_METRICS: - extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate); - extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS, - p.tcpMetricsCollectionPeriodMillis); - break; - default: - log("Unknown data stall detection method, ignoring: " + p.detectionMethod); - return; - } - - proxyDataStallToConnectivityDiagnosticsHandler( - p.detectionMethod, mNetId, p.timestampMillis, extras); + ConnectivityService.this.notifyDataStallSuspected(p, mNetId); } @Override @@ -3117,11 +3101,31 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - private void proxyDataStallToConnectivityDiagnosticsHandler(int detectionMethod, int netId, - long timestampMillis, @NonNull PersistableBundle extras) { + private void notifyDataStallSuspected(DataStallReportParcelable p, int netId) { + final PersistableBundle extras = new PersistableBundle(); + switch (p.detectionMethod) { + case DETECTION_METHOD_DNS_EVENTS: + extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts); + break; + case DETECTION_METHOD_TCP_METRICS: + extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate); + extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS, + p.tcpMetricsCollectionPeriodMillis); + break; + default: + // TODO(b/156294356): update for new data stall detection methods + log("Unknown data stall detection method, ignoring: " + p.detectionMethod); + return; + } + + notifyDataStallSuspected(p.detectionMethod, netId, p.timestampMillis, extras); + } + + private void notifyDataStallSuspected(int detectionMethod, int netId, long timestampMillis, + @NonNull PersistableBundle extras) { final Message msg = mConnectivityDiagnosticsHandler.obtainMessage( - ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, - detectionMethod, netId, timestampMillis); + ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, detectionMethod, netId, + timestampMillis); msg.setData(new Bundle(extras)); // NetworkStateTrackerHandler currently doesn't take any actions based on data @@ -8177,7 +8181,6 @@ public class ConnectivityService extends IConnectivityManager.Stub + "creators"); } - proxyDataStallToConnectivityDiagnosticsHandler( - detectionMethod, network.netId, timestampMillis, extras); + notifyDataStallSuspected(detectionMethod, network.netId, timestampMillis, extras); } } From bee5b3f227db3d68912764c0f86d9948e4dac547 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Fri, 8 May 2020 01:33:13 +0000 Subject: [PATCH 194/229] Fix a bug where a spurious capabilities callback is sent. When a VPN connects and it has any underlying network (which means almost always, because it will take the default network if it doesn't declare any), it has default capabilities and will only take the capabilities of its underlying network as part of an update happening after making the network available but before the rematch can take place. This in turn causes the capabilities callback sent as part of the rematch to be spuriously sent. Test: FrameworksNetTests. Also tested together with a followup that adds tests with drive-by coverage for this. Bug: 150570873 Original-Change: https://android-review.googlesource.com/1305393 Merged-In: Id7d8bba486bada1a7ba5b0f152d2aa02e407f249 Change-Id: Id7d8bba486bada1a7ba5b0f152d2aa02e407f249 --- .../core/java/com/android/server/ConnectivityService.java | 8 ++++++++ .../java/com/android/server/ConnectivityServiceTest.java | 2 -- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 119715456f..f7ace06431 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -7134,6 +7134,14 @@ public class ConnectivityService extends IConnectivityManager.Stub networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND); if (!createNativeNetwork(networkAgent)) return; + if (networkAgent.isVPN()) { + // Initialize the VPN capabilities to their starting values according to the + // underlying networks. This will avoid a spurious callback to + // onCapabilitiesUpdated being sent in updateAllVpnCapabilities below as + // the VPN would switch from its default, blank capabilities to those + // that reflect the capabilities of its underlying networks. + updateAllVpnsCapabilities(); + } networkAgent.created = true; } diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index d2b26d3bfd..4397bd4640 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -5387,8 +5387,6 @@ public class ConnectivityServiceTest { // Even though the VPN is unvalidated, it becomes the default network for our app. callback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent); - // TODO: this looks like a spurious callback. - callback.expectCallback(CallbackEntry.NETWORK_CAPS_UPDATED, vpnNetworkAgent); callback.assertNoCallback(); assertTrue(vpnNetworkAgent.getScore() > mEthernetNetworkAgent.getScore()); From ebbece8b22fcf8837ac3e59843d3062d09dd1796 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Mon, 11 May 2020 04:59:35 +0000 Subject: [PATCH 195/229] Fix a bug where VPNs start out suspended on cellular As NetworkAgent is in a transition where all agents need to include the NOT_SUSPENDED capability as part of their migration to the system API, ConnectivityService adds it forcefully to all agents that don't have the CELLULAR transport. This doesn't include VPNs when VPNs have some cellular network as their underlying network. The best way to solve this is to make sure the VPN capabilities reflect those of the underlying networks as far as the NOT_SUSPENDED capability is concerned. This is how they work for other similar capabilities. This also happens to contain a drive-by fix for an issue with a spurious capabilities callback is triggered when a VPN connects and it has any underlying network (which means almost always, because it will take the default network if it doesn't declare any). Fixing this was necessary to have a cogent test of this issue, but it could be moved to another patch or it could stay unfixed with some minor ajustment to the tests if judged too dangerous to include in R at this point. Test: New tests in this patch. Also manually tested with tcpdump as described in b/150570873. Bug: 150570873 Original-Change: https://android-review.googlesource.com/1301317 Merged-In: I3e4ff990c0d4825b21c7679be29a482a2d1324ec Change-Id: I3e4ff990c0d4825b21c7679be29a482a2d1324ec --- .../android/server/NetworkAgentWrapper.java | 3 + .../server/ConnectivityServiceTest.java | 107 +++++++++++++++++- .../android/server/connectivity/VpnTest.java | 7 ++ 3 files changed, 111 insertions(+), 6 deletions(-) diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index a35fb407bc..0ffafd4561 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -92,6 +92,9 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { break; case TRANSPORT_VPN: mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN); + // VPNs deduce the SUSPENDED capability from their underlying networks and there + // is no public API to let VPN services set it. + mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); mScore = ConnectivityConstants.VPN_DEFAULT_SCORE; break; default: diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index d2b26d3bfd..6f1ad1aece 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -5417,6 +5417,47 @@ public class ConnectivityServiceTest { callback.expectAvailableCallbacksValidated(mEthernetNetworkAgent); } + @Test + public void testVpnStartsWithUnderlyingCaps() throws Exception { + final int uid = Process.myUid(); + + final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback(); + final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder() + .removeCapability(NET_CAPABILITY_NOT_VPN) + .addTransportType(TRANSPORT_VPN) + .build(); + mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback); + vpnNetworkCallback.assertNoCallback(); + + // Connect cell. It will become the default network, and in the absence of setting + // underlying networks explicitly it will become the sole underlying network for the vpn. + mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); + mCellNetworkAgent.connect(true); + + final TestNetworkAgentWrapper vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN); + final ArraySet ranges = new ArraySet<>(); + ranges.add(new UidRange(uid, uid)); + mMockVpn.setNetworkAgent(vpnNetworkAgent); + mMockVpn.connect(); + mMockVpn.setUids(ranges); + vpnNetworkAgent.connect(true /* validated */, false /* hasInternet */, + false /* isStrictMode */); + + vpnNetworkCallback.expectAvailableCallbacks(vpnNetworkAgent.getNetwork(), + false /* suspended */, false /* validated */, false /* blocked */, TIMEOUT_MS); + vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent.getNetwork(), TIMEOUT_MS, + nc -> nc.hasCapability(NET_CAPABILITY_VALIDATED)); + + final NetworkCapabilities nc = mCm.getNetworkCapabilities(vpnNetworkAgent.getNetwork()); + assertTrue(nc.hasTransport(TRANSPORT_VPN)); + assertTrue(nc.hasTransport(TRANSPORT_CELLULAR)); + assertFalse(nc.hasTransport(TRANSPORT_WIFI)); + assertTrue(nc.hasCapability(NET_CAPABILITY_VALIDATED)); + assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); + assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + } + @Test public void testVpnSetUnderlyingNetworks() throws Exception { final int uid = Process.myUid(); @@ -5450,6 +5491,7 @@ public class ConnectivityServiceTest { // Connect cell and use it as an underlying network. mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); + mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); mCellNetworkAgent.connect(true); mService.setUnderlyingNetworksForVpn( @@ -5458,10 +5500,12 @@ public class ConnectivityServiceTest { vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, (caps) -> caps.hasTransport(TRANSPORT_VPN) && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED); + mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); mWiFiNetworkAgent.connect(true); mService.setUnderlyingNetworksForVpn( @@ -5470,7 +5514,8 @@ public class ConnectivityServiceTest { vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, (caps) -> caps.hasTransport(TRANSPORT_VPN) && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); // Don't disconnect, but note the VPN is not using wifi any more. mService.setUnderlyingNetworksForVpn( @@ -5479,16 +5524,36 @@ public class ConnectivityServiceTest { vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, (caps) -> caps.hasTransport(TRANSPORT_VPN) && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); - // Use Wifi but not cell. Note the VPN is now unmetered. + // Remove NOT_SUSPENDED from the only network and observe VPN is now suspended. + mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); + vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, + (caps) -> caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + vpnNetworkCallback.expectCallback(CallbackEntry.SUSPENDED, vpnNetworkAgent); + + // Add NOT_SUSPENDED again and observe VPN is no longer suspended. + mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED); + vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, + (caps) -> caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI) + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + vpnNetworkCallback.expectCallback(CallbackEntry.RESUMED, vpnNetworkAgent); + + // Use Wifi but not cell. Note the VPN is now unmetered and not suspended. mService.setUnderlyingNetworksForVpn( new Network[] { mWiFiNetworkAgent.getNetwork() }); vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, (caps) -> caps.hasTransport(TRANSPORT_VPN) && !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) - && caps.hasCapability(NET_CAPABILITY_NOT_METERED)); + && caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); // Use both again. mService.setUnderlyingNetworksForVpn( @@ -5497,7 +5562,37 @@ public class ConnectivityServiceTest { vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, (caps) -> caps.hasTransport(TRANSPORT_VPN) && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) - && !caps.hasCapability(NET_CAPABILITY_NOT_METERED)); + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + + // Cell is suspended again. As WiFi is not, this should not cause a callback. + mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED); + vpnNetworkCallback.assertNoCallback(); + + // Stop using WiFi. The VPN is suspended again. + mService.setUnderlyingNetworksForVpn( + new Network[] { mCellNetworkAgent.getNetwork() }); + vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, + (caps) -> caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_CELLULAR) + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && !caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + // While the SUSPENDED callback should in theory be sent here, it is not. This is + // a bug in ConnectivityService, but as the SUSPENDED and RESUMED callbacks have never + // been public and are deprecated and slated for removal, there is no sense in spending + // resources fixing this bug now. + + // Use both again. + mService.setUnderlyingNetworksForVpn( + new Network[] { mCellNetworkAgent.getNetwork(), mWiFiNetworkAgent.getNetwork() }); + + vpnNetworkCallback.expectCapabilitiesThat(vpnNetworkAgent, + (caps) -> caps.hasTransport(TRANSPORT_VPN) + && caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI) + && !caps.hasCapability(NET_CAPABILITY_NOT_METERED) + && caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); + // As above, the RESUMED callback not being sent here is a bug, but not a bug that's + // worth anybody's time to fix. // Disconnect cell. Receive update without even removing the dead network from the // underlying networks – it's dead anyway. Not metered any more. diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 1994d1f2ed..f8d8a56b57 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -25,6 +25,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING; +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; @@ -606,6 +607,7 @@ public class VpnTest { .addCapability(NET_CAPABILITY_NOT_METERED) .addCapability(NET_CAPABILITY_NOT_ROAMING) .addCapability(NET_CAPABILITY_NOT_CONGESTED) + .addCapability(NET_CAPABILITY_NOT_SUSPENDED) .setLinkUpstreamBandwidthKbps(20)); setMockedNetworks(networks); @@ -621,6 +623,7 @@ public class VpnTest { assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); + assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); Vpn.applyUnderlyingCapabilities( mConnectivityManager, @@ -635,6 +638,7 @@ public class VpnTest { assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); + assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {wifi}, caps, false /* isAlwaysMetered */); @@ -646,6 +650,7 @@ public class VpnTest { assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); + assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); Vpn.applyUnderlyingCapabilities( mConnectivityManager, new Network[] {wifi}, caps, true /* isAlwaysMetered */); @@ -657,6 +662,7 @@ public class VpnTest { assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); + assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); Vpn.applyUnderlyingCapabilities( mConnectivityManager, @@ -671,6 +677,7 @@ public class VpnTest { assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING)); assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED)); + assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); } /** From 4a7eb2a5d25a6bcefb76fec8844f692d10a24e07 Mon Sep 17 00:00:00 2001 From: Treehugger Robot Date: Fri, 15 May 2020 07:14:29 +0000 Subject: [PATCH 196/229] Address nit from aosp/1301317 Test: atest ConnectivityServiceTest#testVpnSetUnderlyingNetworks Bug: 150570873 Original-Change: https://android-review.googlesource.com/1307374 Merged-In: If5e5439b22f05e08a293fd83da4d54f6a4363ca5 Change-Id: If5e5439b22f05e08a293fd83da4d54f6a4363ca5 --- tests/net/java/com/android/server/ConnectivityServiceTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index d2b26d3bfd..775406e396 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -5447,6 +5447,8 @@ public class ConnectivityServiceTest { assertFalse(nc.hasTransport(TRANSPORT_WIFI)); // For safety reasons a VPN without underlying networks is considered metered. assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED)); + // A VPN without underlying networks is not suspended. + assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED)); // Connect cell and use it as an underlying network. mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR); From 80aec1d4ff092adb4c7c8406b168e3964dab441d Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Fri, 22 May 2020 00:28:02 +0000 Subject: [PATCH 197/229] Forward unknown Data Stall types to Connectivity Diagnostics. This CL forwards suspected Data Stall events detected with unknown detection methods to ConnectivityDiagnostics. Currently, ConnectivityService drops any data stall events with unknown detection methods, which leads to false negatives for Connectivity Diagnostics registrants. This change ensures that registrants will still be notified as NetworkStack is updated to use new detection methods. The documentation for ConnectivityDiagnosticsManager#DataStallReport is also updated to reflect that the detection methods included in the report are a bit mask of detection methods used. Implicitly, this means that data stalls detected via unknown methods will have an empty bit mask (0x00). Bug: 156294356 Test: atest ConnectivityDiagnosticsManager Change-Id: I62d0bf91fcc17c7921afd519c72551399906bd6b Merged-In: I62d0bf91fcc17c7921afd519c72551399906bd6b (cherry picked from commit a1d9d811a05bf3447ebb90a39343b53eee79f0db) --- .../net/ConnectivityDiagnosticsManager.java | 6 +-- .../android/server/ConnectivityService.java | 51 +++++++++++-------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java index 9086d49231..275e38c744 100644 --- a/core/java/android/net/ConnectivityDiagnosticsManager.java +++ b/core/java/android/net/ConnectivityDiagnosticsManager.java @@ -437,7 +437,7 @@ public class ConnectivityDiagnosticsManager { */ private long mReportTimestamp; - /** The detection method used to identify the suspected data stall */ + /** A bitmask of the detection methods used to identify the suspected data stall */ @DetectionMethod private final int mDetectionMethod; /** LinkProperties available on the Network at the reported timestamp */ @@ -499,9 +499,9 @@ public class ConnectivityDiagnosticsManager { } /** - * Returns the detection method used to identify this suspected data stall. + * Returns the bitmask of detection methods used to identify this suspected data stall. * - * @return The detection method used to identify the suspected data stall + * @return The bitmask of detection methods used to identify the suspected data stall */ public int getDetectionMethod() { return mDetectionMethod; diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 7c61ba2e7a..1e9a9d85e0 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -3102,30 +3102,24 @@ public class ConnectivityService extends IConnectivityManager.Stub } private void notifyDataStallSuspected(DataStallReportParcelable p, int netId) { + log("Data stall detected with methods: " + p.detectionMethod); + final PersistableBundle extras = new PersistableBundle(); - switch (p.detectionMethod) { - case DETECTION_METHOD_DNS_EVENTS: - extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts); - break; - case DETECTION_METHOD_TCP_METRICS: - extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate); - extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS, - p.tcpMetricsCollectionPeriodMillis); - break; - default: - // TODO(b/156294356): update for new data stall detection methods - log("Unknown data stall detection method, ignoring: " + p.detectionMethod); - return; + int detectionMethod = 0; + if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) { + extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts); + detectionMethod |= DETECTION_METHOD_DNS_EVENTS; + } + if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) { + extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate); + extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS, + p.tcpMetricsCollectionPeriodMillis); + detectionMethod |= DETECTION_METHOD_TCP_METRICS; } - notifyDataStallSuspected(p.detectionMethod, netId, p.timestampMillis, extras); - } - - private void notifyDataStallSuspected(int detectionMethod, int netId, long timestampMillis, - @NonNull PersistableBundle extras) { final Message msg = mConnectivityDiagnosticsHandler.obtainMessage( ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, detectionMethod, netId, - timestampMillis); + p.timestampMillis); msg.setData(new Bundle(extras)); // NetworkStateTrackerHandler currently doesn't take any actions based on data @@ -3134,6 +3128,10 @@ public class ConnectivityService extends IConnectivityManager.Stub mConnectivityDiagnosticsHandler.sendMessage(msg); } + private boolean hasDataStallDetectionMethod(DataStallReportParcelable p, int detectionMethod) { + return (p.detectionMethod & detectionMethod) != 0; + } + private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) { return isPrivateDnsValidationRequired(nai.networkCapabilities); } @@ -8189,6 +8187,19 @@ public class ConnectivityService extends IConnectivityManager.Stub + "creators"); } - notifyDataStallSuspected(detectionMethod, network.netId, timestampMillis, extras); + final DataStallReportParcelable p = new DataStallReportParcelable(); + p.timestampMillis = timestampMillis; + p.detectionMethod = detectionMethod; + + if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) { + p.dnsConsecutiveTimeouts = extras.getInt(KEY_DNS_CONSECUTIVE_TIMEOUTS); + } + if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) { + p.tcpPacketFailRate = extras.getInt(KEY_TCP_PACKET_FAIL_RATE); + p.tcpMetricsCollectionPeriodMillis = extras.getInt( + KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS); + } + + notifyDataStallSuspected(p, network.netId); } } From 0424f88915c831466c9511140e312862b4cc7455 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Sun, 24 May 2020 11:30:55 +0000 Subject: [PATCH 198/229] Test that if an RA sets the same prefix as DNS, nothing happens. This is not particularly likely to happen unless the pref64 RA is sent by a different router than the main RA. But more tests are always good, and this additional coverage will be more useful in an upcoming change. Bug: 150648313 Test: test-only change Original-Change: https://android-review.googlesource.com/1316094 Merged-In: I3316d49d42100800740afadc4edf0a13a4d8377c Change-Id: I3316d49d42100800740afadc4edf0a13a4d8377c --- .../server/ConnectivityServiceTest.java | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 83ca9b28e9..437c382e32 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6346,12 +6346,36 @@ public class ConnectivityServiceTest { expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns); inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString()); - // If the RA prefix reappears, clatd is restarted and prefix discovery is stopped. + // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix + // discovery is not stopped, and there are no callbacks. + lp.setNat64Prefix(pref64FromDns); + mCellNetworkAgent.sendLinkProperties(lp); + callback.assertNoCallback(); + inOrder.verify(mMockNetd, never()).clatdStop(iface); + inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); + inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + + // If the RA is later withdrawn, nothing happens again. + lp.setNat64Prefix(null); + mCellNetworkAgent.sendLinkProperties(lp); + callback.assertNoCallback(); + inOrder.verify(mMockNetd, never()).clatdStop(iface); + inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); + inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + + // If the RA prefix changes, clatd is restarted and prefix discovery is stopped. lp.setNat64Prefix(pref64FromRa); mCellNetworkAgent.sendLinkProperties(lp); expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa); inOrder.verify(mMockNetd).clatdStop(iface); inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); + + // Stopping prefix discovery results in a prefix removed notification. + mService.mNetdEventCallback.onNat64PrefixEvent(netId, false /* added */, + pref64FromDnsStr, 96); + inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); From 37aa693fb50c3ebd81d198b0760fcc6e0080dac4 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 26 May 2020 10:13:17 +0000 Subject: [PATCH 199/229] Inform the DNS resolver when it needs to do DNS64 synthesis. This is only necessary when learning the NAT64 prefix from the RA, because if the NAT64 prefix is learned from DNS, the DNS resolver already knows the prefix and automatically enables DNS64 synthesis. The DNS resolver needs to be informed of the prefix any time clat is running on a prefix learned from an RA. This is simple to implement: just set the prefix when starting clat if prefix discovery is not running, and clear the prefix when stopping clat if prefix discovery was not running. This ensures that the prefix is cleared iff it was set. Bug: 156914456 Test: new unit test coverage Original-Change: https://android-review.googlesource.com/1315578 Merged-In: If8ad2d30712a6df3e207c8d3e8a129705242191e Change-Id: If8ad2d30712a6df3e207c8d3e8a129705242191e --- .../server/connectivity/Nat464Xlat.java | 17 ++++++++ .../server/ConnectivityServiceTest.java | 43 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index 34d0bed9a8..3091a71783 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -198,6 +198,9 @@ public class Nat464Xlat extends BaseNetworkObserver { if (mPrefixDiscoveryRunning && !isPrefixDiscoveryNeeded()) { stopPrefixDiscovery(); } + if (!mPrefixDiscoveryRunning) { + setPrefix64(mNat64PrefixInUse); + } } /** @@ -221,6 +224,10 @@ public class Nat464Xlat extends BaseNetworkObserver { mIface = null; mBaseIface = null; + if (!mPrefixDiscoveryRunning) { + setPrefix64(null); + } + if (isPrefixDiscoveryNeeded()) { if (!mPrefixDiscoveryRunning) { startPrefixDiscovery(); @@ -308,6 +315,16 @@ public class Nat464Xlat extends BaseNetworkObserver { return requiresClat(mNetwork) && mNat64PrefixFromRa == null; } + private void setPrefix64(IpPrefix prefix) { + final String prefixString = (prefix != null) ? prefix.toString() : ""; + try { + mDnsResolver.setPrefix64(getNetId(), prefixString); + } catch (RemoteException | ServiceSpecificException e) { + Slog.e(TAG, "Error setting NAT64 prefix on netId " + getNetId() + " to " + + prefix + ": " + e); + } + } + private void maybeHandleNat64PrefixChange() { final IpPrefix newPrefix = selectNat64Prefix(); if (!Objects.equals(mNat64PrefixInUse, newPrefix)) { diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 437c382e32..c86d388a3d 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -6314,6 +6314,7 @@ public class ConnectivityServiceTest { int netId = network.getNetId(); callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent); inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); callback.assertNoCallback(); assertEquals(pref64FromRa, mCm.getLinkProperties(network).getNat64Prefix()); @@ -6323,6 +6324,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(lp); expectNat64PrefixChange(callback, mCellNetworkAgent, null); inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); // If the RA prefix appears while DNS discovery is in progress, discovery is stopped and @@ -6332,6 +6334,7 @@ public class ConnectivityServiceTest { expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa); inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); // Withdraw the RA prefix so we can test the case where an RA prefix appears after DNS // discovery has succeeded. @@ -6339,6 +6342,7 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(lp); expectNat64PrefixChange(callback, mCellNetworkAgent, null); inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */, @@ -6355,6 +6359,7 @@ public class ConnectivityServiceTest { inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); // If the RA is later withdrawn, nothing happens again. lp.setNat64Prefix(null); @@ -6364,6 +6369,7 @@ public class ConnectivityServiceTest { inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); // If the RA prefix changes, clatd is restarted and prefix discovery is stopped. lp.setNat64Prefix(pref64FromRa); @@ -6377,6 +6383,7 @@ public class ConnectivityServiceTest { pref64FromDnsStr, 96); inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString()); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, pref64FromRa.toString()); inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); // If the RA prefix changes, clatd is restarted and prefix discovery is not started. @@ -6384,7 +6391,9 @@ public class ConnectivityServiceTest { mCellNetworkAgent.sendLinkProperties(lp); expectNat64PrefixChange(callback, mCellNetworkAgent, newPref64FromRa); inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); inOrder.verify(mMockNetd).clatdStart(iface, newPref64FromRa.toString()); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, newPref64FromRa.toString()); inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); @@ -6397,11 +6406,45 @@ public class ConnectivityServiceTest { inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); // The transition between no prefix and DNS prefix is tested in testStackedLinkProperties. + // If the same prefix is learned first by DNS and then by RA, and clat is later stopped, + // (e.g., because the network disconnects) setPrefix64(netid, "") is never called. + lp.setNat64Prefix(null); + mCellNetworkAgent.sendLinkProperties(lp); + expectNat64PrefixChange(callback, mCellNetworkAgent, null); + inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).setPrefix64(netId, ""); + inOrder.verify(mMockDnsResolver).startPrefix64Discovery(netId); + mService.mNetdEventCallback.onNat64PrefixEvent(netId, true /* added */, + pref64FromDnsStr, 96); + expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns); + inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString()); + inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), any()); + + lp.setNat64Prefix(pref64FromDns); + mCellNetworkAgent.sendLinkProperties(lp); callback.assertNoCallback(); + inOrder.verify(mMockNetd, never()).clatdStop(iface); + inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString()); + inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); + + // When tearing down a network, clat state is only updated after CALLBACK_LOST is fired, but + // before CONNECTIVITY_ACTION is sent. Wait for CONNECTIVITY_ACTION before verifying that + // clat has been stopped, or the test will be flaky. + ConditionVariable cv = registerConnectivityBroadcast(1); mCellNetworkAgent.disconnect(); + callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent); + waitFor(cv); + + inOrder.verify(mMockNetd).clatdStop(iface); + inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId); + inOrder.verify(mMockDnsResolver, never()).setPrefix64(eq(netId), anyString()); + mCm.unregisterNetworkCallback(callback); } From 279638210366f30d136398ebffe7bb12805af4dd Mon Sep 17 00:00:00 2001 From: Cody Kesting Date: Wed, 27 May 2020 18:22:56 +0000 Subject: [PATCH 200/229] Comment reason for simulateDataStall structure. This change adds a comment to CS#simulateDataStall to explain why the Data Stall is wrapped in a DataStallReportParcelable before being passed to the ConnectivityDiagnostics handler. This approach is taken to ensure that simulated data stalls are handled the exact same as Data Stalls received directly from NetworkMonitor (including Data Stalls detected by methods that the platform does not understand). Bug: 156294356 Test: atest ConnectivityDiagnosticsManager Change-Id: I751054418bf328c72b977a1cc99c27cb9b8ab7ba Merged-In: I751054418bf328c72b977a1cc99c27cb9b8ab7ba (cherry picked from commit c86db7497a27cfbac5c662911a295598b1335bc0) --- .../core/java/com/android/server/ConnectivityService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 1e9a9d85e0..1634f6e628 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -8187,6 +8187,11 @@ public class ConnectivityService extends IConnectivityManager.Stub + "creators"); } + // Instead of passing the data stall directly to the ConnectivityDiagnostics handler, treat + // this as a Data Stall received directly from NetworkMonitor. This requires wrapping the + // Data Stall information as a DataStallReportParcelable and passing to + // #notifyDataStallSuspected. This ensures that unknown Data Stall detection methods are + // still passed to ConnectivityDiagnostics (with new detection methods masked). final DataStallReportParcelable p = new DataStallReportParcelable(); p.timestampMillis = timestampMillis; p.detectionMethod = detectionMethod; From 7bdbb811ff39c7902c15ddd75d57a5a127908df0 Mon Sep 17 00:00:00 2001 From: Luke Huang Date: Thu, 28 May 2020 15:41:46 +0800 Subject: [PATCH 201/229] Add dnsproxyd_protocol_headers for NETID_USE_LOCAL_NAMESERVERS NETID_USE_LOCAL_NAMESERVERS is no longer in libnetd_client Bug: 151895202 Test: build Change-Id: Iea0c2488dcabdd24d6ffca8134cd11ed12e8308a --- core/jni/android_net_NetUtils.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index ba7fe7ff87..03b9793ccb 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -27,12 +27,13 @@ #include #include +#include // NETID_USE_LOCAL_NAMESERVERS #include #include -#include -#include #include #include +#include +#include #include "NetdClient.h" #include "core_jni_helpers.h" From b6662062ff339d5c3030c887cbf776a71ad49beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Sat, 4 Jan 2020 13:20:53 -0800 Subject: [PATCH 202/229] fix android.net.NetworkStatsTest#testApply464xlatAdjustments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test: atest NetworkStatsTest Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: Ib12ee88295eb502f6da13d212b4fd6298dea380f Merged-In: Ib12ee88295eb502f6da13d212b4fd6298dea380f --- .../java/android/net/NetworkStatsTest.java | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java index 98f705f45e..f28b1864c1 100644 --- a/tests/net/java/android/net/NetworkStatsTest.java +++ b/tests/net/java/android/net/NetworkStatsTest.java @@ -909,8 +909,8 @@ public class NetworkStatsTest { 13805 /* txPackets */, 0 /* operations */); - // Traffic measured for the root uid on the base interface if eBPF is in use. - final NetworkStats.Entry ebpfRootUidEntry = new NetworkStats.Entry( + // Traffic measured for the root uid on the base interface. + final NetworkStats.Entry rootUidEntry = new NetworkStats.Entry( baseIface, rootUid, SET_DEFAULT, TAG_NONE, 163577 /* rxBytes */, 187 /* rxPackets */, @@ -918,17 +918,6 @@ public class NetworkStatsTest { 97 /* txPackets */, 0 /* operations */); - // Traffic measured for the root uid on the base interface if xt_qtaguid is in use. - // Incorrectly includes appEntry's bytes and packets, plus IPv4-IPv6 translation - // overhead (20 bytes per packet), in rx direction. - final NetworkStats.Entry xtRootUidEntry = new NetworkStats.Entry( - baseIface, rootUid, SET_DEFAULT, TAG_NONE, - 31113087 /* rxBytes */, - 22588 /* rxPackets */, - 17607 /* txBytes */, - 97 /* txPackets */, - 0 /* operations */); - final NetworkStats.Entry otherEntry = new NetworkStats.Entry( otherIface, appUid, SET_DEFAULT, TAG_NONE, 2600 /* rxBytes */, @@ -939,12 +928,12 @@ public class NetworkStatsTest { final NetworkStats statsXt = new NetworkStats(TEST_START, 3) .insertEntry(appEntry) - .insertEntry(xtRootUidEntry) + .insertEntry(rootUidEntry) .insertEntry(otherEntry); final NetworkStats statsEbpf = new NetworkStats(TEST_START, 3) .insertEntry(appEntry) - .insertEntry(ebpfRootUidEntry) + .insertEntry(rootUidEntry) .insertEntry(otherEntry); statsXt.apply464xlatAdjustments(stackedIface, false); From 27061604cf118e4da6f99e1b16c3fee6fc9d6400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Sat, 4 Jan 2020 12:51:49 -0800 Subject: [PATCH 203/229] fix com.android.server.net.NetworkStatsFactoryTest#testDoubleClatAccountingSimple MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No clat app uid 0 rx stats on base iface due to ip6tables raw prerouting drop Test: atest NetworkStatsFactoryTest Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: Ifebd946e06b5fa2eeb7ff4fc0b1c423097021692 Merged-In: Ifebd946e06b5fa2eeb7ff4fc0b1c423097021692 --- tests/net/res/raw/xt_qtaguid_with_clat_simple | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/net/res/raw/xt_qtaguid_with_clat_simple b/tests/net/res/raw/xt_qtaguid_with_clat_simple index b37fae6d2a..2c9b9f768d 100644 --- a/tests/net/res/raw/xt_qtaguid_with_clat_simple +++ b/tests/net/res/raw/xt_qtaguid_with_clat_simple @@ -1,5 +1,5 @@ idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets 2 v4-wlan0 0x0 10060 0 42600 213 4100 41 42600 213 0 0 0 0 4100 41 0 0 0 0 3 v4-wlan0 0x0 10060 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -4 wlan0 0x0 0 0 46860 213 0 0 46860 213 0 0 0 0 0 0 0 0 0 0 +4 wlan0 0x0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 wlan0 0x0 1029 0 0 0 4920 41 0 0 0 0 0 0 4920 41 0 0 0 0 From e32498e4374526f4c33b6452b521e26bb0ad9e04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Sat, 4 Jan 2020 12:59:06 -0800 Subject: [PATCH 204/229] fix com.android.server.net.NetworkStatsFactoryTest#testDoubleClatAccounting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No clat app uid 0 rx stats on base iface due to ip6tables raw prerouting drop Test: atest NetworkStatsFactoryTest Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: I4393afcbe8e1bb886ecf4f5c1573f6ac8a0e29f5 Merged-In: I4393afcbe8e1bb886ecf4f5c1573f6ac8a0e29f5 --- .../java/com/android/server/net/NetworkStatsFactoryTest.java | 2 +- tests/net/res/raw/xt_qtaguid_with_clat | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java index 4473492d79..fd51c4ae3f 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java @@ -446,7 +446,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { assertStatsEntry(stats, "v4-wlan0", 1000, SET_DEFAULT, 0x0, 30812L, 2310L); assertStatsEntry(stats, "v4-wlan0", 10102, SET_DEFAULT, 0x0, 10022L, 3330L); assertStatsEntry(stats, "v4-wlan0", 10060, SET_DEFAULT, 0x0, 9532772L, 254112L); - assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, 15229L, 0L); + assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, 0L, 0L); assertStatsEntry(stats, "wlan0", 1000, SET_DEFAULT, 0x0, 6126L, 2013L); assertStatsEntry(stats, "wlan0", 10013, SET_DEFAULT, 0x0, 0L, 144L); assertStatsEntry(stats, "wlan0", 10018, SET_DEFAULT, 0x0, 5980263L, 167667L); diff --git a/tests/net/res/raw/xt_qtaguid_with_clat b/tests/net/res/raw/xt_qtaguid_with_clat index 6cd7499545..8967d4f1ac 100644 --- a/tests/net/res/raw/xt_qtaguid_with_clat +++ b/tests/net/res/raw/xt_qtaguid_with_clat @@ -7,7 +7,7 @@ idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packe 7 v4-wlan0 0x0 10060 1 1448660 1041 31192 753 1448660 1041 0 0 0 0 31192 753 0 0 0 0 8 v4-wlan0 0x0 10102 0 9702 16 2870 23 9702 16 0 0 0 0 2870 23 0 0 0 0 9 v4-wlan0 0x0 10102 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -10 wlan0 0x0 0 0 11058671 7892 0 0 11043898 7811 13117 61 1656 20 0 0 0 0 0 0 +10 wlan0 0x0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 11 wlan0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 wlan0 0x0 1000 0 6126 13 2013 16 5934 11 192 2 0 0 1821 14 192 2 0 0 13 wlan0 0x0 1000 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 From bcb4c0db35364d8e24356cd004819f6b3fbbca7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Sat, 4 Jan 2020 13:07:51 -0800 Subject: [PATCH 205/229] fix com.android.server.net.NetworkStatsFactoryTest#testDoubleClatAccounting100MBDownload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No clat app uid 0 rx stats on base iface due to ip6tables raw prerouting drop (so just copy over the rx stats from the before file) Test: atest NetworkStatsTest NetworkStatsFactoryTest Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: Ie73ba0586dafde67bc2726db26e07f7268c18be3 Merged-In: Ie73ba0586dafde67bc2726db26e07f7268c18be3 --- .../com/android/server/net/NetworkStatsFactoryTest.java | 8 +++----- .../net/res/raw/xt_qtaguid_with_clat_100mb_download_after | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java index fd51c4ae3f..e4996d981f 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java @@ -468,9 +468,7 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { long appRxBytesAfter = 439237478L; assertEquals("App traffic should be ~100MB", 110553449, appRxBytesAfter - appRxBytesBefore); - long rootRxBytesBefore = 1394011L; - long rootRxBytesAfter = 1398634L; - assertEquals("UID 0 traffic should be ~0", 4623, rootRxBytesAfter - rootRxBytesBefore); + long rootRxBytes = 330187296L; mFactory.noteStackedIface("v4-wlan0", "wlan0"); NetworkStats stats; @@ -478,12 +476,12 @@ public class NetworkStatsFactoryTest extends NetworkStatsBaseTest { // Stats snapshot before the download stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_100mb_download_before); assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesBefore, 5199872L); - assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytesBefore, 0L); + assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytes, 0L); // Stats snapshot after the download stats = parseDetailedStats(R.raw.xt_qtaguid_with_clat_100mb_download_after); assertStatsEntry(stats, "v4-wlan0", 10106, SET_FOREGROUND, 0x0, appRxBytesAfter, 7867488L); - assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytesAfter, 0L); + assertStatsEntry(stats, "wlan0", 0, SET_DEFAULT, 0x0, rootRxBytes, 0L); } /** diff --git a/tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_after b/tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_after index 9f86153a33..12d98ca29f 100644 --- a/tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_after +++ b/tests/net/res/raw/xt_qtaguid_with_clat_100mb_download_after @@ -9,7 +9,7 @@ idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packe 9 v4-wlan0 0x0 10057 1 728 7 392 7 0 0 728 7 0 0 0 0 392 7 0 0 10 v4-wlan0 0x0 10106 0 2232 18 2232 18 0 0 2232 18 0 0 0 0 2232 18 0 0 11 v4-wlan0 0x0 10106 1 432952718 314238 5442288 121260 432950238 314218 2480 20 0 0 5433900 121029 8388 231 0 0 -12 wlan0 0x0 0 0 440746376 329772 0 0 439660007 315369 232001 1276 854368 13127 0 0 0 0 0 0 +12 wlan0 0x0 0 0 330187296 250652 0 0 329106990 236273 226202 1255 854104 13124 0 0 0 0 0 0 13 wlan0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 14 wlan0 0x0 1000 0 77113 272 56151 575 77113 272 0 0 0 0 19191 190 36960 385 0 0 15 wlan0 0x0 1000 1 20227 80 8356 72 18539 74 1688 6 0 0 7562 66 794 6 0 0 From 19e7950e50e64e388dac972329c67ae87c1c94c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Thu, 28 May 2020 01:06:28 -0700 Subject: [PATCH 206/229] NetworkStats: apply464xlatAdjustments - remove useBpfStats parameter. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test: atest NetworkStatsTest NetworkStatsFactoryTest Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: I0121a4ac7ee824adc5930bab786d550b2f00b05b Merged-In: I0121a4ac7ee824adc5930bab786d550b2f00b05b --- .../java/android/net/NetworkStatsTest.java | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java index f28b1864c1..735fa7cf37 100644 --- a/tests/net/java/android/net/NetworkStatsTest.java +++ b/tests/net/java/android/net/NetworkStatsTest.java @@ -926,21 +926,14 @@ public class NetworkStatsTest { 3 /* txPackets */, 0 /* operations */); - final NetworkStats statsXt = new NetworkStats(TEST_START, 3) + final NetworkStats stats = new NetworkStats(TEST_START, 3) .insertEntry(appEntry) .insertEntry(rootUidEntry) .insertEntry(otherEntry); - final NetworkStats statsEbpf = new NetworkStats(TEST_START, 3) - .insertEntry(appEntry) - .insertEntry(rootUidEntry) - .insertEntry(otherEntry); + stats.apply464xlatAdjustments(stackedIface); - statsXt.apply464xlatAdjustments(stackedIface, false); - statsEbpf.apply464xlatAdjustments(stackedIface, true); - - assertEquals(3, statsXt.size()); - assertEquals(3, statsEbpf.size()); + assertEquals(3, stats.size()); final NetworkStats.Entry expectedAppUid = new NetworkStats.Entry( v4Iface, appUid, SET_DEFAULT, TAG_NONE, 30949510, @@ -955,12 +948,9 @@ public class NetworkStatsTest { 17607, 97, 0); - assertEquals(expectedAppUid, statsXt.getValues(0, null)); - assertEquals(expectedRootUid, statsXt.getValues(1, null)); - assertEquals(otherEntry, statsXt.getValues(2, null)); - assertEquals(expectedAppUid, statsEbpf.getValues(0, null)); - assertEquals(expectedRootUid, statsEbpf.getValues(1, null)); - assertEquals(otherEntry, statsEbpf.getValues(2, null)); + assertEquals(expectedAppUid, stats.getValues(0, null)); + assertEquals(expectedRootUid, stats.getValues(1, null)); + assertEquals(otherEntry, stats.getValues(2, null)); } @Test @@ -985,7 +975,7 @@ public class NetworkStatsTest { .insertEntry(secondEntry); // Empty map: no adjustment - stats.apply464xlatAdjustments(new ArrayMap<>(), false); + stats.apply464xlatAdjustments(new ArrayMap<>()); assertEquals(2, stats.size()); assertEquals(firstEntry, stats.getValues(0, null)); From 27daadb32869abc76a8288487ccf4070fd32bf3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Thu, 28 May 2020 01:33:52 -0700 Subject: [PATCH 207/229] NetworkStats: apply464xlatAdjustments - don't remove CLAT_UID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should no longer be needed after all the cleanups. Test: atest NetworkStatsTest NetworkStatsFactoryTest Bug: 150738490 Signed-off-by: Maciej Żenczykowski Change-Id: I289d935f84b616ed857ef4c5a7427d57c282d00c Merged-In: I289d935f84b616ed857ef4c5a7427d57c282d00c --- tests/net/res/raw/xt_qtaguid_with_clat | 2 -- tests/net/res/raw/xt_qtaguid_with_clat_simple | 1 - 2 files changed, 3 deletions(-) diff --git a/tests/net/res/raw/xt_qtaguid_with_clat b/tests/net/res/raw/xt_qtaguid_with_clat index 8967d4f1ac..f04b32f083 100644 --- a/tests/net/res/raw/xt_qtaguid_with_clat +++ b/tests/net/res/raw/xt_qtaguid_with_clat @@ -41,5 +41,3 @@ idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packe 41 dummy0 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 lo 0x0 0 0 1288 16 1288 16 0 0 532 8 756 8 0 0 532 8 756 8 43 lo 0x0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -44 wlan0 0x0 1029 0 0 0 312046 5113 0 0 0 0 0 0 306544 5046 3230 38 2272 29 -45 wlan0 0x0 1029 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 \ No newline at end of file diff --git a/tests/net/res/raw/xt_qtaguid_with_clat_simple b/tests/net/res/raw/xt_qtaguid_with_clat_simple index 2c9b9f768d..a1d6d411ba 100644 --- a/tests/net/res/raw/xt_qtaguid_with_clat_simple +++ b/tests/net/res/raw/xt_qtaguid_with_clat_simple @@ -2,4 +2,3 @@ idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packe 2 v4-wlan0 0x0 10060 0 42600 213 4100 41 42600 213 0 0 0 0 4100 41 0 0 0 0 3 v4-wlan0 0x0 10060 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 wlan0 0x0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -5 wlan0 0x0 1029 0 0 0 4920 41 0 0 0 0 0 0 4920 41 0 0 0 0 From ba8ca7839402b4e289d7ff87f5d90f3966361fee Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Thu, 14 May 2020 19:02:03 -0700 Subject: [PATCH 208/229] Add RequiresFeature annotations for IKEv2 VPN profiles This change adds the @RequiresFeature annotation to Ikev2VpnProfile Builder methods, and checks before provisioning VPN profiles. Bug: 156681625 Test: New tests added, passing. Change-Id: I125d8fbe5d67fb877ad7d0636c007cb3e1a9f59b Merged-In: I125d8fbe5d67fb877ad7d0636c007cb3e1a9f59b (cherry picked from commit e84a17dd1706f4c8373047b2023a1ec4b7cf4bf3) --- .../com/android/server/connectivity/VpnTest.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index f8d8a56b57..4ccf79a0cb 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -199,6 +199,8 @@ public class VpnTest { when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)) .thenReturn(Resources.getSystem().getString( R.string.config_customVpnAlwaysOnDisconnectedDialogComponent)); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) + .thenReturn(true); when(mSystemServices.isCallerSystem()).thenReturn(true); // Used by {@link Notification.Builder} @@ -730,6 +732,20 @@ public class VpnTest { } } + @Test + public void testProvisionVpnProfileNoIpsecTunnels() throws Exception { + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) + .thenReturn(false); + final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN); + + try { + checkProvisionVpnProfile( + vpn, true /* expectedResult */, AppOpsManager.OP_ACTIVATE_PLATFORM_VPN); + fail("Expected exception due to missing feature"); + } catch (UnsupportedOperationException expected) { + } + } + @Test public void testProvisionVpnProfilePreconsented() throws Exception { final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN); From dcb0e912b11b22eb58b7e37e892ad44d2d9c941a Mon Sep 17 00:00:00 2001 From: Automerger Merge Worker Date: Thu, 28 May 2020 05:29:14 +0000 Subject: [PATCH 209/229] Adjust tests for renaming groupHint to cluster. Bug: 146460486 Test: atest android.net.IpMemoryStoreTest Test: atest com.android.server.connectivity.ipmemorystore.IpMemoryStoreServiceTest Change-Id: Ia9797bb93aa4ff89147a77823d342dc22aec6a25 Merged-In: I69f7a2971cc5985d0f0078aecc39d4d6a6130033 (cherry-picked from aosp/1311654) --- tests/net/java/android/net/IpMemoryStoreTest.java | 2 +- tests/net/java/android/net/ipmemorystore/ParcelableTests.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/net/java/android/net/IpMemoryStoreTest.java b/tests/net/java/android/net/IpMemoryStoreTest.java index 442ac5605e..0b13800bc5 100644 --- a/tests/net/java/android/net/IpMemoryStoreTest.java +++ b/tests/net/java/android/net/IpMemoryStoreTest.java @@ -105,7 +105,7 @@ public class IpMemoryStoreTest { private static NetworkAttributes buildTestNetworkAttributes(String hint, int mtu) { return new NetworkAttributes.Builder() - .setGroupHint(hint) + .setCluster(hint) .setMtu(mtu) .build(); } diff --git a/tests/net/java/android/net/ipmemorystore/ParcelableTests.java b/tests/net/java/android/net/ipmemorystore/ParcelableTests.java index 1a3ea6096c..02f5286506 100644 --- a/tests/net/java/android/net/ipmemorystore/ParcelableTests.java +++ b/tests/net/java/android/net/ipmemorystore/ParcelableTests.java @@ -54,7 +54,7 @@ public class ParcelableTests { builder.setAssignedV4Address((Inet4Address) Inet4Address.getByName("6.7.8.9")); builder.setAssignedV4AddressExpiry(System.currentTimeMillis() + 3_600_000); - builder.setGroupHint("groupHint"); + builder.setCluster("groupHint"); builder.setDnsAddresses(Arrays.asList( InetAddress.getByName("ACA1:652B:0911:DE8F:1200:115E:913B:AA2A"), InetAddress.getByName("6.7.8.9"))); From bfd4336f31ecaa7cf7c8618f5dd3a6125a8405ce Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Fri, 29 May 2020 22:09:13 +0000 Subject: [PATCH 210/229] Allow TRANSPORT_TEST ethernet networks Ethernet networks using tap interfaces should have TRANSPORT_TEST so they are not considered by network selection. Test: atest CaptivePortalApiTest FrameworksNetTests Bug: 156319532 Original-Change: https://android-review.googlesource.com/1317238 Merged-In: I0d9477977c88aa055625ab4046577a41e76b05ff Change-Id: I0d9477977c88aa055625ab4046577a41e76b05ff --- core/java/android/net/NetworkCapabilities.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index 9ded22fb70..a3fd60e9d3 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -679,13 +679,14 @@ public final class NetworkCapabilities implements Parcelable { */ public void restrictCapabilitesForTestNetwork(int creatorUid) { final long originalCapabilities = mNetworkCapabilities; + final long originalTransportTypes = mTransportTypes; final NetworkSpecifier originalSpecifier = mNetworkSpecifier; final int originalSignalStrength = mSignalStrength; final int originalOwnerUid = getOwnerUid(); final int[] originalAdministratorUids = getAdministratorUids(); clearAll(); - // Reset the transports to only contain TRANSPORT_TEST. - mTransportTypes = (1 << TRANSPORT_TEST); + mTransportTypes = (originalTransportTypes & TEST_NETWORKS_ALLOWED_TRANSPORTS) + | (1 << TRANSPORT_TEST); mNetworkCapabilities = originalCapabilities & TEST_NETWORKS_ALLOWED_CAPABILITIES; mNetworkSpecifier = originalSpecifier; mSignalStrength = originalSignalStrength; @@ -786,6 +787,13 @@ public final class NetworkCapabilities implements Parcelable { "TEST" }; + /** + * Allowed transports on a test network, in addition to TRANSPORT_TEST. + */ + private static final int TEST_NETWORKS_ALLOWED_TRANSPORTS = 1 << TRANSPORT_TEST + // Test ethernet networks can be created with EthernetManager#setIncludeTestInterfaces + | 1 << TRANSPORT_ETHERNET; + /** * Adds the given transport type to this {@code NetworkCapability} instance. * Multiple transports may be applied. Note that when searching From edb74fd839b33bd44e0eeec73f8f545fdeb99f7a Mon Sep 17 00:00:00 2001 From: Junyu Lai Date: Tue, 2 Jun 2020 09:52:38 +0000 Subject: [PATCH 211/229] Disable log for per uid blocked status changed event This consumes ~3.5% system logs, however it is not very useful when debugging since similar information could be obtained from dumpsys {connectivity|netpolicy}. Thus, remove the log. Test: manual Bug: 135504481 Change-Id: I04d2b7402f892546722fe6868c521afd9534f183 Merged-In: I04d2b7402f892546722fe6868c521afd9534f183 (cherry picked from commit 21a352f761ce558bea6fa9ab2a4e49a164228b56) --- .../core/java/com/android/server/ConnectivityService.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 1634f6e628..0ab571854c 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1374,10 +1374,9 @@ public class ConnectivityService extends IConnectivityManager.Stub if (nri == null || net == null || !LOGD_BLOCKED_NETWORKINFO) { return; } - String action = blocked ? "BLOCKED" : "UNBLOCKED"; - log(String.format("Blocked status changed to %s for %d(%d) on netId %d", blocked, - nri.mUid, nri.request.requestId, net.netId)); - mNetworkInfoBlockingLogs.log(action + " " + nri.mUid); + final String action = blocked ? "BLOCKED" : "UNBLOCKED"; + mNetworkInfoBlockingLogs.log(String.format( + "%s %d(%d) on netId %d", action, nri.mUid, nri.request.requestId, net.netId)); } /** From d33028c2059011613e0d8efdfa530acd8734e8ce Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Fri, 5 Jun 2020 00:41:42 +0000 Subject: [PATCH 212/229] Update extra info before registering The extra info is taken into NetworkMonitor from while creating it. The NetworkMonitor is created when a new agent is registered but the extra info is not available at that time. Make sure the field is set in the NetworkInfo when registering. Bug: 156173829 Test: adb shell dumpsys network and check the apn in the extra info shown correctly Test: atest FrameworkNetTests Merged-In: Ieaad8cbf1a28af3b97c7f98f74358e417fcad661 Change-Id: Ieaad8cbf1a28af3b97c7f98f74358e417fcad661 --- core/java/android/net/NetworkAgent.java | 1 + core/java/android/net/NetworkAgentConfig.java | 41 ++++++++++++++++++- .../android/net/NetworkAgentConfigTest.kt | 2 +- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 65e772cb5e..482d2d2192 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -357,6 +357,7 @@ public abstract class NetworkAgent { final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacyType, config.legacyTypeName, ""); ni.setIsAvailable(true); + ni.setExtraInfo(config.getLegacyExtraInfo()); return ni; } diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java index fee868a93b..fe1268d79b 100644 --- a/core/java/android/net/NetworkAgentConfig.java +++ b/core/java/android/net/NetworkAgentConfig.java @@ -185,6 +185,26 @@ public final class NetworkAgentConfig implements Parcelable { return legacyTypeName; } + /** + * The legacy extra info of the agent. The extra info should only be : + *

      + *
    • For cellular agents, the APN name.
    • + *
    • For ethernet agents, the interface name.
    • + *
    + * @hide + */ + @NonNull + private String mLegacyExtraInfo = ""; + + /** + * The legacy extra info of the agent. + * @hide + */ + @NonNull + public String getLegacyExtraInfo() { + return mLegacyExtraInfo; + } + /** @hide */ public NetworkAgentConfig() { } @@ -201,6 +221,7 @@ public final class NetworkAgentConfig implements Parcelable { skip464xlat = nac.skip464xlat; legacyType = nac.legacyType; legacyTypeName = nac.legacyTypeName; + mLegacyExtraInfo = nac.mLegacyExtraInfo; } } @@ -308,6 +329,18 @@ public final class NetworkAgentConfig implements Parcelable { return this; } + /** + * Sets the legacy extra info of the agent. + * @param legacyExtraInfo the legacy extra info. + * @return this builder, to facilitate chaining. + * @hide + */ + @NonNull + public Builder setLegacyExtraInfo(@NonNull String legacyExtraInfo) { + mConfig.mLegacyExtraInfo = legacyExtraInfo; + return this; + } + /** * Returns the constructed {@link NetworkAgentConfig} object. */ @@ -330,14 +363,15 @@ public final class NetworkAgentConfig implements Parcelable { && skip464xlat == that.skip464xlat && legacyType == that.legacyType && Objects.equals(subscriberId, that.subscriberId) - && Objects.equals(legacyTypeName, that.legacyTypeName); + && Objects.equals(legacyTypeName, that.legacyTypeName) + && Objects.equals(mLegacyExtraInfo, that.mLegacyExtraInfo); } @Override public int hashCode() { return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated, acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId, - skip464xlat, legacyType, legacyTypeName); + skip464xlat, legacyType, legacyTypeName, mLegacyExtraInfo); } @Override @@ -353,6 +387,7 @@ public final class NetworkAgentConfig implements Parcelable { + ", legacyType = " + legacyType + ", hasShownBroken = " + hasShownBroken + ", legacyTypeName = '" + legacyTypeName + '\'' + + ", legacyExtraInfo = '" + mLegacyExtraInfo + '\'' + "}"; } @@ -372,6 +407,7 @@ public final class NetworkAgentConfig implements Parcelable { out.writeInt(skip464xlat ? 1 : 0); out.writeInt(legacyType); out.writeString(legacyTypeName); + out.writeString(mLegacyExtraInfo); } public static final @NonNull Creator CREATOR = @@ -388,6 +424,7 @@ public final class NetworkAgentConfig implements Parcelable { networkAgentConfig.skip464xlat = in.readInt() != 0; networkAgentConfig.legacyType = in.readInt(); networkAgentConfig.legacyTypeName = in.readString(); + networkAgentConfig.mLegacyExtraInfo = in.readString(); return networkAgentConfig; } diff --git a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt index de65ba2497..a4d8353d12 100644 --- a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt +++ b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt @@ -44,7 +44,7 @@ class NetworkAgentConfigTest { setPartialConnectivityAcceptable(false) setUnvalidatedConnectivityAcceptable(true) }.build() - assertParcelSane(config, 9) + assertParcelSane(config, 10) } @Test @IgnoreUpTo(Build.VERSION_CODES.Q) From 9d2a21503b0fb5d114e89e345c85c1cd03dca659 Mon Sep 17 00:00:00 2001 From: Treehugger Robot Date: Fri, 5 Jun 2020 03:36:44 +0000 Subject: [PATCH 213/229] Update javadoc to use complete sentence Avoid using the "iff" abbreviation in our Javadoc. Bug: 158092978 Test: m doc-comment-check-docs and check the generated doc Merged-In: I41bf8a6ddad200f00524d9b2dd1bf169810ee460 Change-Id: I41bf8a6ddad200f00524d9b2dd1bf169810ee460 --- core/java/android/net/NetworkRequest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java index a6bd74a587..473e6c5a72 100644 --- a/core/java/android/net/NetworkRequest.java +++ b/core/java/android/net/NetworkRequest.java @@ -468,8 +468,8 @@ public class NetworkRequest implements Parcelable { } /** - * Returns true iff. the capabilities requested in this NetworkRequest are satisfied by the - * provided {@link NetworkCapabilities}. + * Returns true if and only if the capabilities requested in this NetworkRequest are satisfied + * by the provided {@link NetworkCapabilities}. * * @param nc Capabilities that should satisfy this NetworkRequest. null capabilities do not * satisfy any request. From a8eab54eeed5dbe995b26785592e4c869200fe8e Mon Sep 17 00:00:00 2001 From: Aaron Huang Date: Tue, 28 Apr 2020 18:07:42 +0800 Subject: [PATCH 214/229] Add unit test for NetworkStatsSubscriptionsMonitor Bug: 154080205 Test: atest FrameworksNetTests:com.android.server.net.NetworkStatsSubscriptionsMonitorTest Change-Id: I4ef3f1ab2e5ea1322133edd80db3ccd0022e9c91 --- .../NetworkStatsSubscriptionsMonitorTest.java | 218 ++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java diff --git a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java new file mode 100644 index 0000000000..058856dcd6 --- /dev/null +++ b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2020 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.net; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyInt; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.annotation.NonNull; +import android.content.Context; +import android.os.Looper; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import com.android.internal.util.CollectionUtils; +import com.android.server.net.NetworkStatsSubscriptionsMonitor.Delegate; +import com.android.server.net.NetworkStatsSubscriptionsMonitor.RatTypeListener; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +@RunWith(JUnit4.class) +public final class NetworkStatsSubscriptionsMonitorTest { + private static final int TEST_SUBID1 = 3; + private static final int TEST_SUBID2 = 5; + private static final String TEST_IMSI1 = "466921234567890"; + private static final String TEST_IMSI2 = "466920987654321"; + private static final String TEST_IMSI3 = "466929999999999"; + + @Mock private Context mContext; + @Mock private PhoneStateListener mPhoneStateListener; + @Mock private SubscriptionManager mSubscriptionManager; + @Mock private TelephonyManager mTelephonyManager; + @Mock private Delegate mDelegate; + private final List mTestSubList = new ArrayList<>(); + + private final Executor mExecutor = Executors.newSingleThreadExecutor(); + private NetworkStatsSubscriptionsMonitor mMonitor; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + if (Looper.myLooper() == null) { + Looper.prepare(); + } + + when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); + + when(mContext.getSystemService(eq(Context.TELEPHONY_SUBSCRIPTION_SERVICE))) + .thenReturn(mSubscriptionManager); + when(mContext.getSystemService(eq(Context.TELEPHONY_SERVICE))) + .thenReturn(mTelephonyManager); + + mMonitor = new NetworkStatsSubscriptionsMonitor(mContext, mExecutor, mDelegate); + } + + @Test + public void testStartStop() { + // Verify that addOnSubscriptionsChangedListener() is never called before start(). + verify(mSubscriptionManager, never()) + .addOnSubscriptionsChangedListener(mExecutor, mMonitor); + mMonitor.start(); + verify(mSubscriptionManager).addOnSubscriptionsChangedListener(mExecutor, mMonitor); + + // Verify that removeOnSubscriptionsChangedListener() is never called before stop() + verify(mSubscriptionManager, never()).removeOnSubscriptionsChangedListener(mMonitor); + mMonitor.stop(); + verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(mMonitor); + } + + @NonNull + private static int[] convertArrayListToIntArray(@NonNull List arrayList) { + final int[] list = new int[arrayList.size()]; + for (int i = 0; i < arrayList.size(); i++) { + list[i] = arrayList.get(i); + } + return list; + } + + private void setRatTypeForSub(List listeners, + int subId, int type) { + final ServiceState serviceState = mock(ServiceState.class); + when(serviceState.getDataNetworkType()).thenReturn(type); + final RatTypeListener match = CollectionUtils + .find(listeners, it -> it.getSubId() == subId); + if (match != null) { + match.onServiceStateChanged(serviceState); + } + } + + private void addTestSub(int subId, String subscriberId) { + // add SubId to TestSubList. + if (!mTestSubList.contains(subId)) { + mTestSubList.add(subId); + } + final int[] subList = convertArrayListToIntArray(mTestSubList); + when(mSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(subList); + when(mTelephonyManager.getSubscriberId(subId)).thenReturn(subscriberId); + mMonitor.onSubscriptionsChanged(); + } + + private void removeTestSub(int subId) { + // Remove subId from TestSubList. + mTestSubList.removeIf(it -> it == subId); + final int[] subList = convertArrayListToIntArray(mTestSubList); + when(mSubscriptionManager.getCompleteActiveSubscriptionIdList()).thenReturn(subList); + mMonitor.onSubscriptionsChanged(); + } + + private void assertRatTypeChangedForSub(String subscriberId, int ratType) { + assertEquals(mMonitor.getRatTypeForSubscriberId(subscriberId), ratType); + final ArgumentCaptor typeCaptor = ArgumentCaptor.forClass(Integer.class); + // Verify callback with the subscriberId and the RAT type should be as expected. + // It will fail if get a callback with an unexpected RAT type. + verify(mDelegate).onCollapsedRatTypeChanged(eq(subscriberId), typeCaptor.capture()); + final int type = typeCaptor.getValue(); + assertEquals(ratType, type); + } + + private void assertRatTypeNotChangedForSub(String subscriberId, int ratType) { + assertEquals(mMonitor.getRatTypeForSubscriberId(subscriberId), ratType); + // Should never get callback with any RAT type. + verify(mDelegate, never()).onCollapsedRatTypeChanged(eq(subscriberId), anyInt()); + } + + @Test + public void testSubChangedAndRatTypeChanged() { + final ArgumentCaptor ratTypeListenerCaptor = + ArgumentCaptor.forClass(RatTypeListener.class); + + mMonitor.start(); + // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback + // before changing RAT type. + addTestSub(TEST_SUBID1, TEST_IMSI1); + assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); + + // Insert sim2. + addTestSub(TEST_SUBID2, TEST_IMSI2); + assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); + verify(mTelephonyManager, times(2)).listen(ratTypeListenerCaptor.capture(), + eq(PhoneStateListener.LISTEN_SERVICE_STATE)); + reset(mDelegate); + + // Set RAT type of sim1 to UMTS. + // Verify RAT type of sim1 after subscription gets onCollapsedRatTypeChanged() callback + // and others remain untouched. + setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1, + TelephonyManager.NETWORK_TYPE_UMTS); + assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS); + assertRatTypeNotChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UNKNOWN); + assertRatTypeNotChangedForSub(TEST_IMSI3, TelephonyManager.NETWORK_TYPE_UNKNOWN); + reset(mDelegate); + + // Set RAT type of sim2 to LTE. + // Verify RAT type of sim2 after subscription gets onCollapsedRatTypeChanged() callback + // and others remain untouched. + setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID2, + TelephonyManager.NETWORK_TYPE_LTE); + assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS); + assertRatTypeChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_LTE); + assertRatTypeNotChangedForSub(TEST_IMSI3, TelephonyManager.NETWORK_TYPE_UNKNOWN); + reset(mDelegate); + + // Remove sim2 and verify that callbacks are fired and RAT type is correct for sim2. + // while the other two remain untouched. + removeTestSub(TEST_SUBID2); + verify(mTelephonyManager).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); + assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS); + assertRatTypeChangedForSub(TEST_IMSI2, TelephonyManager.NETWORK_TYPE_UNKNOWN); + assertRatTypeNotChangedForSub(TEST_IMSI3, TelephonyManager.NETWORK_TYPE_UNKNOWN); + reset(mDelegate); + + // Set RAT type of sim1 to UNKNOWN. Then stop monitoring subscription changes + // and verify that the listener for sim1 is removed. + setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1, + TelephonyManager.NETWORK_TYPE_UNKNOWN); + assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); + reset(mDelegate); + + mMonitor.stop(); + verify(mTelephonyManager, times(2)).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); + assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); + } +} From f949ec251f017886afc2595a5e3a544a3bb59940 Mon Sep 17 00:00:00 2001 From: markchien Date: Wed, 3 Jun 2020 22:55:27 +0800 Subject: [PATCH 215/229] Cleanup config_mobile_hotspot_provision_app usage config_mobile_hotspot_provision_app would be move out of framework and only private for tethering only. enforceTetherChangePermission is no longer needed because its only caller PanService already gate by other privileged permission (BLUETOOTH_PRIVILEGED). Bug: 146918263 Test: m Change-Id: I030871c2bc46bc09c4e52970b4995f98d31bb90e Merged-In: I030871c2bc46bc09c4e52970b4995f98d31bb90e --- .../java/android/net/ConnectivityManager.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 36ffe50ef8..ba348993e2 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2246,26 +2246,6 @@ public class ConnectivityManager { .getPackageNameForUid(context, uid), true /* throwException */); } - /** {@hide} */ - public static final void enforceTetherChangePermission(Context context, String callingPkg) { - Preconditions.checkNotNull(context, "Context cannot be null"); - Preconditions.checkNotNull(callingPkg, "callingPkg cannot be null"); - - if (context.getResources().getStringArray( - com.android.internal.R.array.config_mobile_hotspot_provision_app).length == 2) { - // Have a provisioning app - must only let system apps (which check this app) - // turn on tethering - context.enforceCallingOrSelfPermission( - android.Manifest.permission.TETHER_PRIVILEGED, "ConnectivityService"); - } else { - int uid = Binder.getCallingUid(); - // If callingPkg's uid is not same as Binder.getCallingUid(), - // AppOpsService throws SecurityException. - Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPkg, - true /* throwException */); - } - } - /** * @deprecated - use getSystemService. This is a kludge to support static access in certain * situations where a Context pointer is unavailable. From cece40543ed1695b4a5451c7fe4cd7ba62d6e2b7 Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Thu, 11 Jun 2020 13:03:37 +0000 Subject: [PATCH 216/229] Document the limitation to a hundred callbacks. Some developers have been surprised by this limitation and had trouble figuring out what the issue was. Add documentation to address this. This also includes a drive-by removal of a duplicate check. Bug: 149867479 Test: doc-only change Original-Change: https://android-review.googlesource.com/1313813 Merged-In: I5911d01984695550b6c9afe7a8eb535bf5e320a1 Change-Id: I5911d01984695550b6c9afe7a8eb535bf5e320a1 --- .../net/ConnectivityDiagnosticsManager.java | 8 ++ .../java/android/net/ConnectivityManager.java | 87 +++++++++++++++++-- .../android/server/ConnectivityService.java | 2 +- 3 files changed, 87 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java index 275e38c744..704f31d7f7 100644 --- a/core/java/android/net/ConnectivityDiagnosticsManager.java +++ b/core/java/android/net/ConnectivityDiagnosticsManager.java @@ -711,6 +711,13 @@ public class ConnectivityDiagnosticsManager { * not currently registered. If a ConnectivityDiagnosticsCallback instance is registered with * multiple NetworkRequests, an IllegalArgumentException will be thrown. * + *

    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 + * callbacks in {@link ConnectivityManager}. Registering a callback 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 #unregisterConnectivityDiagnosticsCallback}. + * * @param request The NetworkRequest that will be used to match with Networks for which * callbacks will be fired * @param e The Executor to be used for running the callback method invocations @@ -718,6 +725,7 @@ public class ConnectivityDiagnosticsManager { * System * @throws IllegalArgumentException if the same callback instance is registered with multiple * NetworkRequests + * @throws RuntimeException if the app already has too many callbacks registered. */ public void registerConnectivityDiagnosticsCallback( @NonNull NetworkRequest request, diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index ba348993e2..a29f878260 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -3794,13 +3794,22 @@ public class ConnectivityManager { * or the ability to modify system settings as determined by * {@link android.provider.Settings.System#canWrite}.

    * + *

    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 + * all variants of this method, of {@link #registerNetworkCallback} 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} to be utilized for this request. Note * the callback must not be shared - it uniquely specifies this request. * The callback is invoked on the default internal Handler. * @throws IllegalArgumentException if {@code request} contains invalid network capabilities. * @throws SecurityException if missing the appropriate permissions. - * @throws RuntimeException if request limit per UID is exceeded. + * @throws RuntimeException if the app already has too many callbacks registered. */ public void requestNetwork(@NonNull NetworkRequest request, @NonNull NetworkCallback networkCallback) { @@ -3814,8 +3823,8 @@ public class ConnectivityManager { * but runs all the callbacks on the passed Handler. * *

    This method has the same permission requirements as - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} and throws the same exceptions in - * the same conditions. + * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, is subject to the same limitations, + * and throws the same exceptions in the same conditions. * * @param request {@link NetworkRequest} describing this request. * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note @@ -3846,8 +3855,8 @@ public class ConnectivityManager { * for that purpose. Calling this method will attempt to bring up the requested network. * *

    This method has the same permission requirements as - * {@link #requestNetwork(NetworkRequest, NetworkCallback)} and throws the same exceptions in - * the same conditions. + * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, is subject to the same limitations, + * and throws the same exceptions in the same conditions. * * @param request {@link NetworkRequest} describing this request. * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note @@ -3873,8 +3882,8 @@ public class ConnectivityManager { * on the passed Handler. * *

    This method has the same permission requirements as - * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} and throws the same exceptions - * in the same conditions. + * {@link #requestNetwork(NetworkRequest, NetworkCallback)}, is subject to the same limitations, + * and throws the same exceptions in the same conditions. * * @param request {@link NetworkRequest} describing this request. * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note @@ -3943,6 +3952,15 @@ public class ConnectivityManager { * is unknown prior to bringing up the network so the framework does not * know how to go about satisfying a request with these capabilities. * + *

    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 + * all variants of this method, of {@link #registerNetworkCallback} 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(PendingIntent)} + * or {@link #releaseNetworkRequest(PendingIntent)}. + * *

    This method requires the caller to hold either the * {@link android.Manifest.permission#CHANGE_NETWORK_STATE} permission * or the ability to modify system settings as determined by @@ -3954,7 +3972,7 @@ public class ConnectivityManager { * comes from {@link PendingIntent#getBroadcast}. Cannot be null. * @throws IllegalArgumentException if {@code request} contains invalid network capabilities. * @throws SecurityException if missing the appropriate permissions. - * @throws RuntimeException if request limit per UID is exceeded. + * @throws RuntimeException if the app already has too many callbacks registered. */ public void requestNetwork(@NonNull NetworkRequest request, @NonNull PendingIntent operation) { @@ -4010,10 +4028,20 @@ public class ConnectivityManager { * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is * called. * + *

    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 + * all variants of this method, of {@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. * The callback is invoked on the default internal Handler. + * @throws RuntimeException if the app already has too many callbacks registered. */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull NetworkRequest request, @@ -4027,10 +4055,21 @@ public class ConnectivityManager { * either the application exits or {@link #unregisterNetworkCallback(NetworkCallback)} is * called. * + *

    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 + * all variants of this method, of {@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. */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull NetworkRequest request, @@ -4064,10 +4103,21 @@ public class ConnectivityManager { *

    * The request may be released normally by calling * {@link #unregisterNetworkCallback(android.app.PendingIntent)}. + * + *

    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 + * all variants of this method, of {@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(PendingIntent)} + * or {@link #releaseNetworkRequest(PendingIntent)}. + * * @param request {@link NetworkRequest} describing this request. * @param operation Action to perform when the network is available (corresponds * to the {@link NetworkCallback#onAvailable} call. Typically * comes from {@link PendingIntent#getBroadcast}. Cannot be null. + * @throws RuntimeException if the app already has too many callbacks registered. */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerNetworkCallback(@NonNull NetworkRequest request, @@ -4089,9 +4139,19 @@ public class ConnectivityManager { * will continue to be called until either the application exits or * {@link #unregisterNetworkCallback(NetworkCallback)} is called. * + *

    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 + * all variants of this method, of {@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 networkCallback The {@link NetworkCallback} that the system will call as the * system default network changes. * The callback is invoked on the default internal Handler. + * @throws RuntimeException if the app already has too many callbacks registered. */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback) { @@ -4103,9 +4163,19 @@ public class ConnectivityManager { * will continue to be called until either the application exits or * {@link #unregisterNetworkCallback(NetworkCallback)} is called. * + *

    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 + * all variants of this method, of {@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 networkCallback The {@link NetworkCallback} that the system will call as the * system default network changes. * @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. */ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerDefaultNetworkCallback(@NonNull NetworkCallback networkCallback, @@ -4197,7 +4267,6 @@ public class ConnectivityManager { * Cannot be null. */ public void unregisterNetworkCallback(@NonNull PendingIntent operation) { - checkPendingIntentNotNull(operation); releaseNetworkRequest(operation); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 0ab571854c..2958fd2ae6 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -6426,7 +6426,7 @@ public class ConnectivityService extends IConnectivityManager.Stub final boolean shouldFilter = requiresVpnIsolation(nai, newNc, nai.linkProperties); final String iface = nai.linkProperties.getInterfaceName(); // For VPN uid interface filtering, old ranges need to be removed before new ranges can - // be added, due to the range being expanded and stored as invidiual UIDs. For example + // be added, due to the range being expanded and stored as individual UIDs. For example // the UIDs might be updated from [0, 99999] to ([0, 10012], [10014, 99999]) which means // prevRanges = [0, 99999] while newRanges = [0, 10012], [10014, 99999]. If prevRanges // were added first and then newRanges got removed later, there would be only one uid From c3884937e1d280f64ba9f568cc502f8e7976a3c3 Mon Sep 17 00:00:00 2001 From: Remi NGUYEN VAN Date: Mon, 8 Jun 2020 15:40:06 +0900 Subject: [PATCH 217/229] Move Inet[4]AddressUtils to libs/net The classes should not be picked up from frameworks/base, as they are part of several mainline modules. Also refine comments in DhcpResults following feedback in previous change. Bug: 151052811 Test: m; manual: flashed, wifi and telephony working Test: atest NetworkStackCoverageTests Change-Id: I7074651c6a2a7a6b11bcf13cc4bb03833d7d655f --- core/java/android/net/NetworkUtils.java | 3 ++- core/java/android/net/StaticIpConfiguration.java | 2 +- tests/net/common/java/android/net/DhcpInfoTest.java | 3 +-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 779f7bc91e..b5095a4180 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -21,13 +21,14 @@ import static android.system.OsConstants.AF_INET6; import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; -import android.net.shared.Inet4AddressUtils; import android.os.Build; import android.system.ErrnoException; import android.system.Os; import android.util.Log; import android.util.Pair; +import com.android.net.module.util.Inet4AddressUtils; + import java.io.FileDescriptor; import java.math.BigInteger; import java.net.Inet4Address; diff --git a/core/java/android/net/StaticIpConfiguration.java b/core/java/android/net/StaticIpConfiguration.java index f24a9bd530..a973455baa 100644 --- a/core/java/android/net/StaticIpConfiguration.java +++ b/core/java/android/net/StaticIpConfiguration.java @@ -21,11 +21,11 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; -import android.net.shared.InetAddressUtils; import android.os.Parcel; import android.os.Parcelable; import com.android.internal.util.Preconditions; +import com.android.net.module.util.InetAddressUtils; import java.net.InetAddress; import java.util.ArrayList; diff --git a/tests/net/common/java/android/net/DhcpInfoTest.java b/tests/net/common/java/android/net/DhcpInfoTest.java index bd5533f339..4d45ad72a9 100644 --- a/tests/net/common/java/android/net/DhcpInfoTest.java +++ b/tests/net/common/java/android/net/DhcpInfoTest.java @@ -16,8 +16,7 @@ package android.net; -import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTL; - +import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTL; import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals; import static com.android.testutils.ParcelUtilsKt.parcelingRoundTrip; From b00152243319ebd18cb61682bfbac0e207599554 Mon Sep 17 00:00:00 2001 From: Benedict Wong Date: Mon, 15 Jun 2020 17:54:29 +0000 Subject: [PATCH 218/229] Set correct owner UID for VPN agentConnect() This commit changes agentConnect to set the owner UID as the mOwnerUid field instead of the Binder.getCallingUid(). Binder.getCallingUid() can return incorrect results for platform VPNs, as agentConnect() is called under a clean calling UID. Additionally, this relaxes the ownerUid sanitization check to allow a VPN network's owner to see it's own ownership information. Vpn.mOwnerUid is guaranteed to be correct, as all VPNs MUST have called prepareInternal() at some previous point, which sets mOwnerUid as the package's UID (or SYSTEM_UID if this is legacy VPN). Bug: 150135470 Test: CTS tests showing ownership information Merged-In: Ic979dad73983d722365849fbfb0becfd432b894c Change-Id: Ic979dad73983d722365849fbfb0becfd432b894c (cherry picked from commit e29bf99a7fc1067c546d7fa6cbcb9001fb110d16) --- .../java/android/net/NetworkCapabilities.java | 27 +++++++++++++++---- .../android/server/ConnectivityService.java | 6 +++++ 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java index a3fd60e9d3..004f84422b 100644 --- a/core/java/android/net/NetworkCapabilities.java +++ b/core/java/android/net/NetworkCapabilities.java @@ -900,9 +900,17 @@ public final class NetworkCapabilities implements Parcelable { *

    For NetworkCapability instances being sent from ConnectivityService, this value MUST be * reset to Process.INVALID_UID unless all the following conditions are met: * + *

    The caller is the network owner, AND one of the following sets of requirements is met: + * *

      - *
    1. The destination app is the network owner - *
    2. The destination app has the ACCESS_FINE_LOCATION permission granted + *
    3. The described Network is a VPN + *
    + * + *

    OR: + * + *

      + *
    1. The calling app is the network owner + *
    2. The calling app has the ACCESS_FINE_LOCATION permission granted *
    3. The user's location toggle is on *
    * @@ -928,7 +936,16 @@ public final class NetworkCapabilities implements Parcelable { /** * Retrieves the UID of the app that owns this network. * - *

    For user privacy reasons, this field will only be populated if: + *

    For user privacy reasons, this field will only be populated if the following conditions + * are met: + * + *

    The caller is the network owner, AND one of the following sets of requirements is met: + * + *

      + *
    1. The described Network is a VPN + *
    + * + *

    OR: * *

      *
    1. The calling app is the network owner @@ -936,8 +953,8 @@ public final class NetworkCapabilities implements Parcelable { *
    2. The user's location toggle is on *
    * - * Instances of NetworkCapabilities sent to apps without the appropriate permissions will - * have this field cleared out. + * Instances of NetworkCapabilities sent to apps without the appropriate permissions will have + * this field cleared out. */ public int getOwnerUid() { return mOwnerUid; diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2958fd2ae6..36ba610085 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1698,6 +1698,12 @@ public class ConnectivityService extends IConnectivityManager.Stub return newNc; } + // Allow VPNs to see ownership of their own VPN networks - not location sensitive. + if (nc.hasTransport(TRANSPORT_VPN)) { + // Owner UIDs already checked above. No need to re-check. + return newNc; + } + Binder.withCleanCallingIdentity( () -> { if (!mLocationPermissionChecker.checkLocationPermission( From 1182d5a7fc26b8448b3e34b218896c0b6a9e7916 Mon Sep 17 00:00:00 2001 From: Chiachang Wang Date: Tue, 16 Jun 2020 01:02:52 +0000 Subject: [PATCH 219/229] Test extra info sent to NetworkMonitor Test extra info sent to NetworkMonitor correctly if network agent is created through new NetworkAgent constructor without legacy network info taken as parameter. Bug: 156173829 Test: atest FrameworkNetTests Merged-In: I4f827664c528bea30cc957a0a617dd37693f4460 Change-Id: I4f827664c528bea30cc957a0a617dd37693f4460 --- .../server/ConnectivityServiceTest.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index c86d388a3d..385005f90c 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -100,6 +100,7 @@ import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.startsWith; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.any; @@ -164,6 +165,8 @@ import android.net.LinkAddress; import android.net.LinkProperties; import android.net.MatchAllNetworkSpecifier; import android.net.Network; +import android.net.NetworkAgent; +import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkFactory; import android.net.NetworkInfo; @@ -6800,6 +6803,30 @@ public class ConnectivityServiceTest { assertEquals(wifiLp, mService.getActiveLinkProperties()); } + @Test + public void testLegacyExtraInfoSentToNetworkMonitor() throws Exception { + class TestNetworkAgent extends NetworkAgent { + TestNetworkAgent(Context context, Looper looper, NetworkAgentConfig config) { + super(context, looper, "MockAgent", new NetworkCapabilities(), + new LinkProperties(), 40 , config, null /* provider */); + } + } + final NetworkAgent naNoExtraInfo = new TestNetworkAgent( + mServiceContext, mCsHandlerThread.getLooper(), new NetworkAgentConfig()); + naNoExtraInfo.register(); + verify(mNetworkStack).makeNetworkMonitor(any(), isNull(String.class), any()); + naNoExtraInfo.unregister(); + + reset(mNetworkStack); + final NetworkAgentConfig config = + new NetworkAgentConfig.Builder().setLegacyExtraInfo("legacyinfo").build(); + final NetworkAgent naExtraInfo = new TestNetworkAgent( + mServiceContext, mCsHandlerThread.getLooper(), config); + naExtraInfo.register(); + verify(mNetworkStack).makeNetworkMonitor(any(), eq("legacyinfo"), any()); + naExtraInfo.unregister(); + } + private void setupLocationPermissions( int targetSdk, boolean locationToggle, String op, String perm) throws Exception { final ApplicationInfo applicationInfo = new ApplicationInfo(); From 58897cc491bf0fb24b8f3e49d1d80f64138f361a Mon Sep 17 00:00:00 2001 From: Treehugger Robot Date: Wed, 17 Jun 2020 13:21:06 +0000 Subject: [PATCH 220/229] Treat RouteInfo with different interfaces as different routes On Android different interfaces usually use different routing tables. As a result, a change in interface should not be treated as route update, but rather a remove and an add. This change fixes a bug in VPN seamless handover where routes failed to be updated when a new tunnel interface replaces the existing one within the same network. Bug: 158696878 Test: atest com.android.cts.net.HostsideVpnTests Test: atest NetworkStackTests Test: atest CtsNetTestCases Test: atest FrameworksNetTests Original-Change: https://android-review.googlesource.com/1331916 Merged-In: I57987233d42a0253eaee2e1ca5f28728c2354620 Change-Id: I57987233d42a0253eaee2e1ca5f28728c2354620 --- core/java/android/net/RouteInfo.java | 43 ++++++++++++++++--- .../java/android/net/LinkPropertiesTest.java | 18 ++++++++ .../java/android/net/RouteInfoTest.java | 42 +++++++++++++++++- 3 files changed, 95 insertions(+), 8 deletions(-) diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index e550f85e6b..9876076173 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -26,7 +26,6 @@ import android.net.util.NetUtils; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import android.util.Pair; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -554,15 +553,45 @@ public final class RouteInfo implements Parcelable { } /** - * A helper class that contains the destination and the gateway in a {@code RouteInfo}, - * used by {@link ConnectivityService#updateRoutes} or + * A helper class that contains the destination, the gateway and the interface in a + * {@code RouteInfo}, used by {@link ConnectivityService#updateRoutes} or * {@link LinkProperties#addRoute} to calculate the list to be updated. + * {@code RouteInfo} objects with different interfaces are treated as different routes because + * *usually* on Android different interfaces use different routing tables, and moving a route + * to a new routing table never constitutes an update, but is always a remove and an add. * * @hide */ - public static class RouteKey extends Pair { - RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway) { - super(destination, gateway); + public static class RouteKey { + @NonNull private final IpPrefix mDestination; + @Nullable private final InetAddress mGateway; + @Nullable private final String mInterface; + + RouteKey(@NonNull IpPrefix destination, @Nullable InetAddress gateway, + @Nullable String iface) { + mDestination = destination; + mGateway = gateway; + mInterface = iface; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof RouteKey)) { + return false; + } + RouteKey p = (RouteKey) o; + // No need to do anything special for scoped addresses. Inet6Address#equals does not + // consider the scope ID, but the netd route IPCs (e.g., INetd#networkAddRouteParcel) + // and the kernel ignore scoped addresses both in the prefix and in the nexthop and only + // look at RTA_OIF. + return Objects.equals(p.mDestination, mDestination) + && Objects.equals(p.mGateway, mGateway) + && Objects.equals(p.mInterface, mInterface); + } + + @Override + public int hashCode() { + return Objects.hash(mDestination, mGateway, mInterface); } } @@ -574,7 +603,7 @@ public final class RouteInfo implements Parcelable { */ @NonNull public RouteKey getRouteKey() { - return new RouteKey(mDestination, mGateway); + return new RouteKey(mDestination, mGateway, mInterface); } /** diff --git a/tests/net/common/java/android/net/LinkPropertiesTest.java b/tests/net/common/java/android/net/LinkPropertiesTest.java index 0fc9be32f4..6eba62e637 100644 --- a/tests/net/common/java/android/net/LinkPropertiesTest.java +++ b/tests/net/common/java/android/net/LinkPropertiesTest.java @@ -16,6 +16,8 @@ package android.net; +import static android.net.RouteInfo.RTN_THROW; +import static android.net.RouteInfo.RTN_UNICAST; import static android.net.RouteInfo.RTN_UNREACHABLE; import static com.android.testutils.ParcelUtilsKt.assertParcelSane; @@ -1282,4 +1284,20 @@ public class LinkPropertiesTest { assertTrue(lp.hasIpv6UnreachableDefaultRoute()); assertFalse(lp.hasIpv4UnreachableDefaultRoute()); } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testRouteAddWithSameKey() throws Exception { + LinkProperties lp = new LinkProperties(); + lp.setInterfaceName("wlan0"); + final IpPrefix v6 = new IpPrefix("64:ff9b::/96"); + lp.addRoute(new RouteInfo(v6, address("fe80::1"), "wlan0", RTN_UNICAST, 1280)); + assertEquals(1, lp.getRoutes().size()); + lp.addRoute(new RouteInfo(v6, address("fe80::1"), "wlan0", RTN_UNICAST, 1500)); + assertEquals(1, lp.getRoutes().size()); + final IpPrefix v4 = new IpPrefix("192.0.2.128/25"); + lp.addRoute(new RouteInfo(v4, address("192.0.2.1"), "wlan0", RTN_UNICAST, 1460)); + assertEquals(2, lp.getRoutes().size()); + lp.addRoute(new RouteInfo(v4, address("192.0.2.1"), "wlan0", RTN_THROW, 1460)); + assertEquals(2, lp.getRoutes().size()); + } } diff --git a/tests/net/common/java/android/net/RouteInfoTest.java b/tests/net/common/java/android/net/RouteInfoTest.java index 8204b494bb..60cac0b6b0 100644 --- a/tests/net/common/java/android/net/RouteInfoTest.java +++ b/tests/net/common/java/android/net/RouteInfoTest.java @@ -25,6 +25,7 @@ import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -56,7 +57,7 @@ public class RouteInfoTest { private static final int INVALID_ROUTE_TYPE = -1; private InetAddress Address(String addr) { - return InetAddress.parseNumericAddress(addr); + return InetAddresses.parseNumericAddress(addr); } private IpPrefix Prefix(String prefix) { @@ -391,4 +392,43 @@ public class RouteInfoTest { r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0"); assertEquals(0, r.getMtu()); } + + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) + public void testRouteKey() { + RouteInfo.RouteKey k1, k2; + // Only prefix, null gateway and null interface + k1 = new RouteInfo(Prefix("2001:db8::/128"), null).getRouteKey(); + k2 = new RouteInfo(Prefix("2001:db8::/128"), null).getRouteKey(); + assertEquals(k1, k2); + assertEquals(k1.hashCode(), k2.hashCode()); + + // With prefix, gateway and interface. Type and MTU does not affect RouteKey equality + k1 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0", + RTN_UNREACHABLE, 1450).getRouteKey(); + k2 = new RouteInfo(Prefix("192.0.2.0/24"), Address("192.0.2.1"), "wlan0", + RouteInfo.RTN_UNICAST, 1400).getRouteKey(); + assertEquals(k1, k2); + assertEquals(k1.hashCode(), k2.hashCode()); + + // Different scope IDs are ignored by the kernel, so we consider them equal here too. + k1 = new RouteInfo(Prefix("2001:db8::/64"), Address("fe80::1%1"), "wlan0").getRouteKey(); + k2 = new RouteInfo(Prefix("2001:db8::/64"), Address("fe80::1%2"), "wlan0").getRouteKey(); + assertEquals(k1, k2); + assertEquals(k1.hashCode(), k2.hashCode()); + + // Different prefix + k1 = new RouteInfo(Prefix("192.0.2.0/24"), null).getRouteKey(); + k2 = new RouteInfo(Prefix("192.0.3.0/24"), null).getRouteKey(); + assertNotEquals(k1, k2); + + // Different gateway + k1 = new RouteInfo(Prefix("ff02::1/128"), Address("2001:db8::1"), null).getRouteKey(); + k2 = new RouteInfo(Prefix("ff02::1/128"), Address("2001:db8::2"), null).getRouteKey(); + assertNotEquals(k1, k2); + + // Different interface + k1 = new RouteInfo(Prefix("ff02::1/128"), null, "tun0").getRouteKey(); + k2 = new RouteInfo(Prefix("ff02::1/128"), null, "tun1").getRouteKey(); + assertNotEquals(k1, k2); + } } From 5a42a4132fe57b344c68065d079d7abc29a6418d Mon Sep 17 00:00:00 2001 From: Luke Huang Date: Tue, 16 Jun 2020 19:10:02 +0800 Subject: [PATCH 221/229] Disable sockets and DNS if process lacks INTERNET permission. This is a Client-only solution. - Add to NetdClient a per-process std::atomic_boolean similar to netIdForProcess and netIdForResolv. - The boolean says whether the process should be allowed Internet connectivity. - Add an @hide method to NetUtils.java to set the boolean; call it from the initialization code of the new process just after forking from zygote. - Make netdClientSocket and dnsOpenProxy check the boolean. If the boolean is false, return EPERM from socket calls. Bug: 150028556 Test: atest NetworkUtilsTest Test: atest CtsAppSecurityHostTestCases:UseProcessTest Change-Id: If002280fbad493dfc2db3d9d505c0257d49a9056 Exempt-From-Owner-Approval: OWNERS already approved identical patchset 5 --- core/java/android/net/NetworkUtils.java | 8 +++ core/jni/android_net_NetUtils.cpp | 8 +++ .../java/android/net/NetworkUtilsTest.java | 60 +++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 779f7bc91e..0b92b95128 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -154,6 +154,14 @@ public class NetworkUtils { */ public static native Network getDnsNetwork() throws ErrnoException; + /** + * Allow/Disallow creating AF_INET/AF_INET6 sockets and DNS lookups for current process. + * + * @param allowNetworking whether to allow or disallow creating AF_INET/AF_INET6 sockets + * and DNS lookups. + */ + public static native void setAllowNetworkingForProcess(boolean allowNetworking); + /** * Get the tcp repair window associated with the {@code fd}. * diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index 03b9793ccb..d4805acb06 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -226,6 +226,11 @@ static jobject android_net_utils_getDnsNetwork(JNIEnv *env, jobject thiz) { class_Network, ctor, dnsNetId & ~NETID_USE_LOCAL_NAMESERVERS, privateDnsBypass); } +static void android_net_utils_setAllowNetworkingForProcess(JNIEnv *env, jobject thiz, + jboolean hasConnectivity) { + setAllowNetworkingForProcess(hasConnectivity == JNI_TRUE); +} + static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) { if (javaFd == NULL) { jniThrowNullPointerException(env, NULL); @@ -266,6 +271,7 @@ static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, j /* * JNI registration. */ +// clang-format off static const JNINativeMethod gNetworkUtilMethods[] = { /* name, signature, funcPtr */ { "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork }, @@ -282,7 +288,9 @@ static const JNINativeMethod gNetworkUtilMethods[] = { { "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult }, { "resNetworkCancel", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_resNetworkCancel }, { "getDnsNetwork", "()Landroid/net/Network;", (void*) android_net_utils_getDnsNetwork }, + { "setAllowNetworkingForProcess", "(Z)V", (void *)android_net_utils_setAllowNetworkingForProcess }, }; +// clang-format on int register_android_net_NetworkUtils(JNIEnv* env) { diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java index 7748288aeb..3158cc8637 100644 --- a/tests/net/java/android/net/NetworkUtilsTest.java +++ b/tests/net/java/android/net/NetworkUtilsTest.java @@ -16,10 +16,24 @@ package android.net; +import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_INET6; +import static android.system.OsConstants.AF_UNIX; +import static android.system.OsConstants.EPERM; +import static android.system.OsConstants.SOCK_DGRAM; +import static android.system.OsConstants.SOCK_STREAM; + import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.system.ErrnoException; +import android.system.Os; + import androidx.test.runner.AndroidJUnit4; +import libcore.io.IoUtils; + import org.junit.Test; import org.junit.runner.RunWith; @@ -125,4 +139,50 @@ public class NetworkUtilsTest { assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536), NetworkUtils.routedIPv6AddressCount(set)); } + + private static void expectSocketSuccess(String msg, int domain, int type) { + try { + IoUtils.closeQuietly(Os.socket(domain, type, 0)); + } catch (ErrnoException e) { + fail(msg + e.getMessage()); + } + } + + private static void expectSocketPemissionError(String msg, int domain, int type) { + try { + IoUtils.closeQuietly(Os.socket(domain, type, 0)); + fail(msg); + } catch (ErrnoException e) { + assertEquals(msg, e.errno, EPERM); + } + } + + private static void expectHasNetworking() { + expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException", + AF_UNIX, SOCK_STREAM); + expectSocketSuccess("Creating a AF_INET socket shouldn't have thrown ErrnoException", + AF_INET, SOCK_DGRAM); + expectSocketSuccess("Creating a AF_INET6 socket shouldn't have thrown ErrnoException", + AF_INET6, SOCK_DGRAM); + } + + private static void expectNoNetworking() { + expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException", + AF_UNIX, SOCK_STREAM); + expectSocketPemissionError( + "Creating a AF_INET socket should have thrown ErrnoException(EPERM)", + AF_INET, SOCK_DGRAM); + expectSocketPemissionError( + "Creating a AF_INET6 socket should have thrown ErrnoException(EPERM)", + AF_INET6, SOCK_DGRAM); + } + + @Test + public void testSetAllowNetworkingForProcess() { + expectHasNetworking(); + NetworkUtils.setAllowNetworkingForProcess(false); + expectNoNetworking(); + NetworkUtils.setAllowNetworkingForProcess(true); + expectHasNetworking(); + } } From 51221efa456559189a1b226865221a33e5787b1a Mon Sep 17 00:00:00 2001 From: Luke Huang Date: Tue, 16 Jun 2020 08:13:28 +0800 Subject: [PATCH 222/229] Move DnsPacket to libs net This class might be used by some mainline modules. Bug: 151052811 Test: atest DnsPacketTest Test: atest DnsResolverTest Change-Id: I8841d91456952ded5efbf8ea221289aecc7746ad --- core/java/android/net/DnsResolver.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java index 0b1a84534e..3f7660f570 100644 --- a/core/java/android/net/DnsResolver.java +++ b/core/java/android/net/DnsResolver.java @@ -38,6 +38,8 @@ import android.os.MessageQueue; import android.system.ErrnoException; import android.util.Log; +import com.android.net.module.util.DnsPacket; + import java.io.FileDescriptor; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -97,7 +99,7 @@ public final class DnsResolver { @interface DnsError {} /** * Indicates that there was an error parsing the response the query. - * The cause of this error is available via getCause() and is a ParseException. + * The cause of this error is available via getCause() and is a {@link ParseException}. */ public static final int ERROR_PARSE = 0; /** @@ -290,8 +292,15 @@ public final class DnsResolver { } try { mAllAnswers.addAll(new DnsAddressAnswer(answer).getAddresses()); - } catch (ParseException e) { - mDnsException = new DnsException(ERROR_PARSE, e); + } catch (DnsPacket.ParseException e) { + // Convert the com.android.net.module.util.DnsPacket.ParseException to an + // android.net.ParseException. This is the type that was used in Q and is implied + // by the public documentation of ERROR_PARSE. + // + // DnsPacket cannot throw android.net.ParseException directly because it's @hide. + ParseException pe = new ParseException(e.reason, e.getCause()); + pe.setStackTrace(e.getStackTrace()); + mDnsException = new DnsException(ERROR_PARSE, pe); } maybeReportAnswer(); } From f2db66615de841df6187e5ac9b86627cb89d51d2 Mon Sep 17 00:00:00 2001 From: paulhu Date: Tue, 9 Jun 2020 19:07:03 +0800 Subject: [PATCH 223/229] Make PendingIntent immutable and correct Settings package name ConnectivityService puts up some notifications with pending intents, but these pending intents are mutable that content can be changed by someone. So make these pending intents to be immutable. Some OEMs have their own Settings package. Thus, need to get the current using Settings package name instead of just use default name "com.android.settings". Bug: 154928507 Test: atest FrameworksNetTests Change-Id: I02e3277358623400aa03dc8996af3d7c46a8ce76 --- .../android/server/ConnectivityService.java | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2958fd2ae6..2a1e54de2b 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -67,6 +67,7 @@ import android.app.BroadcastOptions; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -3069,7 +3070,11 @@ public class ConnectivityService extends IConnectivityManager.Stub // Only the system server can register notifications with package "android" final long token = Binder.clearCallingIdentity(); try { - pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0); + pendingIntent = PendingIntent.getBroadcast( + mContext, + 0 /* requestCode */, + intent, + PendingIntent.FLAG_IMMUTABLE); } finally { Binder.restoreCallingIdentity(token); } @@ -3925,6 +3930,15 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.decreaseIndent(); } + // TODO: This method is copied from TetheringNotificationUpdater. Should have a utility class to + // unify the method. + private static @NonNull String getSettingsPackageName(@NonNull final PackageManager pm) { + final Intent settingsIntent = new Intent(Settings.ACTION_SETTINGS); + final ComponentName settingsComponent = settingsIntent.resolveActivity(pm); + return settingsComponent != null + ? settingsComponent.getPackageName() : "com.android.settings"; + } + private void showNetworkNotification(NetworkAgentInfo nai, NotificationType type) { final String action; final boolean highPriority; @@ -3959,12 +3973,20 @@ public class ConnectivityService extends IConnectivityManager.Stub if (type != NotificationType.PRIVATE_DNS_BROKEN) { intent.setData(Uri.fromParts("netId", Integer.toString(nai.network.netId), null)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setClassName("com.android.settings", - "com.android.settings.wifi.WifiNoInternetDialog"); + // Some OEMs have their own Settings package. Thus, need to get the current using + // Settings package name instead of just use default name "com.android.settings". + final String settingsPkgName = getSettingsPackageName(mContext.getPackageManager()); + intent.setClassName(settingsPkgName, + settingsPkgName + ".wifi.WifiNoInternetDialog"); } PendingIntent pendingIntent = PendingIntent.getActivityAsUser( - mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); + mContext, + 0 /* requestCode */, + intent, + PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE, + null /* options */, + UserHandle.CURRENT); mNotifier.showNotification(nai.network.netId, type, nai, null, pendingIntent, highPriority); } From b6b7e0c2bec9f577713518f58797e77e0f225d73 Mon Sep 17 00:00:00 2001 From: Mike Yu Date: Mon, 22 Jun 2020 06:56:39 +0000 Subject: [PATCH 224/229] Support DNS-over-TLS probes in NetworkDiagnostics Probe DNS servers to see they support DNS-over-TLS. Use system CAs to verify whether the certificates sent by DNS servers are trusted or not. An error is thrown to cause the probe failed if DNS servers send untrusted certificates. Unlike the DnsResolver which doesn't verify the certificates in opportunistic mode, all of the DoT probes from NetworkDiagnostics check certificates. DoT probes apply to the DNS servers gotten from LinkProperties and the DoT servers gotten from PrivateDnsConfig whatever private DNS mode is. A common example in DNS strict mode: . DNS TLS dst{8.8.8.8} hostname{dns.google} src{192.168.43.2:48436} qtype{1} qname{815149-android-ds.metric.gstatic.com}: SUCCEEDED: 1/1 NOERROR (432ms) F DNS TLS dst{192.168.43.144} hostname{}: FAILED: java.net.ConnectException: failed to connect to /192.168.43.144 (port 853) from /192.168.43.2 (port 41770) after 2500ms: isConnected failed: ECONNREFUSED (Connection refused) (172ms) . DNS TLS dst{8.8.4.4} hostname{dns.google} src{192.168.43.2:37598} qtype{1} qname{759312-android-ds.metric.gstatic.com}: SUCCEEDED: 1/1 NOERROR (427ms) An example when the CA is not trusted: F DNS TLS dst{8.8.8.8} hostname{dns.google}: FAILED: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found. (16ms) An example when TCP/TLS handshake timeout: F DNS TLS dst{8.8.8.8} hostname{dns.google}: FAILED: java.net.SocketTimeoutException: failed to connect to /8.8.8.8 (port 853) from /192.168.2.108 (port 45680) after 2500ms (2514ms) Bug: 132925257 Bug: 118369977 Test: atest FrameworksNetTests Original-Change: https://android-review.googlesource.com/1011670 Merged-In: I1b54abed0e931ca4b8a97149459cde54da1c3d6f Change-Id: I1b54abed0e931ca4b8a97149459cde54da1c3d6f --- .../android/server/ConnectivityService.java | 2 + .../server/connectivity/DnsManager.java | 19 +- .../connectivity/NetworkDiagnostics.java | 208 +++++++++++++++--- .../server/connectivity/DnsManagerTest.java | 47 ++++ 4 files changed, 237 insertions(+), 39 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 36ba610085..5f7c3e056e 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -2487,10 +2487,12 @@ public class ConnectivityService extends IConnectivityManager.Stub final List netDiags = new ArrayList(); final long DIAG_TIME_MS = 5000; for (NetworkAgentInfo nai : networksSortedById()) { + PrivateDnsConfig privateDnsCfg = mDnsManager.getPrivateDnsConfig(nai.network); // Start gathering diagnostic information. netDiags.add(new NetworkDiagnostics( nai.network, new LinkProperties(nai.linkProperties), // Must be a copy. + privateDnsCfg, DIAG_TIME_MS)); } diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java index 506c8e3919..cf6a7f6e8d 100644 --- a/services/core/java/com/android/server/connectivity/DnsManager.java +++ b/services/core/java/com/android/server/connectivity/DnsManager.java @@ -57,6 +57,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -64,7 +65,9 @@ import java.util.stream.Collectors; * Encapsulate the management of DNS settings for networks. * * This class it NOT designed for concurrent access. Furthermore, all non-static - * methods MUST be called from ConnectivityService's thread. + * methods MUST be called from ConnectivityService's thread. However, an exceptional + * case is getPrivateDnsConfig(Network) which is exclusively for + * ConnectivityService#dumpNetworkDiagnostics() on a random binder thread. * * [ Private DNS ] * The code handling Private DNS is spread across several components, but this @@ -236,8 +239,8 @@ public class DnsManager { private final ContentResolver mContentResolver; private final IDnsResolver mDnsResolver; private final MockableSystemProperties mSystemProperties; - // TODO: Replace these Maps with SparseArrays. - private final Map mPrivateDnsMap; + private final ConcurrentHashMap mPrivateDnsMap; + // TODO: Replace the Map with SparseArrays. private final Map mPrivateDnsValidationMap; private final Map mLinkPropertiesMap; private final Map mTransportsMap; @@ -247,15 +250,13 @@ public class DnsManager { private int mSuccessThreshold; private int mMinSamples; private int mMaxSamples; - private String mPrivateDnsMode; - private String mPrivateDnsSpecifier; public DnsManager(Context ctx, IDnsResolver dnsResolver, MockableSystemProperties sp) { mContext = ctx; mContentResolver = mContext.getContentResolver(); mDnsResolver = dnsResolver; mSystemProperties = sp; - mPrivateDnsMap = new HashMap<>(); + mPrivateDnsMap = new ConcurrentHashMap<>(); mPrivateDnsValidationMap = new HashMap<>(); mLinkPropertiesMap = new HashMap<>(); mTransportsMap = new HashMap<>(); @@ -275,6 +276,12 @@ public class DnsManager { mLinkPropertiesMap.remove(network.netId); } + // This is exclusively called by ConnectivityService#dumpNetworkDiagnostics() which + // is not on the ConnectivityService handler thread. + public PrivateDnsConfig getPrivateDnsConfig(@NonNull Network network) { + return mPrivateDnsMap.getOrDefault(network.netId, PRIVATE_DNS_OFF); + } + public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) { Slog.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")"); return (cfg != null) diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java index a1a8e355dc..49c16ad96e 100644 --- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java +++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java @@ -18,12 +18,15 @@ package com.android.server.connectivity; import static android.system.OsConstants.*; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkUtils; import android.net.RouteInfo; import android.net.TrafficStats; +import android.net.shared.PrivateDnsConfig; import android.net.util.NetworkConstants; import android.os.SystemClock; import android.system.ErrnoException; @@ -38,6 +41,8 @@ import com.android.internal.util.TrafficStatsConstants; import libcore.io.IoUtils; import java.io.Closeable; +import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.FileDescriptor; import java.io.IOException; import java.io.InterruptedIOException; @@ -52,6 +57,7 @@ import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -59,6 +65,12 @@ import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import javax.net.ssl.SNIHostName; +import javax.net.ssl.SNIServerName; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + /** * NetworkDiagnostics * @@ -100,6 +112,7 @@ public class NetworkDiagnostics { private final Network mNetwork; private final LinkProperties mLinkProperties; + private final PrivateDnsConfig mPrivateDnsCfg; private final Integer mInterfaceIndex; private final long mTimeoutMs; @@ -163,12 +176,15 @@ public class NetworkDiagnostics { private final Map, Measurement> mExplicitSourceIcmpChecks = new HashMap<>(); private final Map mDnsUdpChecks = new HashMap<>(); + private final Map mDnsTlsChecks = new HashMap<>(); private final String mDescription; - public NetworkDiagnostics(Network network, LinkProperties lp, long timeoutMs) { + public NetworkDiagnostics(Network network, LinkProperties lp, + @NonNull PrivateDnsConfig privateDnsCfg, long timeoutMs) { mNetwork = network; mLinkProperties = lp; + mPrivateDnsCfg = privateDnsCfg; mInterfaceIndex = getInterfaceIndex(mLinkProperties.getInterfaceName()); mTimeoutMs = timeoutMs; mStartTime = now(); @@ -199,8 +215,22 @@ public class NetworkDiagnostics { } } for (InetAddress nameserver : mLinkProperties.getDnsServers()) { - prepareIcmpMeasurement(nameserver); - prepareDnsMeasurement(nameserver); + prepareIcmpMeasurement(nameserver); + prepareDnsMeasurement(nameserver); + + // Unlike the DnsResolver which doesn't do certificate validation in opportunistic mode, + // DoT probes to the DNS servers will fail if certificate validation fails. + prepareDnsTlsMeasurement(null /* hostname */, nameserver); + } + + for (InetAddress tlsNameserver : mPrivateDnsCfg.ips) { + // Reachability check is necessary since when resolving the strict mode hostname, + // NetworkMonitor always queries for both A and AAAA records, even if the network + // is IPv4-only or IPv6-only. + if (mLinkProperties.isReachable(tlsNameserver)) { + // If there are IPs, there must have been a name that resolved to them. + prepareDnsTlsMeasurement(mPrivateDnsCfg.hostname, tlsNameserver); + } } mCountDownLatch = new CountDownLatch(totalMeasurementCount()); @@ -222,6 +252,15 @@ public class NetworkDiagnostics { } } + private static String socketAddressToString(@NonNull SocketAddress sockAddr) { + // The default toString() implementation is not the prettiest. + InetSocketAddress inetSockAddr = (InetSocketAddress) sockAddr; + InetAddress localAddr = inetSockAddr.getAddress(); + return String.format( + (localAddr instanceof Inet6Address ? "[%s]:%d" : "%s:%d"), + localAddr.getHostAddress(), inetSockAddr.getPort()); + } + private void prepareIcmpMeasurement(InetAddress target) { if (!mIcmpChecks.containsKey(target)) { Measurement measurement = new Measurement(); @@ -252,8 +291,19 @@ public class NetworkDiagnostics { } } + private void prepareDnsTlsMeasurement(@Nullable String hostname, @NonNull InetAddress target) { + // This might overwrite an existing entry in mDnsTlsChecks, because |target| can be an IP + // address configured by the network as well as an IP address learned by resolving the + // strict mode DNS hostname. If the entry is overwritten, the overwritten measurement + // thread will not execute. + Measurement measurement = new Measurement(); + measurement.thread = new Thread(new DnsTlsCheck(hostname, target, measurement)); + mDnsTlsChecks.put(target, measurement); + } + private int totalMeasurementCount() { - return mIcmpChecks.size() + mExplicitSourceIcmpChecks.size() + mDnsUdpChecks.size(); + return mIcmpChecks.size() + mExplicitSourceIcmpChecks.size() + mDnsUdpChecks.size() + + mDnsTlsChecks.size(); } private void startMeasurements() { @@ -266,6 +316,9 @@ public class NetworkDiagnostics { for (Measurement measurement : mDnsUdpChecks.values()) { measurement.thread.start(); } + for (Measurement measurement : mDnsTlsChecks.values()) { + measurement.thread.start(); + } } public void waitForMeasurements() { @@ -297,6 +350,11 @@ public class NetworkDiagnostics { measurements.add(entry.getValue()); } } + for (Map.Entry entry : mDnsTlsChecks.entrySet()) { + if (entry.getKey() instanceof Inet4Address) { + measurements.add(entry.getValue()); + } + } // IPv6 measurements second. for (Map.Entry entry : mIcmpChecks.entrySet()) { @@ -315,6 +373,11 @@ public class NetworkDiagnostics { measurements.add(entry.getValue()); } } + for (Map.Entry entry : mDnsTlsChecks.entrySet()) { + if (entry.getKey() instanceof Inet6Address) { + measurements.add(entry.getValue()); + } + } return measurements; } @@ -387,6 +450,8 @@ public class NetworkDiagnostics { try { mFileDescriptor = Os.socket(mAddressFamily, sockType, protocol); } finally { + // TODO: The tag should remain set until all traffic is sent and received. + // Consider tagging the socket after the measurement thread is started. TrafficStats.setThreadStatsTag(oldTag); } // Setting SNDTIMEO is purely for defensive purposes. @@ -403,13 +468,12 @@ public class NetworkDiagnostics { mSocketAddress = Os.getsockname(mFileDescriptor); } - protected String getSocketAddressString() { - // The default toString() implementation is not the prettiest. - InetSocketAddress inetSockAddr = (InetSocketAddress) mSocketAddress; - InetAddress localAddr = inetSockAddr.getAddress(); - return String.format( - (localAddr instanceof Inet6Address ? "[%s]:%d" : "%s:%d"), - localAddr.getHostAddress(), inetSockAddr.getPort()); + protected boolean ensureMeasurementNecessary() { + if (mMeasurement.finishTime == 0) return false; + + // Countdown latch was not decremented when the measurement failed during setup. + mCountDownLatch.countDown(); + return true; } @Override @@ -448,13 +512,7 @@ public class NetworkDiagnostics { @Override public void run() { - // Check if this measurement has already failed during setup. - if (mMeasurement.finishTime > 0) { - // If the measurement failed during construction it didn't - // decrement the countdown latch; do so here. - mCountDownLatch.countDown(); - return; - } + if (ensureMeasurementNecessary()) return; try { setupSocket(SOCK_DGRAM, mProtocol, TIMEOUT_SEND, TIMEOUT_RECV, 0); @@ -462,7 +520,7 @@ public class NetworkDiagnostics { mMeasurement.recordFailure(e.toString()); return; } - mMeasurement.description += " src{" + getSocketAddressString() + "}"; + mMeasurement.description += " src{" + socketAddressToString(mSocketAddress) + "}"; // Build a trivial ICMP packet. final byte[] icmpPacket = { @@ -507,10 +565,10 @@ public class NetworkDiagnostics { private static final int RR_TYPE_AAAA = 28; private static final int PACKET_BUFSIZE = 512; - private final Random mRandom = new Random(); + protected final Random mRandom = new Random(); // Should be static, but the compiler mocks our puny, human attempts at reason. - private String responseCodeStr(int rcode) { + protected String responseCodeStr(int rcode) { try { return DnsResponseCode.values()[rcode].toString(); } catch (IndexOutOfBoundsException e) { @@ -518,7 +576,7 @@ public class NetworkDiagnostics { } } - private final int mQueryType; + protected final int mQueryType; public DnsUdpCheck(InetAddress target, Measurement measurement) { super(target, measurement); @@ -535,13 +593,7 @@ public class NetworkDiagnostics { @Override public void run() { - // Check if this measurement has already failed during setup. - if (mMeasurement.finishTime > 0) { - // If the measurement failed during construction it didn't - // decrement the countdown latch; do so here. - mCountDownLatch.countDown(); - return; - } + if (ensureMeasurementNecessary()) return; try { setupSocket(SOCK_DGRAM, IPPROTO_UDP, TIMEOUT_SEND, TIMEOUT_RECV, @@ -550,12 +602,10 @@ public class NetworkDiagnostics { mMeasurement.recordFailure(e.toString()); return; } - mMeasurement.description += " src{" + getSocketAddressString() + "}"; // This needs to be fixed length so it can be dropped into the pre-canned packet. final String sixRandomDigits = String.valueOf(mRandom.nextInt(900000) + 100000); - mMeasurement.description += " qtype{" + mQueryType + "}" - + " qname{" + sixRandomDigits + "-android-ds.metric.gstatic.com}"; + appendDnsToMeasurementDescription(sixRandomDigits, mSocketAddress); // Build a trivial DNS packet. final byte[] dnsPacket = getDnsQueryPacket(sixRandomDigits); @@ -592,7 +642,7 @@ public class NetworkDiagnostics { close(); } - private byte[] getDnsQueryPacket(String sixRandomDigits) { + protected byte[] getDnsQueryPacket(String sixRandomDigits) { byte[] rnd = sixRandomDigits.getBytes(StandardCharsets.US_ASCII); return new byte[] { (byte) mRandom.nextInt(), (byte) mRandom.nextInt(), // [0-1] query ID @@ -611,5 +661,97 @@ public class NetworkDiagnostics { 0, 1 // QCLASS, set to 1 = IN (Internet) }; } + + protected void appendDnsToMeasurementDescription( + String sixRandomDigits, SocketAddress sockAddr) { + mMeasurement.description += " src{" + socketAddressToString(sockAddr) + "}" + + " qtype{" + mQueryType + "}" + + " qname{" + sixRandomDigits + "-android-ds.metric.gstatic.com}"; + } + } + + // TODO: Have it inherited from SimpleSocketCheck, and separate common DNS helpers out of + // DnsUdpCheck. + private class DnsTlsCheck extends DnsUdpCheck { + private static final int TCP_CONNECT_TIMEOUT_MS = 2500; + private static final int TCP_TIMEOUT_MS = 2000; + private static final int DNS_TLS_PORT = 853; + private static final int DNS_HEADER_SIZE = 12; + + private final String mHostname; + + public DnsTlsCheck(@Nullable String hostname, @NonNull InetAddress target, + @NonNull Measurement measurement) { + super(target, measurement); + + mHostname = hostname; + mMeasurement.description = "DNS TLS dst{" + mTarget.getHostAddress() + "} hostname{" + + TextUtils.emptyIfNull(mHostname) + "}"; + } + + private SSLSocket setupSSLSocket() throws IOException { + // A TrustManager will be created and initialized with a KeyStore containing system + // CaCerts. During SSL handshake, it will be used to validate the certificates from + // the server. + SSLSocket sslSocket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(); + sslSocket.setSoTimeout(TCP_TIMEOUT_MS); + + if (!TextUtils.isEmpty(mHostname)) { + // Set SNI. + final List names = + Collections.singletonList(new SNIHostName(mHostname)); + SSLParameters params = sslSocket.getSSLParameters(); + params.setServerNames(names); + sslSocket.setSSLParameters(params); + } + + mNetwork.bindSocket(sslSocket); + return sslSocket; + } + + private void sendDoTProbe(@Nullable SSLSocket sslSocket) throws IOException { + final String sixRandomDigits = String.valueOf(mRandom.nextInt(900000) + 100000); + final byte[] dnsPacket = getDnsQueryPacket(sixRandomDigits); + + mMeasurement.startTime = now(); + sslSocket.connect(new InetSocketAddress(mTarget, DNS_TLS_PORT), TCP_CONNECT_TIMEOUT_MS); + + // Synchronous call waiting for the TLS handshake complete. + sslSocket.startHandshake(); + appendDnsToMeasurementDescription(sixRandomDigits, sslSocket.getLocalSocketAddress()); + + final DataOutputStream output = new DataOutputStream(sslSocket.getOutputStream()); + output.writeShort(dnsPacket.length); + output.write(dnsPacket, 0, dnsPacket.length); + + final DataInputStream input = new DataInputStream(sslSocket.getInputStream()); + final int replyLength = Short.toUnsignedInt(input.readShort()); + final byte[] reply = new byte[replyLength]; + int bytesRead = 0; + while (bytesRead < replyLength) { + bytesRead += input.read(reply, bytesRead, replyLength - bytesRead); + } + + if (bytesRead > DNS_HEADER_SIZE && bytesRead == replyLength) { + mMeasurement.recordSuccess("1/1 " + responseCodeStr((int) (reply[3]) & 0x0f)); + } else { + mMeasurement.recordFailure("1/1 Read " + bytesRead + " bytes while expected to be " + + replyLength + " bytes"); + } + } + + @Override + public void run() { + if (ensureMeasurementNecessary()) return; + + // No need to restore the tag, since this thread is only used for this measurement. + TrafficStats.getAndSetThreadStatsTag(TrafficStatsConstants.TAG_SYSTEM_PROBE); + + try (SSLSocket sslSocket = setupSSLSocket()) { + sendDoTProbe(sslSocket); + } catch (IOException e) { + mMeasurement.recordFailure(e.toString()); + } + } } } diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java index 0a603b8e4b..26a28da975 100644 --- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java @@ -62,6 +62,8 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.util.MessageUtils; import com.android.internal.util.test.FakeSettingsProvider; +import libcore.net.InetAddressUtils; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -379,4 +381,49 @@ public class DnsManagerTest { assertEquals(name, dnsTransTypes.get(i)); } } + + @Test + public void testGetPrivateDnsConfigForNetwork() throws Exception { + final Network network = new Network(TEST_NETID); + final InetAddress dnsAddr = InetAddressUtils.parseNumericAddress("3.3.3.3"); + final InetAddress[] tlsAddrs = new InetAddress[]{ + InetAddressUtils.parseNumericAddress("6.6.6.6"), + InetAddressUtils.parseNumericAddress("2001:db8:66:66::1") + }; + final String tlsName = "strictmode.com"; + LinkProperties lp = new LinkProperties(); + lp.addDnsServer(dnsAddr); + + // The PrivateDnsConfig map is empty, so the default PRIVATE_DNS_OFF is returned. + PrivateDnsConfig privateDnsCfg = mDnsManager.getPrivateDnsConfig(network); + assertFalse(privateDnsCfg.useTls); + assertEquals("", privateDnsCfg.hostname); + assertEquals(new InetAddress[0], privateDnsCfg.ips); + + // An entry with default PrivateDnsConfig is added to the PrivateDnsConfig map. + mDnsManager.updatePrivateDns(network, mDnsManager.getPrivateDnsConfig()); + mDnsManager.noteDnsServersForNetwork(TEST_NETID, lp); + mDnsManager.updatePrivateDnsValidation( + new DnsManager.PrivateDnsValidationUpdate(TEST_NETID, dnsAddr, "", true)); + mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); + privateDnsCfg = mDnsManager.getPrivateDnsConfig(network); + assertTrue(privateDnsCfg.useTls); + assertEquals("", privateDnsCfg.hostname); + assertEquals(new InetAddress[0], privateDnsCfg.ips); + + // The original entry is overwritten by a new PrivateDnsConfig. + mDnsManager.updatePrivateDns(network, new PrivateDnsConfig(tlsName, tlsAddrs)); + mDnsManager.updatePrivateDnsStatus(TEST_NETID, lp); + privateDnsCfg = mDnsManager.getPrivateDnsConfig(network); + assertTrue(privateDnsCfg.useTls); + assertEquals(tlsName, privateDnsCfg.hostname); + assertEquals(tlsAddrs, privateDnsCfg.ips); + + // The network is removed, so the PrivateDnsConfig map becomes empty again. + mDnsManager.removeNetwork(network); + privateDnsCfg = mDnsManager.getPrivateDnsConfig(network); + assertFalse(privateDnsCfg.useTls); + assertEquals("", privateDnsCfg.hostname); + assertEquals(new InetAddress[0], privateDnsCfg.ips); + } } From 8fb860bfe1c9f55e8902fe9b3282a1f5d37fe378 Mon Sep 17 00:00:00 2001 From: Ken Chen Date: Mon, 22 Jun 2020 20:39:49 +0800 Subject: [PATCH 225/229] Update DnsManagerTest for AIDL interface change Check one more parameter enforceDnsUid in ResolverOptionsParcel in DnsManagerTest. Bug: 159587277 Test: atest com.android.server.connectivity.DnsManagerTest#testSendDnsConfiguration Change-Id: Ic53f42b968626294c851dac252a70769846ba427 --- .../java/com/android/server/connectivity/DnsManagerTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java index 0a603b8e4b..7cdffc650a 100644 --- a/tests/net/java/com/android/server/connectivity/DnsManagerTest.java +++ b/tests/net/java/com/android/server/connectivity/DnsManagerTest.java @@ -103,7 +103,8 @@ public class DnsManagerTest { @NonNull ResolverOptionsParcel expected) { assertEquals(actual.hosts, expected.hosts); assertEquals(actual.tcMode, expected.tcMode); - assertFieldCountEquals(2, ResolverOptionsParcel.class); + assertEquals(actual.enforceDnsUid, expected.enforceDnsUid); + assertFieldCountEquals(3, ResolverOptionsParcel.class); } private void assertResolverParamsEquals(@NonNull ResolverParamsParcel actual, From c206662f5bae8b49cf6aff8f0f202dccb801225d Mon Sep 17 00:00:00 2001 From: Orion Hodson Date: Tue, 2 Jun 2020 13:22:06 +0100 Subject: [PATCH 226/229] Update to use nativehelper/JNIPlatformHelp.h Reflects refactoring of JNI helper code that depends on private methods within libnativehelper. Bug: 151443957 Test: Treehugger Change-Id: I7af128f42ae89a77a8e3fb113ea533331153c535 Merged-In: I7af128f42ae89a77a8e3fb113ea533331153c535 Exempt-From-Owner-Approval: cherry pick (cherry picked from commit 329c612e3d5ae440bf13e1f5fc9a4012263524e9) --- core/jni/android_net_NetUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index d4805acb06..e56809f66d 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -30,7 +30,7 @@ #include // NETID_USE_LOCAL_NAMESERVERS #include #include -#include +#include #include #include #include From b9128f36a5513215981085edf01d17e28b0a225f Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 26 Jun 2020 07:48:13 +0000 Subject: [PATCH 227/229] Send ConnDiags event before revalidating network in CS. This change updates ConnectivityService to notify the ConnectivityDiagnosticsHandler of app-reported connectivity before attempting to revalidate the network. This change forces an ordering on Connectivity Diagnostics events in the case that the reported connectivity does not match the known connectivity for the network - this leads to the network being revalidated and the ConnectivityDiagnostics event onConnectivityReportAvailable. Passing the onNetworkConnectivityReported event to the ConnectivityDiagnosticsHandler first ensures that it is passed to callbacks before any potential ConnectivityReports are. Bug: 159718782 Test: android.net.cts.ConnectivityDiagnosticsManagerTest Original-Change: https://android-review.googlesource.com/1350662 Merged-In: Ic7bc7138c54c47bbfdf56af5811709fde66f8606 Change-Id: Ic7bc7138c54c47bbfdf56af5811709fde66f8606 --- .../java/com/android/server/ConnectivityService.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 01b2e691d4..77cd5d2ffd 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -4323,9 +4323,11 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceInternetPermission(); final int uid = Binder.getCallingUid(); final int connectivityInfo = encodeBool(hasConnectivity); - mHandler.sendMessage( - mHandler.obtainMessage(EVENT_REVALIDATE_NETWORK, uid, connectivityInfo, network)); + // Handle ConnectivityDiagnostics event before attempting to revalidate the network. This + // forces an ordering of ConnectivityDiagnostics events in the case where hasConnectivity + // does not match the known connectivity of the network - this causes NetworkMonitor to + // revalidate the network and generate a ConnectivityDiagnostics ConnectivityReport event. final NetworkAgentInfo nai; if (network == null) { nai = getDefaultNetwork(); @@ -4338,6 +4340,9 @@ public class ConnectivityService extends IConnectivityManager.Stub ConnectivityDiagnosticsHandler.EVENT_NETWORK_CONNECTIVITY_REPORTED, connectivityInfo, 0, nai)); } + + mHandler.sendMessage( + mHandler.obtainMessage(EVENT_REVALIDATE_NETWORK, uid, connectivityInfo, network)); } private void handleReportNetworkConnectivity( From 9aa3127449c85227e2e75c9e6ce36eb7def402fe Mon Sep 17 00:00:00 2001 From: Chalard Jean Date: Wed, 8 Jul 2020 05:38:59 +0000 Subject: [PATCH 228/229] Add some more public doc for MacAddress Bug: 140807677 Test: doc-only change Original-Change: https://android-review.googlesource.com/1354447 Merged-In: I0f6e59eda42fd92ec34db0e9bc2d26d2e83d41d0 Change-Id: I0f6e59eda42fd92ec34db0e9bc2d26d2e83d41d0 --- core/java/android/net/MacAddress.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java index 0e10c42e61..0eb3c1e8ad 100644 --- a/core/java/android/net/MacAddress.java +++ b/core/java/android/net/MacAddress.java @@ -38,7 +38,9 @@ import java.util.Arrays; * Representation of a MAC address. * * This class only supports 48 bits long addresses and does not support 64 bits long addresses. - * Instances of this class are immutable. + * Instances of this class are immutable. This class provides implementations of hashCode() + * and equals() that make it suitable for use as keys in standard implementations of + * {@link java.util.Map}. */ public final class MacAddress implements Parcelable { @@ -122,12 +124,22 @@ public final class MacAddress implements Parcelable { } /** + * Convert this MacAddress to a byte array. + * + * The returned array is in network order. For example, if this MacAddress is 1:2:3:4:5:6, + * the returned array is [1, 2, 3, 4, 5, 6]. + * * @return a byte array representation of this MacAddress. */ public @NonNull byte[] toByteArray() { return byteAddrFromLongAddr(mAddr); } + /** + * Returns a human-readable representation of this MacAddress. + * The exact format is implementation-dependent and should not be assumed to have any + * particular format. + */ @Override public @NonNull String toString() { return stringAddrFromLongAddr(mAddr); From 27748323825d6f63ad5a33f42c43fa0634b414da Mon Sep 17 00:00:00 2001 From: junyulai Date: Thu, 16 Jul 2020 13:48:09 +0800 Subject: [PATCH 229/229] Attribute data usage to virtual RAT type for 5G non-standalone mode Test: atest NetworkStatsSubscriptionsMonitorTest#test5g Bug: 160727498 Change-Id: I8753e68140c0993773017c9a49bd8a666a364071 Merged-In: I8753e68140c0993773017c9a49bd8a666a364071 (cherry-picked from ag/12167624) --- .../java/android/net/NetworkTemplateTest.kt | 7 ++- .../NetworkStatsSubscriptionsMonitorTest.java | 55 ++++++++++++++++++- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/tests/net/java/android/net/NetworkTemplateTest.kt b/tests/net/java/android/net/NetworkTemplateTest.kt index 5dd0fda4da..9ba56e44fe 100644 --- a/tests/net/java/android/net/NetworkTemplateTest.kt +++ b/tests/net/java/android/net/NetworkTemplateTest.kt @@ -26,6 +26,7 @@ import android.net.NetworkStats.METERED_ALL import android.net.NetworkStats.ROAMING_ALL import android.net.NetworkTemplate.MATCH_MOBILE import android.net.NetworkTemplate.MATCH_WIFI +import android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA import android.net.NetworkTemplate.NETWORK_TYPE_ALL import android.net.NetworkTemplate.buildTemplateMobileWithRatType import android.telephony.TelephonyManager @@ -145,11 +146,13 @@ class NetworkTemplateTest { assertParcelSane(templateWifi, 8) } - // Verify NETWORK_TYPE_ALL does not conflict with TelephonyManager#NETWORK_TYPE_* constants. + // Verify NETWORK_TYPE_* constants in NetworkTemplate do not conflict with + // TelephonyManager#NETWORK_TYPE_* constants. @Test - fun testNetworkTypeAll() { + fun testNetworkTypeConstants() { for (ratType in TelephonyManager.getAllNetworkTypes()) { assertNotEquals(NETWORK_TYPE_ALL, ratType) + assertNotEquals(NETWORK_TYPE_5G_NSA, ratType) } } } diff --git a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java index 058856dcd6..c91dfecf04 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java @@ -17,6 +17,7 @@ package com.android.server.net; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; @@ -29,7 +30,9 @@ import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.content.Context; +import android.net.NetworkTemplate; import android.os.Looper; +import android.telephony.NetworkRegistrationInfo; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; @@ -61,7 +64,6 @@ public final class NetworkStatsSubscriptionsMonitorTest { private static final String TEST_IMSI3 = "466929999999999"; @Mock private Context mContext; - @Mock private PhoneStateListener mPhoneStateListener; @Mock private SubscriptionManager mSubscriptionManager; @Mock private TelephonyManager mTelephonyManager; @Mock private Delegate mDelegate; @@ -215,4 +217,55 @@ public final class NetworkStatsSubscriptionsMonitorTest { verify(mTelephonyManager, times(2)).listen(any(), eq(PhoneStateListener.LISTEN_NONE)); assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); } + + + @Test + public void test5g() { + mMonitor.start(); + // Insert sim1, verify RAT type is NETWORK_TYPE_UNKNOWN, and never get any callback + // before changing RAT type. Also capture listener for later use. + addTestSub(TEST_SUBID1, TEST_IMSI1); + assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN); + final ArgumentCaptor ratTypeListenerCaptor = + ArgumentCaptor.forClass(RatTypeListener.class); + verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(), + eq(PhoneStateListener.LISTEN_SERVICE_STATE)); + final RatTypeListener listener = CollectionUtils + .find(ratTypeListenerCaptor.getAllValues(), it -> it.getSubId() == TEST_SUBID1); + assertNotNull(listener); + + // Set RAT type to 5G NSA (non-standalone) mode, verify the monitor outputs + // NETWORK_TYPE_5G_NSA. + final ServiceState serviceState = mock(ServiceState.class); + when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_LTE); + when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED); + listener.onServiceStateChanged(serviceState); + assertRatTypeChangedForSub(TEST_IMSI1, NetworkTemplate.NETWORK_TYPE_5G_NSA); + reset(mDelegate); + + // Set RAT type to LTE without NR connected, the RAT type should be downgraded to LTE. + when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_NONE); + listener.onServiceStateChanged(serviceState); + assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_LTE); + reset(mDelegate); + + // Verify NR connected with other RAT type does not take effect. + when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_UMTS); + when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED); + listener.onServiceStateChanged(serviceState); + assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS); + reset(mDelegate); + + // Set RAT type to 5G standalone mode, the RAT type should be NR. + setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1, + TelephonyManager.NETWORK_TYPE_NR); + assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR); + reset(mDelegate); + + // Set NR state to none in standalone mode does not change anything. + when(serviceState.getDataNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_NR); + when(serviceState.getNrState()).thenReturn(NetworkRegistrationInfo.NR_STATE_NONE); + listener.onServiceStateChanged(serviceState); + assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR); + } }